diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 616f00120c..32731fe00e 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -194,6 +194,9 @@ DISSECTOR_SRC = \ packet-dcerpc-wkssvc.c \ packet-dcerpc.c \ packet-dcm.c \ + packet-dcom.c \ + packet-dcom-cba.c \ + packet-dcom-cba-acco.c \ packet-ddtp.c \ packet-dec-bpdu.c \ packet-dhcp-failover.c \ @@ -599,6 +602,7 @@ DISSECTOR_INCLUDES = \ packet-dcerpc-tapi.h \ packet-dcerpc-wkssvc.h \ packet-dcerpc.h \ + packet-dcom.h \ packet-ddtp.h \ packet-diameter-defs.h \ packet-diffserv-mpls-common.h \ diff --git a/epan/dissectors/packet-dcerpc.c b/epan/dissectors/packet-dcerpc.c index 85de5dbf52..5a2cf84870 100644 --- a/epan/dissectors/packet-dcerpc.c +++ b/epan/dissectors/packet-dcerpc.c @@ -666,6 +666,28 @@ dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver, hf_info->strings = value_string_from_subdissectors(procs); } + +/* try to get registered name for this uuid */ +gchar *dcerpc_get_uuid_name(e_uuid_t *uuid, guint16 ver) +{ + dcerpc_uuid_key key; + dcerpc_uuid_value *sub_proto; + + + /* try to get registered uuid "name" of if_id */ + key.uuid = *uuid; + key.ver = ver; + + if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) != NULL + && proto_is_protocol_enabled(sub_proto->proto)) { + + return sub_proto->name; + } + + return NULL; +} + + /* Function to find the name of a registered protocol * or NULL if the protocol/version is not known to ethereal. */ @@ -2290,7 +2312,7 @@ dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo, } offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, ctx_tree, hdr->drep, - hf_dcerpc_cn_num_trans_items, &num_trans_items); + hf_dcerpc_cn_num_trans_items, &num_trans_items); /* padding */ offset += 1; @@ -2843,7 +2865,7 @@ dcerpc_add_conv_to_bind_table(decode_dcerpc_bind_values_t *binding) binding->port_a, binding->port_b, 0); - + if (!conv) { conv = conversation_new ( &binding->addr_a, @@ -2853,7 +2875,7 @@ dcerpc_add_conv_to_bind_table(decode_dcerpc_bind_values_t *binding) binding->port_b, 0); } - + bind_value = g_mem_chunk_alloc (dcerpc_bind_value_chunk); bind_value->uuid = binding->uuid; bind_value->ver = binding->ver; @@ -3971,23 +3993,23 @@ dissect_dcerpc_dg_stub (tvbuff_t *tvb, int offset, packet_info *pinfo, hdr->seqnum, &hdr->act_id, dcerpc_cl_reassemble_table, hdr->frag_num, stub_length, !(hdr->flags1 & PFCL1_LASTFRAG)); - if (fd_head != NULL) { + if (fd_head != NULL) { /* We completed reassembly... */ if(pinfo->fd->num==fd_head->reassembled_in) { /* ...and this is the reassembled RPC PDU */ - next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len); - tvb_set_child_real_data_tvbuff(tvb, next_tvb); - add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC"); - show_fragment_seq_tree(fd_head, &dcerpc_frag_items, - dcerpc_tree, pinfo, next_tvb); + next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len); + tvb_set_child_real_data_tvbuff(tvb, next_tvb); + add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC"); + show_fragment_seq_tree(fd_head, &dcerpc_frag_items, + dcerpc_tree, pinfo, next_tvb); - /* - * XXX - authentication info? - */ - pinfo->fragmented = FALSE; - dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb, - next_tvb, hdr->drep, di, NULL); - } else { + /* + * XXX - authentication info? + */ + pinfo->fragmented = FALSE; + dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb, + next_tvb, hdr->drep, di, NULL); + } else { /* ...and this isn't the reassembled RPC PDU */ pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in, tvb, 0, 0, fd_head->reassembled_in); @@ -4822,7 +4844,7 @@ proto_register_dcerpc (void) NULL, 0, "Time between Request and Response for DCE-RPC calls", HFILL }}, { &hf_dcerpc_reassembled_in, - { "Reassembled PDU in frame", "dcerpc.reassembled_in", FT_FRAMENUM, BASE_NONE, + { "Reassembled PDU in frame", "dcerpc.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "The DCE/RPC PDU is completely reassembled in the packet with this number", HFILL }}, { &hf_dcerpc_unknown_if_id, diff --git a/epan/dissectors/packet-dcerpc.h b/epan/dissectors/packet-dcerpc.h index 875eadc182..ce1b45dc42 100644 --- a/epan/dissectors/packet-dcerpc.h +++ b/epan/dissectors/packet-dcerpc.h @@ -224,6 +224,9 @@ dcerpc_sub_dissector *dcerpc_get_proto_sub_dissector(e_uuid_t *uuid, guint16 ver value_string *value_string_from_subdissectors(dcerpc_sub_dissector *sd); +/* try to get protocol name registered for this uuid */ +gchar *dcerpc_get_uuid_name(e_uuid_t *uuid, guint16 ver); + /* Private data structure to pass to DCERPC dissector. This is used to pass transport specific information down to the dissector from the dissector that parsed this encapsulated calls. diff --git a/epan/dissectors/packet-dcom-cba-acco.c b/epan/dissectors/packet-dcom-cba-acco.c new file mode 100644 index 0000000000..85f52a24a5 --- /dev/null +++ b/epan/dissectors/packet-dcom-cba-acco.c @@ -0,0 +1,2916 @@ +/* packet-dcom-cba-acco.c + * Routines for DCOM CBA + * + * $Id$ + * + * Ethereal - 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + + +#include +#include +#include "packet-dcerpc.h" +#include "packet-dcom.h" + +static int hf_cba_acco_opnum = -1; + +static int hf_cba_acco_ping_factor = -1; + +static int hf_cba_acco_count = -1; + +static int hf_cba_acco_item = -1; +static int hf_cba_acco_data = -1; +static int hf_cba_acco_qc = -1; +static int hf_cba_acco_time_stamp = -1; + +static int hf_cba_acco_conn_qos_type = -1; +static int hf_cba_acco_conn_qos_value = -1; +static int hf_cba_acco_conn_state = -1; +static int hf_cba_acco_conn_cons_id = -1; +static int hf_cba_acco_conn_version = -1; +static int hf_cba_acco_conn_prov_id = -1; +static int hf_cba_acco_conn_provider = -1; +static int hf_cba_acco_conn_consumer = -1; +static int hf_cba_acco_conn_provider_item = -1; +static int hf_cba_acco_conn_consumer_item = -1; +static int hf_cba_acco_conn_substitute = -1; +static int hf_cba_acco_conn_epsilon = -1; +static int hf_cba_acco_conn_persist = -1; + +static int hf_cba_acco_cb_length = -1; +static int hf_cba_acco_cb_conn_data = -1; +static int hf_cba_acco_cb_version = -1; +static int hf_cba_acco_cb_flags = -1; +static int hf_cba_acco_cb_count = -1; +static int hf_cba_acco_cb_item = -1; +static int hf_cba_acco_cb_item_hole = -1; +static int hf_cba_acco_cb_item_length = -1; +static int hf_cba_acco_cb_item_data = -1; + +static int hf_cba_acco_server_pICBAAccoCallback = -1; + +static int hf_cba_acco_server_first_connect = -1; + +static int hf_cba_acco_serversrt_prov_mac = -1; +static int hf_cba_acco_serversrt_cons_mac = -1; + +static int hf_cba_acco_serversrt_cr_id = -1; +static int hf_cba_acco_serversrt_cr_length = -1; +static int hf_cba_acco_serversrt_cr_flags = -1; +static int hf_cba_acco_serversrt_cr_flags_timestamped = -1; +static int hf_cba_acco_serversrt_cr_flags_reconfigure = -1; +static int hf_cba_acco_serversrt_record_length = -1; +static int hf_cba_acco_serversrt_action = -1; +static int hf_cba_acco_serversrt_last_connect = -1; + +static int hf_cba_getprovconnout = -1; + +static int hf_cba_type_desc_len = -1; + +static int hf_cba_connectincr = -1; +static int hf_cba_connectoutcr = -1; +static int hf_cba_connectin = -1; +static int hf_cba_connectout = -1; +static int hf_cba_getconnectionout = -1; +static int hf_cba_readitemout = -1; +static int hf_cba_writeitemin = -1; +static int hf_cba_addconnectionin = -1; +static int hf_cba_addconnectionout = -1; +static int hf_cba_getidout = -1; + +static int hf_cba_getconsconnout = -1; +static int hf_cba_diagconsconnout = -1; +static int hf_cba_acco_conn_error_state = -1; + +static int hf_cba_acco_server_cb_pointer = -1; + +static int hf_cba_acco_info_max = -1; +static int hf_cba_acco_info_curr = -1; + +static int hf_cba_acco_cdb_cookie = -1; + +static int hf_cba_acco_rtauto = -1; + +static int hf_cba_acco_prov_crid = -1; + + +gint ett_cba_connectincr = -1; +gint ett_cba_connectoutcr = -1; +gint ett_cba_connectin = -1; +gint ett_cba_connectout = -1; +gint ett_cba_getprovconnout = -1; +gint ett_cba_addconnectionin = -1; +gint ett_cba_addconnectionout = -1; +gint ett_cba_getidout = -1; +gint ett_cba_getconnectionout = -1; +gint ett_cba_readitemout = -1; +gint ett_cba_writeitemin = -1; +gint ett_cba_acco_serversrt_cr_flags = -1; + +static int proto_ICBAAccoMgt = -1; +static gint ett_ICBAAccoMgt = -1; +static e_uuid_t uuid_ICBAAccoMgt = { 0xcba00041, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoMgt = 0; + +static int proto_ICBAAccoMgt2 = -1; +static e_uuid_t uuid_ICBAAccoMgt2 = { 0xcba00046, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoMgt2 = 0; + +static int proto_ICBAAccoCallback = -1; +static gint ett_ICBAAccoCallback = -1; +static gint ett_ICBAAccoCallback_Buffer = -1; +static gint ett_ICBAAccoCallback_Item = -1; +static e_uuid_t uuid_ICBAAccoCallback = { 0xcba00042, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoCallback = 0; + +static int proto_ICBAAccoCallback2 = -1; +static e_uuid_t uuid_ICBAAccoCallback2 = { 0xcba00047, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoCallback2 = 0; + +static int proto_ICBAAccoServer = -1; +static gint ett_ICBAAccoServer = -1; +static e_uuid_t uuid_ICBAAccoServer = { 0xcba00043, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoServer = 0; + +static int proto_ICBAAccoServer2 = -1; +static e_uuid_t uuid_ICBAAccoServer2 = { 0xcba00048, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoServer2 = 0; + +static int proto_ICBAAccoServerSRT = -1; +static gint ett_ICBAAccoServerSRT = -1; +static e_uuid_t uuid_ICBAAccoServerSRT = { 0xcba00045, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoServerSRT = 0; + +static int proto_ICBAAccoSync = -1; +static gint ett_ICBAAccoSync = -1; +static e_uuid_t uuid_ICBAAccoSync = { 0xcba00044, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoSync = 0; + + + +static const value_string cba_acco_qc_vals[] = { + { 0x44, "UncertainLastUsableValue" }, + { 0x48, "UncertainSubstituteSet" }, + { 0x50, "UncertainSensorNotAccurate" }, + { 0x80, "GoodNonCascOk" }, + { 0, NULL } +}; + + +static const value_string cba_qos_type_vals[] = { + { 0x00, "Acyclic" }, + { 0x01, "Acyclic seconds" }, /* obsolete */ + { 0x02, "Acyclic status" }, + { 0x03, "Acyclic HMI" }, + { 0x20, "Constant" }, + { 0x30, "Cyclic Real-Time" }, + { 0, NULL } +}; + + +static const value_string cba_persist_vals[] = { + { 0x00, "Volatile" }, + { 0x01, "PendingPersistent" }, + { 0x02, "Persistent" }, + { 0, NULL } +}; + + +static const value_string cba_acco_conn_state_vals[] = { + { 0x00, "Passive" }, + { 0x01, "Active" }, + { 0, NULL } +}; + +static const value_string cba_acco_serversrt_action_vals[] = { + { 0x00, "Activate" }, + { 0x01, "Deactivate" }, + { 0x02, "Remove" }, + { 0, NULL } +}; + +static const value_string cba_acco_serversrt_last_connect_vals[] = { + { 0x00, "CR not complete" }, + { 0x01, "CR complete" }, + { 0, NULL } +}; + + +/* dissect a response containing an array of hresults (e.g: ICBAAccoMgt::RemoveConnections) */ +static int +dissect_HResultArray_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32HResult; + guint32 u32Pointer; + guint32 u32ArraySize = 0; + guint32 u32Idx; + guint32 u32Tmp; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Idx = 1; + u32Tmp = u32ArraySize; + while (u32Tmp--) { + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult, u32Idx); + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u -> %s", + u32ArraySize, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_ICBAAccoServer_Connect_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8State; + guint32 u32Count; + guint32 u32ArraySize; + + guint32 u32VariableOffset; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32Pointer; + guint16 u16VarType; + guint32 u32ConsID; + gchar szItem[1000] = { 0 }; + guint32 u32MaxItemLen = sizeof(szItem); + gchar szCons[1000] = { 0 }; + guint32 u32MaxConsLen = sizeof(szCons); + guint32 u32Idx; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_consumer, szCons, u32MaxConsLen); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + offset = dissect_dcom_BYTE(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize*16; + + /* array of CONNECTINs */ + u32Idx = 1; + while (u32ArraySize--) { + sub_item = proto_tree_add_item(tree, hf_cba_connectin, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectin); + u32SubStart = offset; + + /* ProviderItem */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_provider_item, szItem, u32MaxItemLen); + } + + /* DataType */ + offset = dissect_dcom_VARTYPE(tvb, offset, pinfo, sub_tree, drep, + &u16VarType); + + /* Epsilon */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_epsilon); + } + /* ConsumerID */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_cons_id, &u32ConsID); + + /* update subtree header */ + proto_item_append_text(sub_item, "[%u]: ConsID=0x%x, ProvItem=\"%s\", VarType=%s", + u32Idx, u32ConsID, szItem, + val_to_str(u16VarType, dcom_variant_type_vals, "Unknown (0x%04x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + return u32VariableOffset; +} + +static int +dissect_ICBAAccoServer2_Connect2_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8State; + guint32 u32Count; + guint32 u32ArraySize; + + guint32 u32VariableOffset; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32Pointer; + guint16 u16VarType; + guint32 u32ConsID; + gchar szItem[1000] = { 0 }; + guint32 u32MaxItemLen = sizeof(szItem); + gchar szCons[1000] = { 0 }; + guint32 u32MaxConsLen = sizeof(szCons); + guint32 u32Idx; + guint16 u16TypeDescLen; + guint32 u32ArraySize2; + guint32 u32Idx2; + guint16 u16VarType2; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_consumer, szCons, u32MaxConsLen); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + offset = dissect_dcom_BYTE(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize*20; + + /* array of CONNECTINs */ + u32Idx = 1; + while (u32ArraySize--) { + sub_item = proto_tree_add_item(tree, hf_cba_connectin, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectin); + u32SubStart = offset; + + /* ProviderItem */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_provider_item, szItem, u32MaxItemLen); + } + + /* TypeDescLen */ + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_type_desc_len, &u16TypeDescLen); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + /* pTypeDesc */ + if (u32Pointer) { + u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, drep, + &u32ArraySize2); + + /* extended type description will build an array here */ + u32Idx2 = 1; + while (u32ArraySize2--) { + /* ToBeDone: some of the type description values are counts */ + u32VariableOffset = dissect_dcom_VARTYPE(tvb, u32VariableOffset, pinfo, sub_tree, drep, + &u16VarType); + /* remember first VarType only */ + if (u32Idx2 == 1) { + u16VarType2 = u16VarType; + } + u32Idx2++; + } + } + + /* Epsilon */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_epsilon); + } + /* ConsumerID */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_cons_id, &u32ConsID); + + /* update subtree header */ + proto_item_append_text(sub_item, "[%u]: ConsID=0x%x, ProvItem=\"%s\", TypeDesc=%s", + u32Idx, u32ConsID, szItem, + val_to_str(u16VarType2, dcom_variant_type_vals, "Unknown (0x%04x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoServer_Connect_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint8 u8FirstConnect; + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32HResult; + guint32 u32Idx; + guint32 u32ProvID; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, tree, drep, + hf_cba_acco_server_first_connect, &u8FirstConnect); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + /* array of CONNECTOUTs */ + u32Idx = 1; + while(u32ArraySize--) { + sub_item = proto_tree_add_item(tree, hf_cba_connectout, tvb, offset, 8, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectout); + u32SubStart = offset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_prov_id, &u32ProvID); + + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: ProvID=0x%x %s", + u32Idx, u32ProvID, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s Cnt=%u -> %s", + (u8FirstConnect) ? "First" : "NotFirst", + u32Idx-1, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_Server_ProvIDs_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ProvID; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_prov_id, &u32ProvID, u32Idx); + u32Idx++; + } + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + return offset; +} + + +static int +dissect_Server_Consumer_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_consumer, szStr, u32MaxStr); + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Consumer=\"%s\"", szStr); + } + + return offset; +} + + + +static int +dissect_ICBAAccoServer_SetActivation_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint8 u8State; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ProvID; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_prov_id, &u32ProvID, u32Idx); + u32Idx++; + } + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + return offset; +} + + +static int +dissect_ICBAAccoServer_Ping_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_consumer, szStr, u32MaxStr); + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Consumer=\"%s\"", szStr); + } + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_ConnectCR_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + gchar szCons[1000] = { 0 }; + guint32 u32MaxConsLen = sizeof(szCons); + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8ConsMac[6]; + guint16 u16CRID; + guint16 u16CRLength; + guint32 u32Flags; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + proto_item *item = NULL; + proto_tree *flags_tree = NULL; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + /* szCons */ + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_consumer, szCons, u32MaxConsLen); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0); + + /* ConsumerMAC (big-endian, 1byte-aligned) */ + tvb_memcpy(tvb, u8ConsMac, offset, 6); + + proto_tree_add_ether(tree, hf_cba_acco_serversrt_cons_mac, tvb, + offset, 6, u8ConsMac); + offset += 6; + + /* add flags subtree */ + u32Flags = tvb_get_guint8(tvb, offset); + item = proto_tree_add_uint_format(tree, hf_cba_acco_serversrt_cr_flags, + tvb, offset, 4, u32Flags, + "Flags: 0x%02x (%s, %s)", u32Flags, + (u32Flags & 0x1) ? "Timestamped" : "not Timestamped", + (u32Flags & 0x2) ? "Reconfigure" : "not Reconfigure"); + flags_tree = proto_item_add_subtree(item, ett_cba_acco_serversrt_cr_flags); + proto_tree_add_boolean(flags_tree, hf_cba_acco_serversrt_cr_flags_timestamped, tvb, offset, 4, u32Flags); + proto_tree_add_boolean(flags_tree, hf_cba_acco_serversrt_cr_flags_reconfigure, tvb, offset, 4, u32Flags); + offset += 4; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + /* array of CONNECTINCRs */ + sub_item = proto_tree_add_item(tree, hf_cba_connectincr, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectincr); + u32SubStart = offset; + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_serversrt_cr_id, &u16CRID); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_serversrt_cr_length, &u16CRLength); + + /* update subtree header */ + proto_item_append_text(sub_item, "[%u]: CRID=0x%x, CRLength=%u", + u32Idx, u16CRID, u16CRLength); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": %sConsCRID=0x%x Len=%u QoS=%u", + (u32Flags & 0x2) ? "Reco " : "", u16CRID, u16CRLength, u16QoSValue); + } + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_ConnectCR_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint8 u8FirstConnect; + guint8 u8ProvMac[6]; + guint32 u32ProvCRID; + guint32 u32HResult; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32Pointer; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, tree, drep, + hf_cba_acco_server_first_connect, &u8FirstConnect); + + /* ProviderMAC (big-endian, 1byte-aligned) */ + tvb_memcpy(tvb, u8ProvMac, offset, 6); + + proto_tree_add_ether(tree, hf_cba_acco_serversrt_prov_mac, tvb, + offset, 6, u8ProvMac); + offset += 6; + + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + /* array of CONNECTOUTCRs */ + sub_item = proto_tree_add_item(tree, hf_cba_connectoutcr, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectoutcr); + u32SubStart = offset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_prov_crid, &u32ProvCRID); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, drep, + &u32HResult); + + /* update subtree header */ + proto_item_append_text(sub_item, "[%u]: ProvCRID=0x%x, %s", + u32Idx, u32ProvCRID, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s PCRID=0x%x -> %s", + (u8FirstConnect) ? "FirstCR" : "NotFirstCR", + u32ProvCRID, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_DisconnectCR_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ProvCRID; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_prov_crid, &u32ProvCRID, u32Idx); + u32Idx++; + } + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_Connect_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32ProvCRID; + guint8 u8State; + guint8 u8LastConnect; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32VariableOffset; + guint32 u32Idx; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32Pointer; + gchar szProvItem[1000] = { 0 }; + guint32 u32MaxProvItemLen = sizeof(szProvItem); + guint16 u16TypeDescLen; + guint32 u32ArraySize2; + guint32 u32Idx2; + guint16 u16VarType2; + guint16 u16VarType; + guint32 u32ConsID; + guint16 u16RecordLength; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_prov_crid, &u32ProvCRID); + + offset = dissect_dcom_BYTE(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_BYTE(tvb, offset, pinfo, tree, drep, + hf_cba_acco_serversrt_last_connect, &u8LastConnect); + + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize*20; + + u32Idx = 1; + while (u32ArraySize--) { + /* array of CONNECTINs */ + sub_item = proto_tree_add_item(tree, hf_cba_connectin, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectin); + u32SubStart = offset; + + /* ProviderItem */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_provider_item, szProvItem, u32MaxProvItemLen); + } + + /* TypeDescLen */ + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_type_desc_len, &u16TypeDescLen); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + /* pTypeDesc */ + if (u32Pointer) { + u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, drep, + &u32ArraySize2); + + /* extended type description will build an array here */ + u32Idx2 = 1; + while (u32ArraySize2--) { + /* ToBeDone: some of the type description values are counts */ + u32VariableOffset = dissect_dcom_VARTYPE(tvb, u32VariableOffset, pinfo, sub_tree, drep, + &u16VarType); + /* remember first VarType only */ + if (u32Idx2 == 1) { + u16VarType2 = u16VarType; + } + u32Idx2++; + } + } + + /* ConsumerID */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_cons_id, &u32ConsID); + + /* RecordLength */ + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_serversrt_record_length, &u16RecordLength); + + /* update subtree header */ + proto_item_append_text(sub_item, "[%u]: ConsID=0x%x, ProvItem=\"%s\", TypeDesc=%s", + u32Idx, u32ConsID, szProvItem, + val_to_str(u16VarType2, dcom_variant_type_vals, "Unknown (0x%04x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + + u32Idx++; + } + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s Cnt=%u PCRID=0x%x", + (u8LastConnect) ? "LastOfCR" : "", + u32Idx-1, + u32ProvCRID); + } + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoServerSRT_Connect_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32Idx; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32ProvID; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + /* array of CONNECTOUTs */ + u32Idx = 1; + while(u32ArraySize--) { + sub_item = proto_tree_add_item(tree, hf_cba_connectout, tvb, offset, 8, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectout); + u32SubStart = offset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_prov_id, &u32ProvID); + + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: ProvID=0x%x %s", + u32Idx, u32ProvID, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u -> %s", + u32Idx-1, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_Server_GetProvIDs_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ProvID; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + if (check_col(pinfo->cinfo, COL_INFO)) { + if (u32Count) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u ProvID=", u32Count); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, + tree, drep, + hf_cba_acco_conn_prov_id, &u32ProvID, u32Idx); + + if (check_col(pinfo->cinfo, COL_INFO)) { + if (u32Idx == 1) { + col_append_fstr(pinfo->cinfo, COL_INFO, "0x%x", u32ProvID); + } else if (u32Idx < 10) { + col_append_fstr(pinfo->cinfo, COL_INFO, ",0x%x", u32ProvID); + } else if (u32Idx == 10) { + col_append_fstr(pinfo->cinfo, COL_INFO, ",..."); + } + } + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_Server_GetProvConnections_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32TmpCount; + guint32 u32Pointer; + guint32 u32VariableOffset; + guint32 u32Idx; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + gchar szCons[1000] = { 0 }; + guint32 u32MaxConsLen = sizeof(szCons); + gchar szProvItem[1000] = { 0 }; + guint32 u32MaxProvItemLen = sizeof(szProvItem); + guint32 u32ConsID; + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8State; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + + u32VariableOffset = offset; + + if (u32Pointer) { + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + u32VariableOffset = offset + u32Count*28; + + /* array fixed part (including pointers to variable part) */ + u32TmpCount = u32Count; + u32Idx = 1; + while (u32TmpCount--) { + sub_item = proto_tree_add_item(tree, hf_cba_getprovconnout, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_getprovconnout); + u32SubStart = offset; + + /* wszConsumer */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_consumer, szCons, u32MaxConsLen); + } + /* wszProviderItem */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_provider_item, szProvItem, u32MaxProvItemLen); + } + /* dwConsID */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_cons_id, &u32ConsID); + + /* Epsilon */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_epsilon); + } + + /* QoS Type */ + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + /* QoS Value */ + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + /* State */ + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_state, &u8State); + /* PartialResult */ + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: %s", + u32Idx, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + u32VariableOffset = dissect_dcom_HRESULT(tvb, u32VariableOffset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return u32VariableOffset; +} + + +#define CBA_MRSH_VERSION_DCOM 0x1 +#define CBA_MRSH_VERSION_SRT_WITH_CONSID 0x10 +#define CBA_MRSH_VERSION_SRT_WITHOUT_CONSID 0x11 + + +static int +dissect_CBA_Connection_Data(tvbuff_t *tvb, + packet_info *pinfo, proto_tree *tree) +{ + guint8 u8Version; + guint8 u8Flags; + guint16 u16CountFix; + guint16 u16Count; + guint32 u32ItemIdx; + guint32 u32HoleIdx; + proto_item *sub_item; + proto_tree *sub_tree; + proto_item *conn_data_item = NULL; + proto_tree *conn_data_tree = NULL; + guint16 u16Len; + guint32 u32ID; + guint8 u8QC; + guint16 u16DataLen; + guint16 u16HdrLen; + int offset = 0; + int offset_hole; +/* guint32 bTimeStamped = 0;*/ + + /*** ALL data in this buffer is NOT aligned and always little endian ordered ***/ + + if (tree) { + conn_data_item = proto_tree_add_item(tree, hf_cba_acco_cb_conn_data, tvb, offset, 0, FALSE); + conn_data_tree = proto_item_add_subtree(conn_data_item, ett_ICBAAccoCallback_Buffer); + } + + /* add buffer header */ + u8Version = tvb_get_guint8 (tvb, offset); + if (conn_data_tree) { + proto_tree_add_item(conn_data_tree, hf_cba_acco_cb_version, tvb, offset, 1, TRUE); + } + offset += 1; + + u8Flags = tvb_get_guint8 (tvb, offset); + if (conn_data_tree) { + proto_tree_add_item(conn_data_tree, hf_cba_acco_cb_flags, tvb, offset, 1, TRUE); + } + offset += 1; + + u16Count = tvb_get_letohs (tvb, offset); + if (conn_data_tree) { + proto_tree_add_item(conn_data_tree, hf_cba_acco_cb_count, tvb, offset, 2, TRUE); + } + offset += 2; + u16CountFix = u16Count; + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, " Cnt=%u", u16Count); + + /* is this an OnDataChanged buffer format (version), we know? */ + if (u8Version != CBA_MRSH_VERSION_DCOM && + u8Version != CBA_MRSH_VERSION_SRT_WITH_CONSID && + u8Version != CBA_MRSH_VERSION_SRT_WITHOUT_CONSID) + { + return offset; + } + + /* Timestamps are currently unused -> flags must be zero */ + if (u8Flags != 0) { + return offset; + } + + u32ItemIdx = 1; + u32HoleIdx = 1; + while (u16Count--) { + /* find next record header */ + u16Len = tvb_get_letohs (tvb, offset); + + /* trapped inside an empty hole? -> try to find next record header */ + if (u16Len == 0 && + (u8Version == CBA_MRSH_VERSION_SRT_WITH_CONSID || + u8Version == CBA_MRSH_VERSION_SRT_WITHOUT_CONSID)) + { + u32HoleIdx++; + offset_hole = offset; + /* length smaller or larger than possible -> must be a hole */ + while (u16Len == 0) { + offset++; + u16Len = tvb_get_letohs(tvb, offset); + /* this is a bit tricky here! we know: */ + /* u16Len must be greater than 3 (min. size of header itself) */ + /* u16Len must be a lot smaller than 0x300 (max. size of frame) */ + /* -> if we found a length larger than 0x300, */ + /* this must be actually the high byte, so do one more step */ + if (u16Len > 0x300) { + u16Len = 0; + } + } + proto_tree_add_none_format(conn_data_tree, hf_cba_acco_cb_item_hole, tvb, + offset_hole, offset - offset_hole, + "Hole(--): -------------, offset=%2u, length=%2u", + offset_hole, offset - offset_hole); + } + + /* add callback-item subtree */ + sub_item = proto_tree_add_item(conn_data_tree, hf_cba_acco_cb_item, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_ICBAAccoCallback_Item); + + /* add item header fields */ + if (sub_tree) { + proto_tree_add_item(sub_tree, hf_cba_acco_cb_item_length, tvb, offset, 2, TRUE); + } + offset += 2; + u16HdrLen = 2; + + if (u8Version == CBA_MRSH_VERSION_DCOM || + u8Version == CBA_MRSH_VERSION_SRT_WITH_CONSID) + { + u32ID = tvb_get_letohl (tvb, offset); + if (sub_tree) { + proto_tree_add_item(sub_tree, hf_cba_acco_conn_cons_id, tvb, offset, 4, TRUE); + } + offset += 4; + u16HdrLen += 4; + } else { + u32ID = 0; + } + + u8QC = tvb_get_guint8 (tvb, offset); + if (sub_tree) { + proto_tree_add_item(sub_tree, hf_cba_acco_qc, tvb, offset, 1, TRUE); + } + offset += 1; + u16HdrLen += 1; + + /* user data length is item length without headers */ + u16DataLen = u16Len - u16HdrLen; + + /* append text to subtree header */ + if (u8Version == CBA_MRSH_VERSION_DCOM || + u8Version == CBA_MRSH_VERSION_SRT_WITH_CONSID) + { + proto_item_append_text(sub_item, + "[%2u]: ConsID=0x%08x, offset=%2u, length=%2u (user-length=%2u), QC=%s (0x%02x)", + u32ItemIdx, u32ID, offset - u16HdrLen, u16Len, u16DataLen, + val_to_str(u8QC, cba_acco_qc_vals, "Unknown (0x%02x)"), u8QC ); + } else { + proto_item_append_text(sub_item, + "[%2u]: ConsID=-, offset=%2u, length=%2u (user-length=%2u), QC=%s (0x%02x)", + u32ItemIdx, offset - u16HdrLen, u16Len, u16DataLen, + val_to_str(u8QC, cba_acco_qc_vals, "Unknown (0x%02x)"), u8QC ); + } + proto_item_set_len(sub_item, u16Len); + + /* hexdump of user data */ + proto_tree_add_bytes(sub_tree, hf_cba_acco_cb_item_data, tvb, offset, u16DataLen, + tvb_get_ptr(tvb, offset, u16DataLen)); + offset += u16DataLen; + + u32ItemIdx++; + } + + if (u8Version == 1) { + proto_item_append_text(conn_data_item, + ": Version=0x%x (OnDataChanged), Flags=0x%x, Count=%u", + u8Version, u8Flags, u16CountFix); + } else { + proto_item_append_text(conn_data_item, + ": Version=0x%x (SRT), Flags=0x%x, Count=%u, Items=%u, Holes=%u", + u8Version, u8Flags, u16CountFix, u32ItemIdx-1, u32HoleIdx-1); + } + proto_item_set_len(conn_data_item, offset); + + return offset; +} + + +static gboolean +dissect_CBA_Connection_Data_heur(tvbuff_t *tvb, + packet_info *pinfo, proto_tree *tree) +{ + guint8 u8Version; + guint8 u8Flags; + guint16 u16FrameID; + + /* the tvb will NOT contain the frame_id here! */ + u16FrameID = GPOINTER_TO_UINT(pinfo->private_data); + + /* frame id must be in valid range (cyclic Real-Time, class=1) */ + if (u16FrameID < 0xc000 || u16FrameID >= 0xfb00) { + return FALSE; + } + + u8Version = tvb_get_guint8 (tvb, 0); + u8Flags = tvb_get_guint8 (tvb, 1); + + /* version and flags must be ok */ + if(u8Version != 0x11 || u8Flags != 0x00) { + return FALSE; + } + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_add_str(pinfo->cinfo, COL_PROTOCOL, "PN-CBA"); + + dissect_CBA_Connection_Data(tvb, pinfo, tree); + + return TRUE; +} + + +static int +dissect_ICBAAccoCallback_OnDataChanged_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Length; + guint32 u32ArraySize; + tvbuff_t *next_tvb; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + /* length */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_cb_length, &u32Length); + + /* array size */ + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + /*** the data below is NOT ndr encoded (especially NOT aligned)!!! ***/ + /* dissect PROFINET component data (without header) */ + next_tvb = tvb_new_subset(tvb, offset, -1, -1); + + offset += dissect_CBA_Connection_Data(next_tvb, pinfo, tree); + + /* XXX */ + /* tvb_free(next_tvb);*/ + + return offset; +} + + +static int +dissect_ICBAAccoServer2_GetConnectionData_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Length; + guint32 u32ArraySize; + tvbuff_t *next_tvb; + guint32 u32Pointer; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + /* length */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_cb_length, &u32Length); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + /* array size */ + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + /*** the data below is NOT ndr encoded (especially NOT aligned)!!! ***/ + /* dissect PROFINET component data (without header) */ + next_tvb = tvb_new_subset(tvb, offset, -1, -1); + + offset += dissect_CBA_Connection_Data(next_tvb, pinfo, tree); + + /* XXX */ + /* tvb_free(next_tvb);*/ + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_ICBAAccoMgt_AddConnections_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + gchar szConsumer[1000] = { 0 }; + guint32 u32MaxConsLen = sizeof(szConsumer); + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8State; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Pointer; + guint16 u16Persistence; + gchar szConsItem[1000] = { 0 }; + guint32 u32MaxConsItemLen = sizeof(szConsItem); + gchar szProvItem[1000] = { 0 }; + guint32 u32MaxProvItemLen = sizeof(szProvItem); + guint32 u32VariableOffset; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32Idx; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_provider, szConsumer, u32MaxConsLen); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize * 20; + + u32Idx = 1; + while (u32ArraySize--) { + sub_item = proto_tree_add_item(tree, hf_cba_addconnectionin, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_addconnectionin); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_provider_item, szProvItem, u32MaxProvItemLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_consumer_item, szConsItem, u32MaxConsItemLen); + } + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_persist, &u16Persistence); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_substitute); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_epsilon); + } + proto_item_append_text(sub_item, "[%u]: ConsItem=\"%s\" ProvItem=\"%s\" %s", + u32Idx, szConsItem, szProvItem, + val_to_str(u16Persistence, cba_persist_vals, "Unknown (0x%02x)"), u16Persistence); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Prov=\"%s\" State=%s Cnt=%u", + szConsumer, + val_to_str(u8State, cba_acco_conn_state_vals, "Unknown (0x%02x)"), + u32Count); + } + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoMgt_AddConnections_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32ConsID; + guint16 u16ConnVersion; + guint32 u32HResult; + guint32 u32Count; + guint32 u32Idx; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Count = u32ArraySize; + u32Idx = 1; + while (u32ArraySize--) { + sub_item = proto_tree_add_item(tree, hf_cba_addconnectionout, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_addconnectionout); + u32SubStart = offset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_cons_id, &u32ConsID); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_version, &u16ConnVersion); + + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: ConsID=0x%x Version=%u %s", + u32Idx, u32ConsID, u16ConnVersion, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + } + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u -> %s", + u32Count, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_ICBAAccoMgt_RemoveConnections_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ConsID; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_cons_id, &u32ConsID, u32Idx); + u32Idx++; + } + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + return offset; +} + + +static int +dissect_ICBAAccoMgt_SetActivationState_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint8 u8State; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ConsID; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_cons_id, &u32ConsID, u32Idx); + u32Idx++; + } + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + return offset; +} + + +static int +dissect_ICBAAccoMgt_GetInfo_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Max; + guint32 u32CurCnt; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_info_max, &u32Max); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_info_curr, &u32CurCnt); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, ": %u/%u -> %s", + u32CurCnt, u32Max, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_GetIDs_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32ConsID; + guint8 u8State; + guint16 u16Version; + guint32 u32HResult; + guint32 u32Idx; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + if (check_col(pinfo->cinfo, COL_INFO)) { + if (u32Count) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u ConsID=", u32Count); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + sub_item = proto_tree_add_item(tree, hf_cba_getidout, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_getidout); + u32SubStart = offset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_cons_id, &u32ConsID); + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_state, &u8State); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_version, &u16Version); + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: ConsID=0x%x State=%s Version=%u %s", + u32Idx, u32ConsID, + val_to_str(u8State, cba_acco_conn_state_vals, "Unknown (0x%02x)"), + u16Version, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + if (check_col(pinfo->cinfo, COL_INFO)) { + if (u32Idx == 1) { + col_append_fstr(pinfo->cinfo, COL_INFO, "0x%x", u32ConsID); + } else if (u32Idx < 10) { + col_append_fstr(pinfo->cinfo, COL_INFO, ",0x%x", u32ConsID); + } else if (u32Idx == 10) { + col_append_fstr(pinfo->cinfo, COL_INFO, ",..."); + } + } + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_ICBAAccoMgt2_GetConsIDs_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ConsID; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + if (check_col(pinfo->cinfo, COL_INFO)) { + if (u32Count) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u ConsID=", u32Count); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, + tree, drep, + hf_cba_acco_conn_cons_id, &u32ConsID, u32Idx); + + if (check_col(pinfo->cinfo, COL_INFO)) { + if (u32Idx == 1) { + col_append_fstr(pinfo->cinfo, COL_INFO, "0x%x", u32ConsID); + } else if (u32Idx < 10) { + col_append_fstr(pinfo->cinfo, COL_INFO, ",0x%x", u32ConsID); + } else if (u32Idx == 10) { + col_append_fstr(pinfo->cinfo, COL_INFO, ",..."); + } + } + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_ICBAAccoMgt2_GetConsConnections_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32TmpCount; + guint32 u32Pointer; + guint32 u32HResult; + + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8State; + guint16 u16Persistence; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32Idx; + guint32 u32VariableOffset; + gchar szProv[1000] = { 0 }; + guint32 u32MaxProvLen = sizeof(szProv); + gchar szProvItem[1000] = { 0 }; + guint32 u32MaxProvItemLen = sizeof(szProvItem); + gchar szConsItem[1000] = { 0 }; + guint32 u32MaxConsItemLen = sizeof(szConsItem); + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + + u32VariableOffset = offset; + + if (u32Pointer) { + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + u32VariableOffset = offset + u32Count*32; + + /* array fixed part (including pointers to variable part) */ + u32TmpCount = u32Count; + u32Idx = 1; + while (u32TmpCount--) { + sub_item = proto_tree_add_item(tree, hf_cba_getconsconnout, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_getconnectionout); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_provider, szProv, u32MaxProvLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_provider_item, szProvItem, u32MaxProvItemLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_consumer_item, szConsItem, u32MaxConsItemLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_substitute); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_epsilon); + } + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_state, &u8State); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_persist, &u16Persistence); + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: %s", + u32Idx, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + u32VariableOffset = dissect_dcom_HRESULT(tvb, u32VariableOffset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoMgt2_DiagConsConnections_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32TmpCount; + guint32 u32Pointer; + guint32 u32HResult; + guint8 u8State; + guint16 u16Persistence; + guint16 u16ConnVersion; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32Idx; + guint32 u32VariableOffset; + gchar szProv[1000] = { 0 }; + guint32 u32MaxProvLen = sizeof(szProv); + gchar szProvItem[1000] = { 0 }; + guint32 u32MaxProvItemLen = sizeof(szProvItem); + gchar szConsItem[1000] = { 0 }; + guint32 u32MaxConsItemLen = sizeof(szConsItem); + guint32 u32ConnErrorState; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + + u32VariableOffset = offset; + + if (u32Pointer) { + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + u32VariableOffset = offset + u32Count*16; + + /* array fixed part (including pointers to variable part) */ + u32TmpCount = u32Count; + u32Idx = 1; + while (u32TmpCount--) { + sub_item = proto_tree_add_item(tree, hf_cba_diagconsconnout, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_getconnectionout); + u32SubStart = offset; + + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_state, &u8State); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_persist, &u16Persistence); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_version, &u16ConnVersion); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_error_state, &u32ConnErrorState); + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: %s", + u32Idx, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + u32VariableOffset = dissect_dcom_HRESULT(tvb, u32VariableOffset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoMgt_GetConnections_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32ConsID; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--){ + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_cons_id, &u32ConsID, u32Idx); + u32Idx++; + } + + return offset; +} + + +static int +dissect_ICBAAccoMgt_GetConnections_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32TmpCount; + guint32 u32Pointer; + guint32 u32HResult; + + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8State; + guint16 u16Persistence; + guint16 u16ConnVersion; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32Idx; + guint32 u32VariableOffset; + gchar szProv[1000] = { 0 }; + guint32 u32MaxProvLen = sizeof(szProv); + gchar szProvItem[1000] = { 0 }; + guint32 u32MaxProvItemLen = sizeof(szProvItem); + gchar szConsItem[1000] = { 0 }; + guint32 u32MaxConsItemLen = sizeof(szConsItem); + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + + u32VariableOffset = offset; + + if (u32Pointer) { + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + u32VariableOffset = offset + u32Count*36; + + /* array fixed part (including pointers to variable part) */ + u32TmpCount = u32Count; + u32Idx = 1; + while (u32TmpCount--) { + sub_item = proto_tree_add_item(tree, hf_cba_getconnectionout, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_getconnectionout); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_provider, szProv, u32MaxProvLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_provider_item, szProvItem, u32MaxProvItemLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_consumer_item, szConsItem, u32MaxConsItemLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_substitute); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_conn_epsilon); + } + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_state, &u8State); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_persist, &u16Persistence); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_conn_version, &u16ConnVersion); + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: %s", + u32Idx, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + u32VariableOffset = dissect_dcom_HRESULT(tvb, u32VariableOffset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoMgt_ReviseQoS_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16QoSType; + guint16 u16QoSValue; + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, + hf_cba_acco_rtauto, szStr, u32MaxStr); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": RTAuto=\"%s\" QoSType=%s QoSValue=%u", + szStr, + val_to_str(u16QoSType, cba_qos_type_vals, "Unknown (0x%04x)"), + u16QoSValue); + } + + return offset; +} + + +static int +dissect_ICBAAccoMgt_ReviseQoS_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16QoSValue; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, ": %u -> %s", + u16QoSValue, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_get_PingFactor_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16PF; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_ping_factor, &u16PF); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, ": %u -> %s", + u16PF, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_put_PingFactor_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16PF; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_ping_factor, &u16PF); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, ": %u", u16PF); + + return offset; +} + + + +static int +dissect_ICBAAccoMgt_get_CDBCookie_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Cookie; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_cdb_cookie, &u32Cookie); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": CDBCookie=0x%x -> %s", + u32Cookie, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + + +static int +dissect_ICBAAccoSync_ReadItems_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32VariableOffset; + guint32 u32Idx; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize*4; + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_indexed_LPWSTR(tvb, u32VariableOffset, pinfo, tree, drep, + hf_cba_acco_item, szStr, u32MaxStr, u32Idx); + } + + u32Idx++; + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + return u32VariableOffset; +} + + + + +static int +dissect_ICBAAccoSync_ReadItems_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Pointer; + guint16 u16QC; + unsigned char pu64TimeStamp[8]; + guint32 u32ArraySize; + guint32 u32HResult; + guint32 u32Idx; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32VariableOffset; + guint32 u32Tmp; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + u32VariableOffset = offset; + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize * 20; + u32Idx = 1; + u32Tmp = u32ArraySize; + while(u32Tmp--) { + sub_item = proto_tree_add_item(tree, hf_cba_readitemout, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_readitemout); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, drep, hf_cba_acco_data); + } + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_qc, &u16QC); + offset = dissect_dcom_FILETIME(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_time_stamp, pu64TimeStamp); + + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: QC=%s (0x%02x) %s", + u32Idx, + val_to_str(u16QC, cba_acco_qc_vals, "Unknown"), + u16QC, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + u32VariableOffset = dissect_dcom_HRESULT(tvb, u32VariableOffset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u -> %s", + u32ArraySize, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoSync_WriteItems_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32ArraySize; + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + guint32 u32Pointer; + guint32 u32VariableOffset; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32Idx; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize * 8; + u32Idx = 1; + while(u32ArraySize--) { + sub_item = proto_tree_add_item(tree, hf_cba_writeitemin, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_writeitemin); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_item, szStr, u32MaxStr); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_data); + } + + proto_item_append_text(sub_item, "[%u]: Item=\"%s\"", u32Idx, szStr); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + return u32VariableOffset; +} + + + +static int +dissect_ICBAAccoSync_WriteItemsQCD_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32ArraySize; + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + guint32 u32Pointer; + guint32 u32VariableOffset; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32Idx; + guint16 u16QC; + unsigned char pu64TimeStamp[8]; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize * 20; + u32Idx = 1; + while(u32ArraySize--) { + sub_item = proto_tree_add_item(tree, hf_cba_writeitemin, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_writeitemin); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_item, szStr, u32MaxStr); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_cba_acco_data); + } + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_qc, &u16QC); + + offset = dissect_dcom_FILETIME(tvb, offset, pinfo, sub_tree, drep, + hf_cba_acco_time_stamp, pu64TimeStamp); + + proto_item_append_text(sub_item, "[%u]: Item=\"%s\" QC=%s (0x%02x)", + u32Idx, szStr, + val_to_str(u16QC, cba_acco_qc_vals, "Unknown"), u16QC); + + proto_item_set_len(sub_item, offset - u32SubStart); + u32Idx++; + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + return u32VariableOffset; +} + + + + + + +/* sub dissector table of ICBAAccoMgt / ICBAAccoMgt2 interface */ +static dcerpc_sub_dissector ICBAAccoMgt_dissectors[] = { + { 0, "QueryInterface", NULL, NULL}, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "AddConnections", dissect_ICBAAccoMgt_AddConnections_rqst, dissect_ICBAAccoMgt_AddConnections_resp }, + { 4, "RemoveConnections", dissect_ICBAAccoMgt_RemoveConnections_rqst, dissect_HResultArray_resp }, + { 5, "ClearConnections", dissect_dcom_simple_rqst, dissect_dcom_simple_resp }, + { 6, "SetActivationState", dissect_ICBAAccoMgt_SetActivationState_rqst, dissect_HResultArray_resp }, + { 7, "GetInfo", dissect_dcom_simple_rqst, dissect_ICBAAccoMgt_GetInfo_resp }, + { 8, "GetIDs", dissect_dcom_simple_rqst, dissect_ICBAAccoMgt_GetIDs_resp }, + { 9, "GetConnections", dissect_ICBAAccoMgt_GetConnections_rqst, dissect_ICBAAccoMgt_GetConnections_resp }, + {10, "ReviseQoS", dissect_ICBAAccoMgt_ReviseQoS_rqst, dissect_ICBAAccoMgt_ReviseQoS_resp }, + {11, "get_PingFactor", dissect_dcom_simple_rqst, dissect_ICBAAccoMgt_get_PingFactor_resp }, + {12, "put_PingFactor", dissect_ICBAAccoMgt_put_PingFactor_rqst, dissect_dcom_simple_resp }, + {13, "get_CDBCookie", dissect_dcom_simple_rqst, dissect_ICBAAccoMgt_get_CDBCookie_resp }, + /* stage 2 */ + {14, "GetConsIDs", dissect_dcom_simple_rqst, dissect_ICBAAccoMgt2_GetConsIDs_resp }, + {15, "GetConsConnections", dissect_ICBAAccoMgt_GetConnections_rqst, dissect_ICBAAccoMgt2_GetConsConnections_resp }, + {16, "DiagConsConnections", dissect_ICBAAccoMgt_GetConnections_rqst, dissect_ICBAAccoMgt2_DiagConsConnections_resp }, + {17, "GetProvIDs", dissect_dcom_simple_rqst, dissect_Server_GetProvIDs_resp }, + {18, "GetProvConnections", dissect_Server_ProvIDs_rqst, dissect_Server_GetProvConnections_resp }, + {19, "GetDiagnosis", NULL, NULL }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAAccoCallback interface */ +static dcerpc_sub_dissector ICBAAccoCallback_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "OnDataChanged", dissect_ICBAAccoCallback_OnDataChanged_rqst, dissect_dcom_simple_resp }, + /* stage 2 */ + { 4, "Gnip", dissect_dcom_simple_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAAccoServer interface */ +static dcerpc_sub_dissector ICBAAccoServer_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "Connect", dissect_ICBAAccoServer_Connect_rqst, dissect_ICBAAccoServer_Connect_resp }, + { 4, "Disconnect", dissect_Server_ProvIDs_rqst, dissect_HResultArray_resp }, + { 5, "DisconnectMe", dissect_Server_Consumer_rqst, dissect_dcom_simple_resp }, + { 6, "SetActivation", dissect_ICBAAccoServer_SetActivation_rqst, dissect_HResultArray_resp }, + { 7, "Ping", dissect_ICBAAccoServer_Ping_rqst, dissect_dcom_simple_resp }, + /* stage 2 */ + { 8, "Connect2", dissect_ICBAAccoServer2_Connect2_rqst, dissect_ICBAAccoServer_Connect_resp }, + { 9, "GetConnectionData", dissect_Server_Consumer_rqst, dissect_ICBAAccoServer2_GetConnectionData_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAAccoServerSRT interface (stage 2 only) */ +static dcerpc_sub_dissector ICBAAccoServerSRT_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "ConnectCR", dissect_ICBAAccoServerSRT_ConnectCR_rqst, dissect_ICBAAccoServerSRT_ConnectCR_resp }, + { 4, "DisconnectCR", dissect_ICBAAccoServerSRT_DisconnectCR_rqst, dissect_HResultArray_resp }, + { 5, "Connect", dissect_ICBAAccoServerSRT_Connect_rqst, dissect_ICBAAccoServerSRT_Connect_resp }, + { 6, "Disconnect", dissect_Server_ProvIDs_rqst, dissect_HResultArray_resp }, + { 7, "DisconnectMe", dissect_Server_Consumer_rqst, dissect_dcom_simple_resp }, + { 8, "SetActivation", dissect_ICBAAccoServer_SetActivation_rqst, dissect_HResultArray_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAAccoSync interface */ +static dcerpc_sub_dissector ICBAAccoSync_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "ReadItems", dissect_ICBAAccoSync_ReadItems_rqst, dissect_ICBAAccoSync_ReadItems_resp }, + { 4, "WriteItems", dissect_ICBAAccoSync_WriteItems_rqst, dissect_HResultArray_resp }, + { 5, "WriteItemsQCD", dissect_ICBAAccoSync_WriteItemsQCD_rqst, dissect_HResultArray_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* register protocol */ +void +proto_register_dcom_cba_acco (void) +{ + static gint *ett[1]; + static gint *ett2[2]; + static gint *ett3[3]; + static gint *ett4[4]; + static gint *ett5[5]; + + + static hf_register_info hf_cba_acco_array[] = { + { &hf_cba_acco_opnum, + { "Operation", "cba.acco.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }}, + { &hf_cba_acco_ping_factor, + { "PingFactor", "cba.acco.ping_factor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_count, + { "Count", "cba.acco.count", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_info_max, + { "Max", "cba.acco.info_max", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_info_curr, + { "Current", "cba.acco.info_curr", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_rtauto, + { "RTAuto", "cba.acco.rtauto", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_item, + { "Item", "cba.acco.item", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_data, + { "Data", "cba.acco.data", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_qc, + { "QualityCode", "cba.acco.qc", FT_UINT8, BASE_HEX, VALS(cba_acco_qc_vals), 0x0, "", HFILL }}, + { &hf_cba_acco_time_stamp, + { "TimeStamp", "cba.acco.time_stamp", FT_UINT64, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_readitemout, + { "ReadItemOut", "cba.acco.readitemout", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_writeitemin, + { "WriteItemIn", "cba.acco.writeitemin", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_cdb_cookie, + { "CDBCookie", "cba.acco.cdb_cookie", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_conn_error_state, + { "ConnErrorState", "cba.acco.conn_error_state", FT_UINT32, BASE_HEX, VALS(dcom_hresult_vals), 0x0, "", HFILL }}, + }; + + static hf_register_info hf_cba_acco_server[] = { + { &hf_cba_acco_server_pICBAAccoCallback, + { "pICBAAccoCallback", "cba.acco.server_pICBAAccoCallback", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_server_first_connect, + { "FirstConnect", "cba.acco.server_first_connect", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_cba_getprovconnout, + { "GETPROVCONNOUT", "cba.acco.getprovconnout", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_serversrt_prov_mac, + { "ProviderMAC", "cba.acco.serversrt_prov_mac", FT_ETHER, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_serversrt_cons_mac, + { "ConsumerMAC", "cba.acco.serversrt_cons_mac", FT_ETHER, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_serversrt_cr_id, + { "ConsumerCRID", "cba.acco.serversrt_cr_id", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_serversrt_cr_length, + { "CRLength", "cba.acco.serversrt_cr_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_serversrt_cr_flags, + { "Flags", "cba.acco.serversrt_cr_flags", FT_UINT32, BASE_HEX, 0, 0x0, "", HFILL }}, + { &hf_cba_acco_serversrt_cr_flags_timestamped, + { "Timestamped", "cba.acco.serversrt_cr_flags_timestamped", FT_BOOLEAN, 32, TFS (&flags_set_truth), 0x1, "", HFILL }}, + { &hf_cba_acco_serversrt_cr_flags_reconfigure, + { "Reconfigure", "cba.acco.serversrt_cr_flags_reconfigure", FT_BOOLEAN, 32, TFS (&flags_set_truth), 0x2, "", HFILL }}, + { &hf_cba_type_desc_len, + { "TypeDescLen", "cba.acco.type_desc_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_serversrt_record_length, + { "RecordLength", "cba.acco.serversrt_record_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_serversrt_action, + { "Action", "cba.acco.serversrt_action", FT_UINT32, BASE_DEC, VALS(cba_acco_serversrt_action_vals), 0x0, "", HFILL }}, + { &hf_cba_acco_serversrt_last_connect, + { "LastConnect", "cba.acco.serversrt_last_connect", FT_UINT8, BASE_DEC, VALS(cba_acco_serversrt_last_connect_vals), 0x0, "", HFILL }}, + }; + + static hf_register_info hf_cba_connectcr_array[] = { + { &hf_cba_acco_prov_crid, + { "ProviderCRID", "cba.acco.prov_crid", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, + }; + + static hf_register_info hf_cba_connect_array[] = { + { &hf_cba_addconnectionin, + { "ADDCONNECTIONIN", "cba.acco.addconnectionin", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_addconnectionout, + { "ADDCONNECTIONOUT", "cba.acco.addconnectionout", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_getidout, + { "GETIDOUT", "cba.acco.getidout", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_getconnectionout, + { "GETCONNECTIONOUT", "cba.acco.getconnectionout", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_getconsconnout, + { "GETCONSCONNOUT", "cba.acco.getconsconnout", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_diagconsconnout, + { "DIAGCONSCONNOUT", "cba.acco.diagconsconnout", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_connectincr, + { "CONNECTINCR", "cba.acco.connectincr", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_connectoutcr, + { "CONNECTOUTCR", "cba.acco.connectoutcr", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_connectin, + { "CONNECTIN", "cba.acco.connectin", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_connectout, + { "CONNECTOUT", "cba.acco.connectout", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_conn_prov_id, + { "ProviderID", "cba.acco.conn_prov_id", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_conn_cons_id, + { "ConsumerID", "cba.acco.conn_cons_id", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_conn_version, + { "ConnVersion", "cba.acco.conn_version", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_conn_consumer, + { "Consumer", "cba.acco.conn_consumer", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_conn_qos_type, + { "QoSType", "cba.acco.conn_qos_type", FT_UINT16, BASE_HEX, VALS(cba_qos_type_vals), 0x0, "", HFILL }}, + { &hf_cba_acco_conn_qos_value, + { "QoSValue", "cba.acco.conn_qos_value", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_conn_state, + { "State", "cba.acco.conn_state", FT_UINT8, BASE_HEX, VALS(cba_acco_conn_state_vals), 0x0, "", HFILL }}, + { &hf_cba_acco_conn_provider, + { "Provider", "cba.acco.conn_provider", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_conn_provider_item, + { "ProviderItem", "cba.acco.conn_provider_item", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_conn_consumer_item, + { "ConsumerItem", "cba.acco.conn_consumer_item", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_conn_persist, + { "Persistence", "cba.acco.conn_persist", FT_UINT16, BASE_HEX, VALS(cba_persist_vals), 0x0, "", HFILL }}, + { &hf_cba_acco_conn_epsilon, + { "Epsilon", "cba.acco.conn_epsilon", FT_NONE, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_conn_substitute, + { "Substitute", "cba.acco.conn_substitute", FT_NONE, BASE_DEC, NULL, 0x0, "", HFILL }}, + }; + + static hf_register_info hf_cba_acco_cb[] = { + { &hf_cba_acco_cb_length, + { "Length", "cba.acco.cb_length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_cb_version, + { "Version", "cba.acco.cb_version", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_cb_flags, + { "Flags", "cba.acco.cb_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_cb_count, + { "Count", "cba.acco.cb_count", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_cb_conn_data, + { "CBA Connection data", "cba.acco.cb_conn_data", FT_NONE, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_cb_item, + { "Item", "cba.acco.cb_item", FT_NONE, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_cb_item_hole, + { "Hole", "cba.acco.cb_item_hole", FT_NONE, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_cb_item_length, + { "Length", "cba.acco.cb_item_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_acco_cb_item_data, + { "Data(Hex)", "cba.acco.cb_item_data", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }}, + }; + + ett5[0] = &ett_ICBAAccoMgt; + ett5[1] = &ett_cba_addconnectionin; + ett5[2] = &ett_cba_addconnectionout; + ett5[3] = &ett_cba_getidout; + ett5[4] = &ett_cba_getconnectionout; + proto_ICBAAccoMgt = proto_register_protocol ("ICBAAccoMgt", "ICBAAccoMgt", "cba_acco_mgt"); + proto_register_field_array(proto_ICBAAccoMgt, hf_cba_acco_array, array_length(hf_cba_acco_array)); + proto_register_field_array(proto_ICBAAccoMgt, hf_cba_connect_array, array_length(hf_cba_connect_array)); + proto_register_field_array(proto_ICBAAccoMgt, hf_cba_connectcr_array, array_length(hf_cba_connectcr_array)); + proto_register_subtree_array (ett5, array_length (ett5)); + + proto_ICBAAccoMgt2 = proto_register_protocol ("ICBAAccoMgt2", "ICBAAccoMgt2", "cba_acco_mgt2"); + + ett3[0] = &ett_ICBAAccoCallback; + ett3[1] = &ett_ICBAAccoCallback_Item; + ett3[2] = &ett_ICBAAccoCallback_Buffer; + proto_ICBAAccoCallback = proto_register_protocol ("ICBAAccoCallback", "ICBAAccoCB", "cba_acco_cb"); + proto_register_field_array(proto_ICBAAccoCallback, hf_cba_acco_cb, array_length(hf_cba_acco_cb)); + proto_register_subtree_array (ett3, array_length (ett3)); + + proto_ICBAAccoCallback2 = proto_register_protocol ("ICBAAccoCallback2", "ICBAAccoCB2", "cba_acco_cb2"); + + ett4[0] = &ett_ICBAAccoServer; + ett4[1] = &ett_cba_connectin; + ett4[2] = &ett_cba_connectout; + ett4[3] = &ett_cba_getprovconnout; + proto_ICBAAccoServer = proto_register_protocol ("ICBAAccoServer", "ICBAAccoServ", "cba_acco_server"); + proto_register_field_array(proto_ICBAAccoServer, hf_cba_acco_server, array_length(hf_cba_acco_server)); + proto_register_subtree_array (ett4, array_length (ett4)); + + proto_ICBAAccoServer2 = proto_register_protocol ("ICBAAccoServer2", "ICBAAccoServ2", "cba_acco_server2"); + + ett4[0] = &ett_ICBAAccoServerSRT; + ett4[1] = &ett_cba_acco_serversrt_cr_flags; + ett4[2] = &ett_cba_connectincr; + ett4[3] = &ett_cba_connectoutcr; + proto_ICBAAccoServerSRT = proto_register_protocol ("ICBAAccoServerSRT", "ICBAAccoServSRT", "cba_acco_server_srt"); + proto_register_subtree_array (ett4, array_length (ett4)); + + ett3[0] = &ett_ICBAAccoSync; + ett3[1] = &ett_cba_readitemout; + ett3[2] = &ett_cba_writeitemin; + proto_ICBAAccoSync = proto_register_protocol ("ICBAAccoSync", "ICBAAccoSync", "cba_acco_sync"); + proto_register_subtree_array (ett3, array_length (ett3)); +} + + +/* handoff protocol */ +void +proto_reg_handoff_dcom_cba_acco (void) +{ + /* Register the interfaces */ + dcerpc_init_uuid(proto_ICBAAccoMgt, ett_ICBAAccoMgt, + &uuid_ICBAAccoMgt, ver_ICBAAccoMgt, ICBAAccoMgt_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoMgt2, ett_ICBAAccoMgt, + &uuid_ICBAAccoMgt2, ver_ICBAAccoMgt2, ICBAAccoMgt_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoCallback, ett_ICBAAccoCallback, + &uuid_ICBAAccoCallback, ver_ICBAAccoCallback, ICBAAccoCallback_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoCallback2, ett_ICBAAccoCallback, + &uuid_ICBAAccoCallback2, ver_ICBAAccoCallback2, ICBAAccoCallback_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoServer, ett_ICBAAccoServer, + &uuid_ICBAAccoServer, ver_ICBAAccoServer, ICBAAccoServer_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoServer2, ett_ICBAAccoServer, + &uuid_ICBAAccoServer2, ver_ICBAAccoServer2, ICBAAccoServer_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoServerSRT, ett_ICBAAccoServerSRT, + &uuid_ICBAAccoServerSRT, ver_ICBAAccoServerSRT, ICBAAccoServerSRT_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoSync, ett_ICBAAccoSync, + &uuid_ICBAAccoSync, ver_ICBAAccoSync, ICBAAccoSync_dissectors, hf_cba_acco_opnum); + + + heur_dissector_add("pn_rt", dissect_CBA_Connection_Data_heur, proto_ICBAAccoServer); +} diff --git a/epan/dissectors/packet-dcom-cba.c b/epan/dissectors/packet-dcom-cba.c new file mode 100644 index 0000000000..15cf1bd5c0 --- /dev/null +++ b/epan/dissectors/packet-dcom-cba.c @@ -0,0 +1,1547 @@ +/* packet-dcom-cba.c + * Routines for DCOM CBA + * + * $Id$ + * + * Ethereal - 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + + +#include +#include +#include "packet-dcerpc.h" +#include "packet-dcom.h" + + +static int hf_cba_opnum = -1; + +static int hf_cba_revision_major = -1; +static int hf_cba_revision_minor = -1; +static int hf_cba_revision_service_pack = -1; +static int hf_cba_revision_build = -1; + +static int hf_cba_time = -1; + +static int hf_cba_name = -1; +static int hf_cba_producer = -1; +static int hf_cba_product = -1; +static int hf_cba_production_date = -1; +static int hf_cba_serial_no = -1; +static int hf_cba_multi_app = -1; +static int hf_cba_profinet_dcom_stack = -1; +static int hf_cba_pdev_stamp = -1; + +static int hf_cba_browse_count = -1; +static int hf_cba_browse_offset = -1; +static int hf_cba_browse_max_return = -1; +static int hf_cba_browse_item = -1; +static int hf_cba_browse_data_type = -1; +static int hf_cba_browse_access_right = -1; +static int hf_cba_browse_selector = -1; +static int hf_cba_browse_info1 = -1; +static int hf_cba_browse_info2 = -1; + +static int hf_cba_cookie = -1; +static int hf_cba_state = -1; +static int hf_cba_new_state = -1; +static int hf_cba_old_state = -1; +static int hf_cba_grouperror = -1; +static int hf_cba_new_grouperror = -1; +static int hf_cba_old_grouperror = -1; + +static int hf_cba_component_id = -1; +static int hf_cba_component_version = -1; + +static int hf_cba_save_ldev_name = -1; +static int hf_cba_save_result = -1; + + +/* fake protocols (these are simply classes) */ +static int proto_coclass_CBAPhysicalDevice = -1; +static gint ett_coclass_CBAPhysicalDevice = -1; +static e_uuid_t uuid_coclass_CBAPhysicalDevice = { 0xcba00000, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_coclass_CBAPhysicalDevice = 0; + + +/* CBA interfaces */ +static int proto_ICBAPhysicalDevice = -1; +static gint ett_ICBAPhysicalDevice = -1; +static e_uuid_t uuid_ICBAPhysicalDevice = { 0xcba00001, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAPhysicalDevice = 0; + +static int proto_ICBAPhysicalDevice2 = -1; +static e_uuid_t uuid_ICBAPhysicalDevice2 = { 0xcba00006, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAPhysicalDevice2 = 0; + +static int proto_ICBABrowse = -1; +static gint ett_ICBABrowse = -1; +static e_uuid_t uuid_ICBABrowse = { 0xcba00002, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBABrowse = 0; + +static int proto_ICBABrowse2 = -1; +static e_uuid_t uuid_ICBABrowse2 = { 0xcba00007, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBABrowse2 = 0; + +static int proto_ICBAPhysicalDevicePC = -1; +static gint ett_ICBAPhysicalDevicePC = -1; +static e_uuid_t uuid_ICBAPhysicalDevicePC = { 0xcba00003, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAPhysicalDevicePC = 0; + +static int proto_ICBAPhysicalDevicePCEvent = -1; +static gint ett_ICBAPhysicalDevicePCEvent = -1; +static e_uuid_t uuid_ICBAPhysicalDevicePCEvent = { 0xcba00004, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAPhysicalDevicePCEvent = 0; + +static int proto_ICBAPersist = -1; +static gint ett_ICBAPersist = -1; +static e_uuid_t uuid_ICBAPersist = { 0xcba00005, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAPersist = 0; + +static int proto_ICBAPersist2 = -1; +static e_uuid_t uuid_ICBAPersist2 = { 0xcba00008, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAPersist2 = 0; + +static int proto_ICBALogicalDevice = -1; +static gint ett_ICBALogicalDevice = -1; +static e_uuid_t uuid_ICBALogicalDevice = { 0xcba00011, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBALogicalDevice = 0; + +static int proto_ICBALogicalDevice2 = -1; +static e_uuid_t uuid_ICBALogicalDevice2 = { 0xcba00017, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBALogicalDevice2 = 0; + +static int proto_ICBAState = -1; +static gint ett_ICBAState = -1; +static e_uuid_t uuid_ICBAState = { 0xcba00012, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAState = 0; + +static int proto_ICBAStateEvent = -1; +static gint ett_ICBAStateEvent = -1; +static e_uuid_t uuid_ICBAStateEvent = { 0xcba00013, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAStateEvent = 0; + +static int proto_ICBATime = -1; +static gint ett_ICBATime = -1; +static e_uuid_t uuid_ICBATime = { 0xcba00014, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBATime = 0; + +static int proto_ICBAGroupError = -1; +static gint ett_ICBAGroupError = -1; +static e_uuid_t uuid_ICBAGroupError = { 0xcba00015, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAGroupError = 0; + +static int proto_ICBAGroupErrorEvent = -1; +static gint ett_ICBAGroupErrorEvent = -1; +static e_uuid_t uuid_ICBAGroupErrorEvent = { 0xcba00016, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAGroupErrorEvent = 0; + +static int proto_ICBARTAuto = -1; +static gint ett_ICBARTAuto = -1; +static e_uuid_t uuid_ICBARTAuto = { 0xcba00051, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBARTAuto = 0; + +static int proto_ICBARTAuto2 = -1; +static e_uuid_t uuid_ICBARTAuto2 = { 0xcba00052, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBARTAuto2 = 0; + +static int proto_ICBASystemProperties = -1; +static gint ett_ICBASystemProperties = -1; +static e_uuid_t uuid_ICBASystemProperties = { 0xcba00062, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBASystemProperties = 0; + + +static const value_string cba_state_vals[] = { + { 0x00, "NonExistent" }, + { 0x01, "Initializing" }, + { 0x02, "Ready" }, + { 0x03, "Operating" }, + { 0x04, "Defect" }, + { 0, NULL } +}; + + +static const value_string cba_grouperror_vals[] = { + { 0x00, "NonAccessible" }, + { 0x01, "Okay" }, + { 0x02, "Problem" }, + { 0x03, "Unknown" }, + { 0, NULL } +}; + + +static const value_string dcom_boolean_vals[] = { + { 0x00, "FALSE" }, + { 0x01, "TRUE" }, + { 0xffff, "TRUE" }, + { 0, NULL } +}; + + + + +static int +dissect_ICBABrowse_get_Count_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Count; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_browse_count, &u32Count); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (u32HResult) { /* !S_OK */ + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, "-> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } else { + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, " Cnt=%u -> S_OK", u32Count); + } + + + return offset; +} + + +static int +dissect_ICBABrowse_BrowseItems_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Offset; + guint32 u32MaxReturn; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_browse_offset, &u32Offset); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_browse_max_return, &u32MaxReturn); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, " Offset=%u MaxReturn=%u", + u32Offset, u32MaxReturn); + + return offset; +} + + +static int +dissect_ICBABrowse_BrowseItems_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Pointer; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, drep, hf_cba_browse_item); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, drep, hf_cba_browse_data_type); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, drep, hf_cba_browse_access_right); + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBABrowse2_get_Count2_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Selector; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_browse_selector, &u32Selector); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, " Selector=%u", + u32Selector); + + return offset; +} + + + +static int +dissect_ICBABrowse2_BrowseItems2_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Selector; + guint32 u32Offset; + guint32 u32MaxReturn; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_browse_selector, &u32Selector); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_browse_offset, &u32Offset); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_browse_max_return, &u32MaxReturn); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, " Sel=%u Offset=%u MaxReturn=%u", + u32Selector, u32Offset, u32MaxReturn); + + return offset; +} + + +static int +dissect_ICBABrowse2_BrowseItems2_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Pointer; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, drep, hf_cba_browse_item); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, drep, hf_cba_browse_info1); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, drep, hf_cba_browse_info2); + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAPersist2_Save2_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Pointer; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, drep, hf_cba_save_ldev_name); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, drep, hf_cba_save_result); + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + + +static int +dissect_get_BSTR_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, int hfindex) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + guint32 u32Pointer; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_BSTR(tvb, offset, pinfo, tree, drep, + hfindex, szStr, u32MaxStr); + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\" -> %s", szStr, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_get_ProductionDate_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32HResult; + gdouble r8Date; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DATE(tvb, offset, pinfo, tree, drep, + hf_cba_production_date, &r8Date); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Date: %g -> %s", + r8Date, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_get_SerialNo_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32HResult; + guint32 u32Pointer; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, drep, + hf_cba_serial_no); + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_ICBATime_get_Time_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32HResult; + gdouble r8Date; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DATE(tvb, offset, pinfo, tree, drep, + hf_cba_time, &r8Date); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Time: %g -> %s", + r8Date, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_ICBATime_put_Time_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + gdouble r8Date; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DATE(tvb, offset, pinfo, tree, drep, + hf_cba_time, &r8Date); + + return offset; +} + + +static int +dissect_get_Producer_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + return dissect_get_BSTR_resp(tvb, offset, pinfo, tree, drep, hf_cba_producer); +} + + +static int +dissect_get_Product_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + return dissect_get_BSTR_resp(tvb, offset, pinfo, tree, drep, hf_cba_product); +} + + +static int +dissect_ICBAPhysicalDevice_get_LogicalDevice_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Pointer; + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_BSTR(tvb, offset, pinfo, tree, drep, + hf_cba_name, szStr, u32MaxStr); + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\"", szStr); + } + + return offset; +} + + +static int +dissect_ICBAPhysicalDevice_get_LogicalDevice_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAPhysicalDevice2_Type_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16MultiApp; + guint16 u16PROFInetDCOMStack; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, tree, drep, + hf_cba_multi_app, &u16MultiApp); + + offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, tree, drep, + hf_cba_profinet_dcom_stack, &u16PROFInetDCOMStack); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, " App=%s Stack=%s -> %s", + (u16MultiApp) ? "Multi" : "Single", + (u16PROFInetDCOMStack) ? "PN-DCOM" : "MS-DCOM", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_PROFInetRevision_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16Major; + guint16 u16Minor; + guint16 u16ServicePack; + guint16 u16Build; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_revision_major, &u16Major); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_revision_minor, &u16Minor); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_revision_service_pack, &u16ServicePack); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_revision_build, &u16Build); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, " Revision=%u.%u.%u.%u -> %s", + u16Major, u16Minor, u16ServicePack, u16Build, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAPhysicalDevice2_get_PDevStamp_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32PDevStamp; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_pdev_stamp, &u32PDevStamp); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, " PDevStamp=0x%x -> %s", + u32PDevStamp, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_Revision_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16Major; + guint16 u16Minor; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_revision_major, &u16Major); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_revision_minor, &u16Minor); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": %u.%u -> %s", + u16Major, u16Minor, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_get_Name_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + return dissect_get_BSTR_resp(tvb, offset, pinfo, tree, drep, hf_cba_name); +} + + +static int +dissect_ICBALogicalDevice_get_ACCO_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_ICBALogicalDevice_get_RTAuto_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_ICBALogicalDevice_Get_RTAuto_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + guint32 u32Pointer; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_BSTR(tvb, offset, pinfo, tree, drep, + hf_cba_name, szStr, u32MaxStr); + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\"", szStr); + } + + return offset; +} + + + +static int +dissect_ComponentInfo_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + gchar szStr2[1000]; + guint32 u32MaxStr2 = sizeof(szStr2); + guint32 u32HResult; + guint32 u32Pointer; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_BSTR(tvb, offset, pinfo, tree, drep, + hf_cba_component_id, szStr, u32MaxStr); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_BSTR(tvb, offset, pinfo, tree, drep, + hf_cba_component_version, szStr2, u32MaxStr2); + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": ID=\"%s\" Version=\"%s\" -> %s", + szStr, szStr2, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_Advise_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0); + + return offset; +} + + +static int +dissect_Advise_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Cookie; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_cookie, &u32Cookie); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cookie=0x%x -> %s", + u32Cookie, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_Unadvise_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Cookie; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_cookie, &u32Cookie); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cookie=0x%x", + u32Cookie); + } + + return offset; +} + + +static int +dissect_ICBAState_get_State_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16State; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_state, &u16State); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": State=%s -> %s", + val_to_str(u16State, cba_state_vals, "Unknown (0x%08x)"), + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_ICBAStateEvent_OnStateChanged_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16NewState; + guint16 u16OldState; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_new_state, &u16NewState); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_old_state, &u16OldState); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": NewState=%s OldState=%s", + val_to_str(u16NewState, cba_state_vals, "Unknown (0x%04x)"), + val_to_str(u16OldState, cba_state_vals, "Unknown (0x%04x)") ); + } + + return offset; +} + + +static int +dissect_ICBAGroupError_OnGroupErrorChanged_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16NewGroupError; + guint16 u16OldGroupError; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_new_grouperror, &u16NewGroupError); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_old_grouperror, &u16OldGroupError); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": NewGE=%s OldGE=%s", + val_to_str(u16NewGroupError, cba_grouperror_vals, "Unknown (0x%04x)"), + val_to_str(u16OldGroupError, cba_grouperror_vals, "Unknown (0x%04x)") ); + } + + return offset; +} + + +static int +dissect_ICBAPhysicalDevicePCEvent_OnLogicalDeviceAdded_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32Cookie; + guint32 u32HResult; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_cookie, &u32Cookie); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cookie=0x%x %s", + u32Cookie, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +static int +dissect_ICBAGroupError_GroupError_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16GroupError; + guint32 u32Cookie; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_cba_grouperror, &u16GroupError); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_cba_cookie, &u32Cookie); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": GroupError=%s Cookie=0x%x -> %s", + val_to_str(u16GroupError, cba_grouperror_vals, "Unknown (0x%08x)"), + u32Cookie, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +/* sub dissector table of ICBAPhysicalDevice class (fake only) */ +static dcerpc_sub_dissector coclass_ICBAPhysicalDevice_dissectors[] = { + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAPhysicalDevice / ICBAPhysicalDevice2 interface */ +static dcerpc_sub_dissector ICBAPhysicalDevice_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", NULL, NULL }, + { 4, "GetTypeInfo", NULL, NULL }, + { 5, "GetIDsOfNames", NULL, NULL }, + { 6, "Invoke", NULL, NULL }, + + { 7, "get_Producer", dissect_dcom_simple_rqst, dissect_get_Producer_resp }, + { 8, "get_Product", dissect_dcom_simple_rqst, dissect_get_Product_resp }, + { 9, "get_SerialNo", dissect_dcom_simple_rqst, dissect_get_SerialNo_resp }, + {10, "get_ProductionDate", dissect_dcom_simple_rqst, dissect_get_ProductionDate_resp }, + {11, "Revision", dissect_dcom_simple_rqst, dissect_Revision_resp }, + {12, "get_LogicalDevice", dissect_ICBAPhysicalDevice_get_LogicalDevice_rqst, dissect_ICBAPhysicalDevice_get_LogicalDevice_resp }, + /* stage 2 */ + {13, "Type", dissect_dcom_simple_rqst, dissect_ICBAPhysicalDevice2_Type_resp }, + {14, "PROFInetRevision", dissect_dcom_simple_rqst, dissect_PROFInetRevision_resp }, + {15, "PDevStamp", dissect_dcom_simple_rqst, dissect_ICBAPhysicalDevice2_get_PDevStamp_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBABrowse / ICBABrowse2 interface */ +static dcerpc_sub_dissector ICBABrowse_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", NULL, NULL }, + { 4, "GetTypeInfo", NULL, NULL }, + { 5, "GetIDsOfNames", NULL, NULL }, + { 6, "Invoke", NULL, NULL }, + + { 7, "get_Count", dissect_dcom_simple_rqst, dissect_ICBABrowse_get_Count_resp }, + { 8, "BrowseItems", dissect_ICBABrowse_BrowseItems_rqst, dissect_ICBABrowse_BrowseItems_resp }, + /* stage 2 */ + { 9, "get_Count2", dissect_ICBABrowse2_get_Count2_rqst, dissect_ICBABrowse_get_Count_resp }, + {10, "BrowseItems2", dissect_ICBABrowse2_BrowseItems2_rqst, dissect_ICBABrowse2_BrowseItems2_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAPersist / ICBAPersist2 interface */ +static dcerpc_sub_dissector ICBAPersist_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", NULL, NULL }, + { 4, "GetTypeInfo", NULL, NULL }, + { 5, "GetIDsOfNames", NULL, NULL }, + { 6, "Invoke", NULL, NULL }, + + { 7, "Save", dissect_dcom_simple_rqst, dissect_dcom_simple_resp }, + /* stage 2 */ + { 8, "Save2", dissect_dcom_simple_rqst, dissect_ICBAPersist2_Save2_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAPhysicalDevicePC interface */ +/* (local COM interface, not to be called over network) */ +static dcerpc_sub_dissector ICBAPhysicalDevicePC_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "AddLogicalDevice", dissect_Advise_rqst, dissect_Advise_resp }, + { 4, "RemoveLogicalDevice", dissect_Unadvise_rqst, dissect_dcom_simple_resp }, + { 5, "AdvisePDevPC", dissect_Advise_rqst, dissect_Advise_resp }, + { 6, "UnadvisePDevPC", dissect_Unadvise_rqst, dissect_dcom_simple_resp }, + /* stage 2 */ + { 7, "RegisterApplication", NULL, NULL }, + { 8, "UnRegisterApplication", NULL, NULL }, + { 9, "AddLogicalDevice2", NULL, NULL }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAPhysicalDevicePCEvent interface */ +static dcerpc_sub_dissector ICBAPhysicalDevicePCEvent_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "OnLogicalDeviceAdded", dissect_ICBAPhysicalDevicePCEvent_OnLogicalDeviceAdded_rqst, dissect_dcom_simple_resp }, + { 4, "OnLogicalDeviceRemoved", dissect_Unadvise_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBALogicalDevice / ICBALogicalDevice2 interface */ +static dcerpc_sub_dissector ICBALogicalDevice_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", NULL, NULL }, + { 4, "GetTypeInfo", NULL, NULL }, + { 5, "GetIDsOfNames", NULL, NULL }, + { 6, "Invoke", NULL, NULL }, + + { 7, "get_Name", dissect_dcom_simple_rqst, dissect_get_Name_resp }, + { 8, "get_Producer", dissect_dcom_simple_rqst, dissect_get_Producer_resp }, + { 9, "get_Product", dissect_dcom_simple_rqst, dissect_get_Product_resp }, + {10, "get_SerialNo", dissect_dcom_simple_rqst, dissect_get_SerialNo_resp }, + {11, "get_ProductionDate", dissect_dcom_simple_rqst, dissect_get_ProductionDate_resp }, + {12, "Revision", dissect_dcom_simple_rqst, dissect_Revision_resp }, + {13, "get_ACCO", dissect_dcom_simple_rqst, dissect_ICBALogicalDevice_get_ACCO_resp }, + {14, "get_RTAuto", dissect_ICBALogicalDevice_Get_RTAuto_rqst, dissect_ICBALogicalDevice_get_RTAuto_resp }, + /* stage 2 */ + {15, "PROFInetRevision", dissect_dcom_simple_rqst, dissect_PROFInetRevision_resp }, + {16, "ComponentInfo", dissect_dcom_simple_rqst, dissect_ComponentInfo_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAState interface */ +static dcerpc_sub_dissector ICBAState_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", NULL, NULL }, + { 4, "GetTypeInfo", NULL, NULL }, + { 5, "GetIDsOfNames", NULL, NULL }, + { 6, "Invoke", NULL, NULL }, + + { 7, "get_State", dissect_dcom_simple_rqst, dissect_ICBAState_get_State_resp }, + { 8, "Activate", dissect_dcom_simple_rqst, dissect_dcom_simple_resp }, + { 9, "Deactivate", dissect_dcom_simple_rqst, dissect_dcom_simple_resp }, + {10, "Reset", dissect_dcom_simple_rqst, dissect_dcom_simple_resp }, + {11, "AdviseState", dissect_Advise_rqst, dissect_Advise_resp }, + {12, "UnadviseState", dissect_Unadvise_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAStateEvent interface */ +static dcerpc_sub_dissector ICBAStateEvent_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "OnStateChanged", dissect_ICBAStateEvent_OnStateChanged_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBATime interface */ +static dcerpc_sub_dissector ICBATime_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", NULL, NULL }, + { 4, "GetTypeInfo", NULL, NULL }, + { 5, "GetIDsOfNames", NULL, NULL }, + { 6, "Invoke", NULL, NULL }, + + { 7, "get_Time", dissect_dcom_simple_rqst, dissect_ICBATime_get_Time_resp }, + { 8, "put_Time", dissect_ICBATime_put_Time_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAGroupError interface */ +static dcerpc_sub_dissector ICBAGroupError_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", NULL, NULL }, + { 4, "GetTypeInfo", NULL, NULL }, + { 5, "GetIDsOfNames", NULL, NULL }, + { 6, "Invoke", NULL, NULL }, + + { 7, "GroupError", dissect_dcom_simple_rqst, dissect_ICBAGroupError_GroupError_resp }, + { 8, "AdviseGroupError", dissect_Advise_rqst, dissect_Advise_resp }, + { 9, "UnadviseGroupError", dissect_Unadvise_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAGroupErrorEvent interface */ +static dcerpc_sub_dissector ICBAGroupErrorEvent_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "OnGroupErrorChanged", dissect_ICBAGroupError_OnGroupErrorChanged_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBARTAuto interface */ +static dcerpc_sub_dissector ICBARTAuto_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", NULL, NULL }, + { 4, "GetTypeInfo", NULL, NULL }, + { 5, "GetIDsOfNames", NULL, NULL }, + { 6, "Invoke", NULL, NULL }, + + { 7, "get_Name", dissect_dcom_simple_rqst, dissect_get_Name_resp }, + { 8, "Revision", dissect_dcom_simple_rqst, dissect_Revision_resp }, + + /* stage 2 */ + { 9, "ComponentInfo", dissect_dcom_simple_rqst, dissect_ComponentInfo_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* the interface ICBASystemProperties will NOT be seen on the ethernet */ +/* sub dissector table of ICBASystemProperties interface (stage 2 only) */ +/* (usually not called over network, no dissecting needed) */ +static dcerpc_sub_dissector ICBASystemProperties_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", NULL, NULL }, + { 4, "GetTypeInfo", NULL, NULL }, + { 5, "GetIDsOfNames", NULL, NULL }, + { 6, "Invoke", NULL, NULL }, + + { 7, "StateCollection", dissect_dcom_simple_rqst, NULL }, + { 8, "StampCollection", dissect_dcom_simple_rqst, NULL }, + { 0, NULL, NULL, NULL }, +}; + + +/* register protocol */ +void +proto_register_dcom_cba (void) +{ + static gint *ett[1]; + static gint *ett2[2]; + static gint *ett3[3]; + static gint *ett4[4]; + static gint *ett5[5]; + + static hf_register_info hf_cba_browse_array[] = { + { &hf_cba_browse_count, + { "Count", "cba.browse.count", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_browse_offset, + { "Offset", "cba.browse.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_browse_max_return, + { "MaxReturn", "cba.browse.max_return", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_browse_item, + { "ItemNames", "cba.browse.item", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_browse_data_type, + { "DataTypes", "cba.browse.data_type", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_browse_access_right, + { "AccessRights", "cba.browse.access_right", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_browse_selector, + { "Selector", "cba.browse.selector", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_browse_info1, + { "Info1", "cba.browse.info1", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_browse_info2, + { "Info2", "cba.browse.info2", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + }; + + + static hf_register_info hf_cba_pdev_array[] = { + { &hf_cba_revision_major, + { "Major", "cba.revision_major", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_revision_minor, + { "Minor", "cba.revision_minor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_revision_service_pack, + { "ServicePack", "cba.revision_service_pack", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_revision_build, + { "Build", "cba_revision_build", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_cba_producer, + { "Producer", "cba.producer", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_product, + { "Product", "cba.product", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_multi_app, + { "MultiApp", "cba.multi_app", FT_UINT16, BASE_HEX, VALS(dcom_boolean_vals), 0x0, "", HFILL }}, + { &hf_cba_profinet_dcom_stack, + { "PROFInetDCOMStack", "cba.profinet_dcom_stack", FT_UINT16, BASE_HEX, VALS(dcom_boolean_vals), 0x0, "", HFILL }}, + { &hf_cba_pdev_stamp, + { "PDevStamp", "cba.pdev_stamp", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_cba_save_ldev_name, + { "LDevName", "cba.save_ldev_name", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_save_result, + { "PatialResult", "cba.save_result", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + }; + + static hf_register_info hf_cba_ldev_array[] = { + { &hf_cba_name, + { "Name", "cba.name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_component_id, + { "ComponentID", "cba.component_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_component_version, + { "Version", "cba.component_version", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + }; + + static hf_register_info hf_cba_array[] = { + { &hf_cba_opnum, + { "Operation", "cba.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }}, + { &hf_cba_production_date, + { "ProductionDate", "cba.production_date", FT_DOUBLE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_time, + { "Time", "cba.time", FT_DOUBLE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_serial_no, + { "SerialNo", "cba.serial_no", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_cba_state, + { "State", "cba.state", FT_UINT16, BASE_HEX, VALS(cba_state_vals), 0x0, "", HFILL }}, + { &hf_cba_new_state, + { "NewState", "cba.state_new", FT_UINT16, BASE_HEX, VALS(cba_state_vals), 0x0, "", HFILL }}, + { &hf_cba_old_state, + { "OldState", "cba.state_old", FT_UINT16, BASE_HEX, VALS(cba_state_vals), 0x0, "", HFILL }}, + { &hf_cba_cookie, + { "Cookie", "cba.cookie", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_cba_grouperror, + { "GroupError", "cba.grouperror", FT_UINT16, BASE_HEX, VALS(cba_grouperror_vals), 0x0, "", HFILL }}, + { &hf_cba_new_grouperror, + { "NewGroupError", "cba.grouperror_new", FT_UINT16, BASE_HEX, VALS(cba_grouperror_vals), 0x0, "", HFILL }}, + { &hf_cba_old_grouperror, + { "OldGroupError", "cba.grouperror_old", FT_UINT16, BASE_HEX, VALS(cba_grouperror_vals), 0x0, "", HFILL }}, + }; + + + ett[0] = &ett_coclass_CBAPhysicalDevice; + proto_coclass_CBAPhysicalDevice = proto_register_protocol ("CBAPhysicalDevice", "CBAPDev", "cba_pdev_class"); + proto_register_subtree_array (ett, array_length (ett)); + + ett[0] = &ett_ICBAPhysicalDevice; + proto_ICBAPhysicalDevice = proto_register_protocol ("ICBAPhysicalDevice", "ICBAPDev", "cba_pdev"); + proto_register_field_array(proto_ICBAPhysicalDevice, hf_cba_pdev_array, array_length(hf_cba_pdev_array)); + proto_register_subtree_array (ett, array_length (ett)); + + proto_ICBAPhysicalDevice2 = proto_register_protocol ("ICBAPhysicalDevice2", "ICBAPDev2", "cba_pdev2"); + + ett[0] = &ett_ICBABrowse; + proto_ICBABrowse = proto_register_protocol ("ICBABrowse", "ICBABrowse", "cba_browse"); + proto_register_field_array(proto_ICBABrowse, hf_cba_array, array_length(hf_cba_array)); + proto_register_field_array(proto_ICBABrowse, hf_cba_browse_array, array_length(hf_cba_browse_array)); + proto_register_subtree_array (ett, array_length (ett)); + + ett[0] = &ett_ICBABrowse; + proto_ICBABrowse2 = proto_register_protocol ("ICBABrowse2", "ICBABrowse2", "cba_browse2"); + proto_register_subtree_array (ett, array_length (ett)); + + ett[0] = &ett_ICBAPhysicalDevicePC; + proto_ICBAPhysicalDevicePC = proto_register_protocol ("ICBAPhysicalDevicePC", "ICBAPDevPC", "cba_pdev_pc"); + proto_register_subtree_array (ett, array_length (ett)); + + ett[0] = &ett_ICBAPhysicalDevicePCEvent; + proto_ICBAPhysicalDevicePCEvent = proto_register_protocol ("ICBAPhysicalDevicePCEvent", "ICBAPDevPCEvent", "cba_pdev_pc_event"); + proto_register_subtree_array (ett, array_length (ett)); + + ett[0] = &ett_ICBAPersist; + proto_ICBAPersist = proto_register_protocol ("ICBAPersist", "ICBAPersist", "cba_persist"); + proto_register_subtree_array (ett, array_length (ett)); + + proto_ICBAPersist2 = proto_register_protocol ("ICBAPersist2", "ICBAPersist2", "cba_persist2"); + + ett[0] = &ett_ICBALogicalDevice; + proto_ICBALogicalDevice = proto_register_protocol ("ICBALogicalDevice", "ICBALDev", "cba_ldev"); + proto_register_field_array(proto_ICBAPhysicalDevice, hf_cba_ldev_array, array_length(hf_cba_ldev_array)); + proto_register_subtree_array (ett, array_length (ett)); + + ett[0] = &ett_ICBALogicalDevice; + proto_ICBALogicalDevice2 = proto_register_protocol ("ICBALogicalDevice2", "ICBALDev2", "cba_ldev2"); + proto_register_subtree_array (ett, array_length (ett)); + + ett[0] = &ett_ICBAState; + proto_ICBAState = proto_register_protocol ("ICBAState", "ICBAState", "cba_state"); + proto_register_subtree_array (ett, array_length (ett)); + + ett[0] = &ett_ICBAStateEvent; + proto_ICBAStateEvent = proto_register_protocol ("ICBAStateEvent", "ICBAStateEvent", "cba_state_event"); + proto_register_subtree_array (ett, array_length (ett)); + + ett[0] = &ett_ICBATime; + proto_ICBATime = proto_register_protocol ("ICBATime", "ICBATime", "cba_time"); + proto_register_subtree_array (ett, array_length (ett)); + + ett[0] = &ett_ICBAGroupError; + proto_ICBAGroupError = proto_register_protocol ("ICBAGroupError", "ICBAGErr", "cba_grouperror"); + proto_register_subtree_array (ett, array_length (ett)); + + ett[0] = &ett_ICBAGroupErrorEvent; + proto_ICBAGroupErrorEvent = proto_register_protocol ("ICBAGroupErrorEvent", "ICBAGErrEvent", "cba_grouperror_event"); + proto_register_subtree_array (ett, array_length (ett)); + + ett[0] = &ett_ICBARTAuto; + proto_ICBARTAuto = proto_register_protocol ("ICBARTAuto", "ICBARTAuto", "cba_rtauto"); + proto_register_subtree_array (ett, array_length (ett)); + + proto_ICBARTAuto2 = proto_register_protocol ("ICBARTAuto2", "ICBARTAuto2", "cba_rtauto2"); + + ett[0] = &ett_ICBASystemProperties; + proto_ICBASystemProperties = proto_register_protocol ("ICBASystemProperties", "ICBASysProp", "cba_sysprop"); + proto_register_subtree_array (ett, array_length (ett)); +} + + +/* handoff protocol */ +void +proto_reg_handoff_dcom_cba (void) +{ + /* Register the DCOM coclass */ + dcom_register_server_coclass(proto_coclass_CBAPhysicalDevice, ett_coclass_CBAPhysicalDevice, + &uuid_coclass_CBAPhysicalDevice, ver_coclass_CBAPhysicalDevice, + coclass_ICBAPhysicalDevice_dissectors, hf_cba_opnum); + + /* Register the interfaces */ + dcerpc_init_uuid(proto_ICBAPhysicalDevice, ett_ICBAPhysicalDevice, + &uuid_ICBAPhysicalDevice, ver_ICBAPhysicalDevice, + ICBAPhysicalDevice_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAPhysicalDevice2, ett_ICBAPhysicalDevice, + &uuid_ICBAPhysicalDevice2, ver_ICBAPhysicalDevice2, + ICBAPhysicalDevice_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBABrowse, ett_ICBABrowse, + &uuid_ICBABrowse, ver_ICBABrowse, + ICBABrowse_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBABrowse2, ett_ICBABrowse, + &uuid_ICBABrowse2, ver_ICBABrowse2, + ICBABrowse_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAPhysicalDevicePC, ett_ICBAPhysicalDevicePC, + &uuid_ICBAPhysicalDevicePC, ver_ICBAPhysicalDevicePC, + ICBAPhysicalDevicePC_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAPhysicalDevicePCEvent, ett_ICBAPhysicalDevicePCEvent, + &uuid_ICBAPhysicalDevicePCEvent, ver_ICBAPhysicalDevicePCEvent, + ICBAPhysicalDevicePCEvent_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAPersist, ett_ICBAPersist, + &uuid_ICBAPersist, ver_ICBAPersist, + ICBAPersist_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAPersist2, ett_ICBAPersist, + &uuid_ICBAPersist2, ver_ICBAPersist2, + ICBAPersist_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBALogicalDevice, ett_ICBALogicalDevice, + &uuid_ICBALogicalDevice, ver_ICBALogicalDevice, + ICBALogicalDevice_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBALogicalDevice2, ett_ICBALogicalDevice, + &uuid_ICBALogicalDevice2, ver_ICBALogicalDevice, + ICBALogicalDevice_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAState, ett_ICBAState, + &uuid_ICBAState, ver_ICBAState, + ICBAState_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAStateEvent, ett_ICBAStateEvent, + &uuid_ICBAStateEvent, ver_ICBAStateEvent, + ICBAStateEvent_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBATime, ett_ICBATime, + &uuid_ICBATime, ver_ICBATime, + ICBATime_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAGroupError, ett_ICBAGroupError, + &uuid_ICBAGroupError, ver_ICBAGroupError, + ICBAGroupError_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAGroupErrorEvent, ett_ICBAGroupErrorEvent, + &uuid_ICBAGroupErrorEvent, ver_ICBAGroupErrorEvent, + ICBAGroupErrorEvent_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBARTAuto, ett_ICBARTAuto, + &uuid_ICBARTAuto, ver_ICBARTAuto, + ICBARTAuto_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBARTAuto2, ett_ICBARTAuto, + &uuid_ICBARTAuto2, ver_ICBARTAuto2, + ICBARTAuto_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBASystemProperties, ett_ICBASystemProperties, + &uuid_ICBASystemProperties, ver_ICBASystemProperties, + ICBASystemProperties_dissectors, hf_cba_opnum); +} diff --git a/epan/dissectors/packet-dcom.c b/epan/dissectors/packet-dcom.c new file mode 100644 index 0000000000..148f183cc8 --- /dev/null +++ b/epan/dissectors/packet-dcom.c @@ -0,0 +1,1901 @@ +/* packet-dcom.c + * Routines for DCOM generics + * + * $Id$ + * + * Ethereal - 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* A few words about DCOM: + * + * DCOM uses DCERPC as it's underlying "transport" protocol. + * + * The DCOM dissectors are called by DCERPC request and response calls. + * DCOM uses a small header after the DCERPC calls. + * (for a DCERPC request call it's called "this", + * for a DCERPC response call it's called "that") + * + * DCOM defines itself some interfaces: oxid, remact, remunk and others + * + * Implemented is currently "only" a static dissection of packet fields + * (no "object recognition" included) + * + * User's of DCOM can define their own interface's using Microsoft IDL. + * + * Hint: The registered DCOM interface names can be found in the + * windows registry at: "HKEY_CLASSES_ROOT\Interface" + * + * + * Ressources on the web: + * + * "Understanding the DCOM Wire Protocol by Analyzing Network Data Packets" + * http:// www.microsoft.com/msj/0398/dcom.htm + * + * "Distributed Component Object Model Protocol -- DCOM/1.0" + * http://www.microsoft.com/com/resources/specs.asp (link is currently down) + * + */ + +/* Files involved dissecting DCOM: + * + * packet-dcom.c: generic DCOM things (this, that, ...) and + * generic DCOM datatype (DWORD, VARIANT, ...) + * + * DCOM common Interfaces: + * packet-dcom-oxid.c: IOXIDResolver + * packet-dcom-remact.c: IRemoteActivation + * packet-dcom-remunk.c: IRemUnknown, IRemUnknown2 + * packet-dcom-dispatch.c: IDispatch + * packet-dcom-sysact.c: ISystemActivator + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#include +#include +#include "packet-dcerpc.h" +#include "packet-dcom.h" +#include "prefs.h" + + +static int proto_dcom = -1; +void proto_reg_handoff_dcom(void); +static gchar* dcom_uuid_to_str(e_uuid_t *uuid); + +int dcom_prefs_display_unmarshalling_details = FALSE; + + +gint ett_dcom_this = -1; +static int hf_dcom_this_version_major = -1; +static int hf_dcom_this_version_minor = -1; +static int hf_dcom_this_flags = -1; +static int hf_dcom_this_res = -1; +static int hf_dcom_this_cid = -1; + +gint ett_dcom_that = -1; +static int hf_dcom_that_flags = -1; + +gint ett_dcom_extent = -1; +static int hf_dcom_extent = -1; +static int hf_dcom_extent_array_count = -1; +static int hf_dcom_extent_array_res = -1; +static int hf_dcom_extent_size = -1; +static int hf_dcom_extent_id = -1; + +static int hf_dcom_hresult = -1; +static int hf_dcom_tobedone = -1; +static int hf_dcom_tobedone_len = -1; +static int hf_dcom_array_size = -1; +static int hf_dcom_pointer_val = -1; + +/* COMVERSION */ +static int hf_dcom_version_major = -1; +static int hf_dcom_version_minor = -1; + +gint ett_dcom_lpwstr = -1; +static int hf_dcom_max_count = -1; +static int hf_dcom_offset = -1; +static int hf_dcom_byte_length = -1; +static int hf_dcom_actual_count = -1; + +gint ett_dcom_objref = -1; +static int hf_dcom_objref = -1; +static int hf_dcom_objref_signature = -1; +static int hf_dcom_objref_flags = -1; +static int hf_dcom_objref_iid = -1; +static int hf_dcom_objref_clsid = -1; +static int hf_dcom_objref_resolver_address = -1; + +gint ett_dcom_stdobjref = -1; +static int hf_dcom_stdobjref = -1; +static int hf_dcom_stdobjref_flags = -1; +static int hf_dcom_stdobjref_public_refs = -1; +static int hf_dcom_stdobjref_oxid = -1; +static int hf_dcom_stdobjref_oid = -1; +static int hf_dcom_stdobjref_ipid = -1; + +gint ett_dcom_dualstringarray = -1; +gint ett_dcom_dualstringarray_binding = -1; +static int hf_dcom_dualstringarray_num_entries = -1; +static int hf_dcom_dualstringarray_security_offset = -1; +static int hf_dcom_dualstringarray_string = -1; +static int hf_dcom_dualstringarray_string_network_addr = -1; +static int hf_dcom_dualstringarray_string_tower_id = -1; +static int hf_dcom_dualstringarray_security = -1; +static int hf_dcom_dualstringarray_security_authn_svc = -1; +static int hf_dcom_dualstringarray_security_authz_svc = -1; +static int hf_dcom_dualstringarray_security_princ_name = -1; + +gint ett_dcom_interface_pointer = -1; +static int hf_dcom_interface_pointer = -1; +static int hf_dcom_ip_cnt_data = -1; + +gint ett_dcom_safearray = -1; +static int hf_dcom_safearray = -1; +static int hf_dcom_sa_dims32 = -1; +static int hf_dcom_sa_dims16 = -1; +static int hf_dcom_sa_features = -1; +static int hf_dcom_sa_element_size = -1; +static int hf_dcom_sa_locks = -1; +static int hf_dcom_sa_vartype32 = -1; +static int hf_dcom_sa_vartype16 = -1; +static int hf_dcom_sa_elements = -1; +static int hf_dcom_sa_bound_elements = -1; +static int hf_dcom_sa_low_bound = -1; + +gint ett_dcom_sa_features = -1; +static int hf_dcom_sa_features_auto = -1; +static int hf_dcom_sa_features_static = -1; +static int hf_dcom_sa_features_embedded = -1; +static int hf_dcom_sa_features_fixedsize = -1; +static int hf_dcom_sa_features_record = -1; +static int hf_dcom_sa_features_have_iid = -1; +static int hf_dcom_sa_features_have_vartype = -1; +static int hf_dcom_sa_features_bstr = -1; +static int hf_dcom_sa_features_unknown = -1; +static int hf_dcom_sa_features_dispatch = -1; +static int hf_dcom_sa_features_variant = -1; + +gint ett_dcom_variant = -1; +static int hf_dcom_variant = -1; +static int hf_dcom_variant_type = -1; +static int hf_dcom_variant_size = -1; +static int hf_dcom_variant_rpc_res = -1; +static int hf_dcom_variant_wres = -1; +static int hf_dcom_variant_type32 = -1; + +static int hf_dcom_vt_bool = -1; +static int hf_dcom_vt_i1 = -1; +static int hf_dcom_vt_i2 = -1; +static int hf_dcom_vt_i4 = -1; +static int hf_dcom_vt_i8 = -1; /* only inside a SAFEARRAY, not in VARIANTs */ +static int hf_dcom_vt_ui1 = -1; +static int hf_dcom_vt_ui2 = -1; +static int hf_dcom_vt_ui4 = -1; +static int hf_dcom_vt_r4 = -1; +static int hf_dcom_vt_r8 = -1; +static int hf_dcom_vt_date = -1; +static int hf_dcom_vt_bstr = -1; + + + +/* + * Flag bits in connection-oriented PDU header. + */ +#define ETHEREAL_FADF_AUTO 0x0001 +#define ETHEREAL_FADF_STATIC 0x0002 +#define ETHEREAL_FADF_EMBEDDED 0x0004 +#define ETHEREAL_FADF_FIXEDSIZE 0x0010 +#define ETHEREAL_FADF_RECORD 0x0020 +#define ETHEREAL_FADF_HAVEIID 0x0040 +#define ETHEREAL_FADF_HAVEVARTYPE 0x0080 +#define ETHEREAL_FADF_BSTR 0x0100 +#define ETHEREAL_FADF_UNKNOWN 0x0200 +#define ETHEREAL_FADF_DISPATCH 0x0400 +#define ETHEREAL_FADF_VARIANT 0x0800 + + +typedef enum { + ETHEREAL_VT_EMPTY = 0, + ETHEREAL_VT_NULL = 1, + ETHEREAL_VT_I2 = 2, + ETHEREAL_VT_I4 = 3, + ETHEREAL_VT_R4 = 4, + ETHEREAL_VT_R8 = 5, + ETHEREAL_VT_CY = 6, + ETHEREAL_VT_DATE = 7, + ETHEREAL_VT_BSTR = 8, + ETHEREAL_VT_DISPATCH = 9, + ETHEREAL_VT_ERROR = 10, + ETHEREAL_VT_BOOL = 11, + ETHEREAL_VT_VARIANT = 12, + ETHEREAL_VT_UNKNOWN = 13, + ETHEREAL_VT_DECIMAL = 14, + ETHEREAL_VT_I1 = 16, + ETHEREAL_VT_UI1 = 17, + ETHEREAL_VT_UI2 = 18, + ETHEREAL_VT_UI4 = 19, + ETHEREAL_VT_I8 = 20, + ETHEREAL_VT_UI8 = 21, + ETHEREAL_VT_INT = 22, + ETHEREAL_VT_UINT = 23, + ETHEREAL_VT_VOID = 24, + ETHEREAL_VT_HRESULT = 25, + ETHEREAL_VT_PTR = 26, + ETHEREAL_VT_SAFEARRAY = 27, + ETHEREAL_VT_CARRAY = 28, + ETHEREAL_VT_USERDEFINED = 29, + ETHEREAL_VT_LPSTR = 30, + ETHEREAL_VT_LPWSTR = 31, + ETHEREAL_VT_RECORD = 36, + ETHEREAL_VT_FILETIME = 64, + ETHEREAL_VT_BLOB = 65, + ETHEREAL_VT_STREAM = 66, + ETHEREAL_VT_STORAGE = 67, + ETHEREAL_VT_STREAMED_OBJECT = 68, + ETHEREAL_VT_STORED_OBJECT = 69, + ETHEREAL_VT_BLOB_OBJECT = 70, + ETHEREAL_VT_CF = 71, + ETHEREAL_VT_CLSID = 72, + + ETHEREAL_VT_BSTR_BLOB = 0x0fff, + + ETHEREAL_VT_VECTOR = 0x1000, + ETHEREAL_VT_ARRAY = 0x2000, + ETHEREAL_VT_BYREF = 0x4000, + ETHEREAL_VT_RESERVED = 0x8000, + + ETHEREAL_VT_ILLEGAL = 0xffff, + ETHEREAL_VT_ILLEGALMASKED = 0x0fff, + ETHEREAL_VT_TYPEMASK = 0x0fff +} dcom_vartype_t; + +const value_string dcom_variant_type_vals[] = { + { ETHEREAL_VT_EMPTY, "VT_EMPTY"}, + { ETHEREAL_VT_NULL, "VT_NULL"}, + { ETHEREAL_VT_I2, "VT_I2"}, + { ETHEREAL_VT_I4, "VT_I4"}, + { ETHEREAL_VT_R4, "VT_R4"}, + { ETHEREAL_VT_R8, "VT_R8"}, + { ETHEREAL_VT_CY, "VT_CY"}, + { ETHEREAL_VT_DATE, "VT_DATE"}, + { ETHEREAL_VT_BSTR, "VT_BSTR"}, + { ETHEREAL_VT_ERROR, "VT_ERROR"}, + { ETHEREAL_VT_BOOL, "VT_BOOL"}, + { ETHEREAL_VT_I1, "VT_I1"}, + { ETHEREAL_VT_UI1, "VT_UI1"}, + { ETHEREAL_VT_UI2, "VT_UI2"}, + { ETHEREAL_VT_UI4, "VT_UI4"}, + { ETHEREAL_VT_I8, "VT_I8"}, + { ETHEREAL_VT_UI8, "VT_UI8"}, + { ETHEREAL_VT_ARRAY, "VT_ARRAY"}, + { ETHEREAL_VT_UNKNOWN, "VT_UNKNOWN"}, + { ETHEREAL_VT_USERDEFINED, "VT_USERDEFINED"}, + + /* XXX: this could be done better */ + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_I2, "VT_ARRAY|VT_I2"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_I4, "VT_ARRAY|VT_I4"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_R4, "VT_ARRAY|VT_R4"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_R8, "VT_ARRAY|VT_R8"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_DATE, "VT_ARRAY|VT_DATE"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_BSTR, "VT_ARRAY|VT_BSTR"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_ERROR, "VT_ARRAY|VT_ERROR"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_BOOL, "VT_ARRAY|VT_BOOL"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_I1, "VT_ARRAY|VT_I1"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_UI1, "VT_ARRAY|VT_UI1"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_UI2, "VT_ARRAY|VT_UI2"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_UI4, "VT_ARRAY|VT_UI4"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_I8, "VT_ARRAY|VT_I8"}, + { ETHEREAL_VT_ARRAY | ETHEREAL_VT_UI8, "VT_ARRAY|VT_UI8"}, + { 0, NULL } +/* XXX: append more types here */ +}; + + + +/* we need an extension mechanism here (be able to append entries by user protocol) */ +const value_string dcom_hresult_vals[] = { + { 0x00000000, "S_OK" }, + { 0x00000001, "S_FALSE" }, + { 0x8000FFFF, "E_UNEXPECTED" }, + { 0x80004001, "E_NOTIMPL" }, + { 0x80004002, "E_NOINTERFACE" }, + { 0x80004004, "E_ABORT" }, + { 0x80004005, "E_FAIL" }, + { 0x80004003, "E_POINTER" }, + { 0x80070005, "E_ACCESSDENIED" }, + { 0x80070006, "E_HANDLE" }, + { 0x8007000E, "E_OUTOFMEMORY" }, + { 0x80070057, "E_INVALIDARG" }, + + { 0x80010108, "RPC_E_DISCONNECTED" }, + + { 0x80020004, "DISP_E_PARAMNOTFOUND" }, + + { 0x80040154, "REGDB_E_CLASSNOTREG" }, + +/* following are CBA application specific values */ + { 0x0004CA00, "CBA_S_PERSISTPENDING" }, + { 0x0004CA01, "CBA_S_ESTABLISHING" }, + { 0x0004CA02, "CBA_S_NOCONNECTION" }, + { 0x0004CA03, "CBA_S_VALUEBUFFERED" }, + { 0x0004CA04, "CBA_S_VALUEUNCERTAIN" }, + { 0x0004CA05, "CBA_S_NOCONNECTIONDATA" }, + { 0x0004CA06, "CBA_S_FRAMEEMPTY" }, + + { 0x8004CB00, "CBA_E_MALFORMED" }, + { 0x8004CB01, "CBA_E_UNKNOWNOBJECT" }, + { 0x8004CB02, "CBA_E_UNKNOWNMEMBER" }, + { 0x8004CB03, "CBA_E_TYPEMISMATCH" }, + { 0x8004CB04, "CBA_E_INVALIDENUMVALUE" }, + { 0x8004CB05, "CBA_E_INVALIDID" }, + { 0x8004CB06, "CBA_E_INVALIDEPSILON" }, + { 0x8004CB07, "CBA_E_INVALIDSUBSTITUTE" }, + { 0x8004CB08, "CBA_E_INVALIDCONNECTION" }, + { 0x8004CB09, "CBA_E_INVALIDCOOKIE" }, + { 0x8004CB0A, "CBA_E_TIMEVALUEUNSUPPORTED" }, + { 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" }, + { 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" }, + { 0x8004CB0D, "CBA_E_PERSISTRUNNING" }, + { 0x8004CB0E, "CBA_E_INUSE" }, + { 0x8004CB0F, "CBA_E_NOTAPPLICABLE" }, + { 0x8004CB10, "CBA_E_NONACCESSIBLE" }, + { 0x8004CB11, "CBA_E_DEFECT" }, + { 0x8004CB12, "CBA_E_LIMITVIOLATION" }, + { 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" }, + { 0x8004CB14, "CBA_E_QCNOTAPPLICABLE" }, + { 0x8004CB15, "CBA_E_ACCESSBLOCKED" }, + { 0x8004CB16, "CBA_E_COUNTEXCEEDED" }, + { 0x8004CB17, "CBA_E_SIZEEXCEEDED" }, + { 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" }, + { 0x8004CB19, "CBA_E_OUTOFACCOPAIRS" }, + { 0x8004CB1A, "CBA_E_ITEMTOOLARGE" }, + { 0x8004CB1B, "CBA_E_CRDATALENGTH" }, + { 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" }, + { 0x8004CB1D, "CBA_E_CAPACITYEXCEEDED" }, + { 0x8004CB1E, "CBA_E_SUBELEMENTMISMATCH" }, + { 0x8004CB1F, "CBA_E_STATIONFAILURE" }, + { 0x8004CB20, "CBA_E_NOTROUTABLE" }, + { 0x8004CB21, "CBA_E_DISCONNECTRUNNING" }, + { 0x8004CB22, "CBA_E_LOCATIONCHANGED" }, + { 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" }, + { 0x8004CB24, "CBA_E_LINKFAILURE" }, + { 0x8004CB25, "CBA_E_MODECHANGE" }, + { 0, NULL } +}; + +static const value_string dcom_objref_flag_vals[] = { + { 0x1, "OBJREF_STANDARD" }, + { 0x2, "OBJREF_HANDLER" }, + { 0x4, "OBJREF_CUSTOM" }, + { 0, NULL } +}; + +static const value_string dcom_objref_signature_vals[] = { + { 0x574f454d, "MEOW" }, + { 0, NULL } +}; + +static const value_string dcom_dcerpc_pointer_vals[] = { + { 0x72657355, "User" }, + { 0x42535452, "BSTR" }, + { 0x00000000, "NULL" }, + { 0, NULL } +}; + +static const value_string hf_dcom_dualstringarray_tower_id_vals[] = { + { 0x08, "UDP" }, + { 0x07, "TCP" }, + { 0x0E, "IPX" }, + { 0x0C, "SPX" }, + { 0x12, "NB_NB" }, + { 0x0D, "NB_IPX" }, + { 0x04, "DNET_NSP" }, + { 0x1F, "HTTP" }, + { 0, NULL } +}; + +static const value_string dcom_vt_bool_vals[] = { + { 0x0000, "TRUE" }, + { 0xFFFF, "FALSE" }, + { 0, NULL } +}; + + + +/* dissect extension to DCOM "this" and "that" */ +int +dissect_dcom_extent(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32ArraySize; + guint32 u32ArraySize2; + guint32 u32Pointer; + guint32 u32VariableOffset; + guint32 u32Idx; + guint32 u32SubStart; + proto_item *sub_item; + proto_tree *sub_tree; + + guint32 u32ArrayCount; + guint32 u32ArrayRes; + + guint32 u32ExtentSize; + e_uuid_t uuidExtend; + + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer); + + if (u32Pointer == 0) { + return offset; + } + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_dcom_extent_array_count, &u32ArrayCount); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_dcom_extent_array_res, &u32ArrayRes); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer); + + if (u32Pointer == 0) { + return offset; + } + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize*4; + + u32Idx = 1; + while (u32ArraySize--) { + sub_item = proto_tree_add_item(tree, hf_dcom_extent, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_dcom_extent); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer); + + if(u32Pointer != 0) { + u32VariableOffset = dissect_dcom_DWORD(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_dcom_extent_size, &u32ExtentSize); + u32VariableOffset = dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_dcom_extent_id, &uuidExtend); + + u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, drep, + &u32ArraySize2); + u32VariableOffset = dissect_dcom_tobedone_data(tvb, u32VariableOffset, pinfo, sub_tree, drep, u32ArraySize2); + + /* update subtree header */ + proto_item_append_text(sub_item, "[%u]: Bytes=%u", + u32Idx, u32ArraySize2); + proto_item_set_len(sub_item, offset - u32SubStart); + } else { + /* update subtree header */ + proto_item_append_text(sub_item, "[%u]: NULL", u32Idx); + proto_item_set_len(sub_item, offset - u32SubStart); + } + + u32Idx++; + } + + return u32VariableOffset; +} + + +/* dissect DCOM "this" (start of every DCOM request) */ +int +dissect_dcom_this(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16VersionMajor; + guint16 u16VersionMinor; + guint32 u32Flags; + guint32 u32Res; + e_uuid_t uuidCausality; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0, + "DCOM, ORPCThis"); + sub_tree = proto_item_add_subtree(sub_item, ett_dcom_this); + + offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, sub_tree, drep, + &u16VersionMajor, &u16VersionMinor); + u32SubStart = offset - 4; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_this_flags, &u32Flags); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_this_res, &u32Res); + + offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_this_cid, &uuidCausality); + + offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, drep); + + /* update subtree header */ + proto_item_append_text(sub_item, ", V%u.%u, Causality ID: %s", + u16VersionMajor, u16VersionMinor, dcom_uuid_to_str(&uuidCausality)); + proto_item_set_len(sub_item, offset - u32SubStart); + + return offset; +} + + +/* dissect DCOM "that" (start of every DCOM response) */ +int +dissect_dcom_that(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) { + guint32 u32Flags; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0, + "DCOM, ORPCThat"); + sub_tree = proto_item_add_subtree(sub_item, ett_dcom_that); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_that_flags, &u32Flags); + u32SubStart = offset - 4; + + offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, drep); + + /* update subtree header */ + proto_item_set_len(sub_item, offset - u32SubStart); + + return offset; +} + + +/* dissect simple dcom request, DCOM "this" only */ +int +dissect_dcom_simple_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + return offset; +} + + +/* dissect simple dcom response, DCOM "that" and returned HRESULT only */ +int +dissect_dcom_simple_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } + + return offset; +} + + +/* Tries to match uuid against its name. + Returns the associated string ptr on a match. + Formats uuid number and returns the resulting string, on failure. + (copied from val_to_str) */ +static gchar* dcom_uuid_to_str(e_uuid_t *uuid) { + gchar *ret; + static gchar str[3][64]; + static gchar *cur; + + + /* all DCOM interfaces are registered with version 0 */ + ret = dcerpc_get_uuid_name(uuid, 0); + if (ret != NULL) + return ret; + if (cur == &str[0][0]) { + cur = &str[1][0]; + } else if (cur == &str[1][0]) { + cur = &str[2][0]; + } else { + cur = &str[0][0]; + } + snprintf(cur, 64, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid->Data1, uuid->Data2, uuid->Data3, + uuid->Data4[0], uuid->Data4[1], + uuid->Data4[2], uuid->Data4[3], + uuid->Data4[4], uuid->Data4[5], + uuid->Data4[6], uuid->Data4[7]); + return cur; +} + + +#if 0 +/* currently unused (do not remove) */ +int +dissect_dcerpc_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, char *drep, + int hfindex, e_uuid_t *pdata) +{ + e_uuid_t uuid; + gchar *uuid_name; + header_field_info* hfi; + + + dcerpc_tvb_get_uuid (tvb, offset, drep, &uuid); + if (tree) { + /* get name of protocol field to prepend it later */ + hfi = proto_registrar_get_nth(hfindex); + + /* look for a registered uuid name */ + uuid_name = dcerpc_get_uuid_name(&uuid, 0); + + if (uuid_name) { + /* we know the name of this uuid */ + proto_tree_add_string_format (tree, hfindex, tvb, offset, 16, "", + "%s: %s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)", + hfi->name, uuid_name, + uuid.Data1, uuid.Data2, uuid.Data3, + uuid.Data4[0], uuid.Data4[1], + uuid.Data4[2], uuid.Data4[3], + uuid.Data4[4], uuid.Data4[5], + uuid.Data4[6], uuid.Data4[7]); + } else { + /* we don't know the name of this uuid */ + proto_tree_add_string_format (tree, hfindex, tvb, offset, 16, "", + "%s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + hfi->name, + uuid.Data1, uuid.Data2, uuid.Data3, + uuid.Data4[0], uuid.Data4[1], + uuid.Data4[2], uuid.Data4[3], + uuid.Data4[4], uuid.Data4[5], + uuid.Data4[6], uuid.Data4[7]); + } + } + if (pdata) { + *pdata = uuid; + } + return offset + 16; +} +#endif + + +/* dissect 64bits integer with alignment of 8 bytes (use this for VT_I8 type only) */ +int +dissect_dcom_I8(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, + int hfindex, unsigned char *pdata) +{ + dcerpc_info *di; + + + di=pinfo->private_data; + if(di->conformant_run){ + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + if (offset % 8) { + offset += 8 - (offset % 8); + } + return dissect_dcerpc_uint64(tvb, offset, pinfo, + tree, drep, hfindex, pdata); +} + + + +/* dissect a dcerpc array size */ +int +dissect_dcom_dcerpc_array_size(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, guint32 *pu32ArraySize) +{ + + + /* en-/disable this by preference setting */ + if (!dcom_prefs_display_unmarshalling_details) { + /* this will read in the data, but prevent output to tree */ + tree = NULL; + } + + offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, + hf_dcom_array_size, pu32ArraySize); + + return offset; +} + + +/* dissect a dcerpc pointer value */ +int +dissect_dcom_dcerpc_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, guint32 *pu32Pointer) +{ + + /* en-/disable this by preference setting */ + if (!dcom_prefs_display_unmarshalling_details) { + /* this will read in the data, but prevent output to tree */ + tree = NULL; + } + + offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, + hf_dcom_pointer_val, pu32Pointer); + + return offset; +} + + +/* mark data as "ToBeDone" */ +/* XXX: handout data to generic "unkown data" dissector? */ +extern int +dissect_dcom_tobedone_data(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, int length) +{ + + if (drep); + if (pinfo); + + + proto_tree_add_uint(tree, hf_dcom_tobedone_len, tvb, offset, length, length); + + proto_tree_add_bytes(tree, hf_dcom_tobedone, tvb, offset, length, + tvb_get_ptr(tvb, offset, length)); + offset += length; + + return offset; +} + + +/* dissect an indexed WORD, something like: "FieldName[1]: 0x1234" */ +int +dissect_dcom_indexed_WORD(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, + int hfindex, guint16 * pu16WORD, int field_index) +{ + guint16 u16WORD; + + + /* dissect the WORD, but don't add to tree */ + dissect_dcom_WORD(tvb, offset, pinfo, NULL /*tree*/, drep, + hfindex, &u16WORD); + + if (tree) { + /* special formatted output of indexed value */ + proto_tree_add_uint_format(tree, hf_dcom_hresult, tvb, offset, 2, (drep[0] & 0x10), + "%s[%u]: 0x%04x", + proto_registrar_get_name(hfindex), + field_index, u16WORD); + } + + offset += 2; + + if (pu16WORD) + *pu16WORD = u16WORD; + + return offset; +} + + +/* dissect an indexed DWORD, something like: "FieldName[1]: 0x12345678" */ +int +dissect_dcom_indexed_DWORD(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, + int hfindex, guint32 * pu32DWORD, int field_index) +{ + guint32 u32DWORD; + + + /* dissect the DWORD, but don't add to tree */ + dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, drep, + hfindex, &u32DWORD); + + if (tree) { + /* special formatted output of indexed value */ + proto_tree_add_uint_format(tree, hf_dcom_hresult, tvb, offset, 4, (drep[0] & 0x10), + "%s[%u]: 0x%08x", + proto_registrar_get_name(hfindex), + field_index, u32DWORD); + } + + offset += 4; + + if (pu32DWORD) + *pu32DWORD = u32DWORD; + + return offset; +} + + +/* dissect hresult field of a usual DCOM call (seperate method, because often used) */ +int +dissect_dcom_HRESULT(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, + guint32 * pu32HResult) +{ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, + hf_dcom_hresult, pu32HResult); + + return offset; +} + + +/* partial results of indexed DCOM subcalls (e.g.: from a kind of array) */ +int +dissect_dcom_indexed_HRESULT(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, + guint32 * pu32HResult, int field_index) +{ + guint32 u32HResult; + + + /* dissect the DWORD, but don't add to tree */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, drep, + hf_dcom_hresult, &u32HResult); + + if (tree) { + /* special formatted output of indexed value */ + proto_tree_add_uint_format(tree, hf_dcom_hresult, tvb, offset-4, 4, (drep[0] & 0x10), + "HResult[%u]: %s (0x%08x)", field_index, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown"), + u32HResult); + } + if (pu32HResult) + *pu32HResult = u32HResult; + + return offset; +} + + + +int +dissect_dcom_COMVERSION(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, + guint16 * pu16VersionMajor, guint16 * pu16VersionMinor) +{ + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_dcom_version_major, pu16VersionMajor); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_dcom_version_minor, pu16VersionMinor); + + return offset; +} + + +int +dissect_dcom_SAFEARRAY(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex) +{ + guint32 u32Dims; + guint16 u16Dims; + guint16 u16Features; + guint32 u32ElementSize; + guint32 u32VarType; + guint32 u32Elements; + guint32 u32Pointer; + guint32 u32BoundElements; + guint32 u32LowBound; + gchar cData[100]; + guint32 u32ArraySize; + guint32 u32Tmp; + guint32 u32VariableOffset; + guint32 u32Data; + guint16 u16Data; + guint8 u8Data; + guint16 u16Locks; + guint16 u16VarType; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32TmpOffset; + + proto_item *feature_item; + proto_tree *feature_tree; + + + /* XXX: which alignment do we need here? */ + + sub_item = proto_tree_add_item(tree, hf_dcom_safearray, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_dcom_safearray); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer); + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_sa_dims32, &u32Dims); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_sa_dims16, &u16Dims); + + /* feature flags */ + u32TmpOffset = dissect_dcom_WORD(tvb, offset, pinfo, NULL, drep, + hf_dcom_sa_features, &u16Features); + feature_item = proto_tree_add_uint (sub_tree, hf_dcom_sa_features, tvb, offset, 2, u16Features); + feature_tree = proto_item_add_subtree (feature_item, ett_dcom_sa_features); + if (feature_tree) { + proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_variant, tvb, offset, 2, u16Features); + proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_dispatch, tvb, offset, 2, u16Features); + proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_unknown, tvb, offset, 2, u16Features); + proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_bstr, tvb, offset, 2, u16Features); + proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_have_vartype, tvb, offset, 2, u16Features); + proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_have_iid, tvb, offset, 2, u16Features); + proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_record, tvb, offset, 2, u16Features); + proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_fixedsize, tvb, offset, 2, u16Features); + proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_embedded, tvb, offset, 2, u16Features); + proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_static, tvb, offset, 2, u16Features); + proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_auto, tvb, offset, 2, u16Features); + } + offset = u32TmpOffset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_sa_element_size, &u32ElementSize); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_sa_locks, &u16Locks); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_sa_vartype16, &u16VarType); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_sa_vartype32, &u32VarType); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_sa_elements, &u32Elements); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_sa_bound_elements, &u32BoundElements); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_sa_low_bound, &u32LowBound); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, drep, &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize * u32ElementSize; + + u32Tmp = u32ArraySize; + while(u32ArraySize--) { + switch(u32VarType) { + case(ETHEREAL_VT_ERROR): + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, drep, + &u32Data); + break; + case(ETHEREAL_VT_I1): + offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_i1, &u8Data); + break; + case(ETHEREAL_VT_I2): + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_i2, &u16Data); + break; + case(ETHEREAL_VT_I4): + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_i4, &u32Data); + break; + case(ETHEREAL_VT_I8): + offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_i8, NULL); + break; + case(ETHEREAL_VT_BSTR): + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_BSTR(tvb, u32VariableOffset, pinfo, sub_tree, drep, + hf_dcom_vt_bstr, cData, sizeof(cData) ); + } + break; + default: + /* XXX: other types possible, but still not implemented: + VT_UNKNOWN + VT_DISPATCH + VT_VARIANT + VT_RECORD + VT_UNKNOWN|VT_RESERVED + */ + u32VariableOffset = dissect_dcom_tobedone_data(tvb, u32VariableOffset, pinfo, sub_tree, drep, + 10000); + } + } + + /* update subtree header */ + proto_item_append_text(sub_item, ": Elements: %u/%u VarType: %s", + u32Elements, u32BoundElements, + val_to_str(u32VarType, dcom_variant_type_vals, "Unknown (0x%08x)") ); + + proto_item_set_len(sub_item, u32VariableOffset - u32SubStart); + + return u32VariableOffset; +} + + + +int +dissect_dcom_VARTYPE(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, + guint16 *pu16VarType) +{ + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep, + hf_dcom_variant_type, pu16VarType); + + return offset; +} + + +int +dissect_dcom_VARIANT(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex) +{ + guint32 u32Size; + guint32 u32RPCRes; + guint16 u16Res; + guint32 u32SubStart; + proto_item *sub_item; + proto_tree *sub_tree; + guint16 u16VarType; + guint32 u32VarType; + + guint8 u8Data; + guint16 u16Data; + guint32 u32Data; + gchar cData[500]; + guint32 u32Pointer; + gfloat f32Data; + gdouble f64Data; + + + /* alignment of 8 needed for a VARIANT */ + if (offset % 8) { + offset += 8 - (offset % 8); + } + + sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_dcom_variant); + u32SubStart = offset; + + /* the following size can be VERY confusing: + * It is NOT the maximum size of the variant, as one could expect, + * but the current size of the variant padded to 8 bytes. + * BUT: The following data does not start AFTER this padding, + * it starts just after the variant-data (without padding)!!! */ + /* Conclusion: the size given here can be LONGER than the actual size */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_variant_size, &u32Size); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_variant_rpc_res, &u32RPCRes); + offset = dissect_dcom_VARTYPE(tvb, offset, pinfo, sub_tree, drep, + &u16VarType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_variant_wres, &u16Res); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_variant_wres, &u16Res); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_variant_wres, &u16Res); + + /* 32 bit VarType (slightly different to the 16 bit one) */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_variant_type32, &u32VarType); + + if (u32VarType & ETHEREAL_VT_BYREF) { + u32VarType &=~ETHEREAL_VT_BYREF; + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer); + } + + switch (u32VarType) { + case(ETHEREAL_VT_EMPTY): + break; + case(ETHEREAL_VT_BOOL): + offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_bool, &u16Data); + break; + case(ETHEREAL_VT_I1): + offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_i1, &u8Data); + break; + case(ETHEREAL_VT_UI1): + offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_ui1, &u8Data); + break; + case(ETHEREAL_VT_I2): + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_i2, &u16Data); + break; + case(ETHEREAL_VT_UI2): + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_ui2, &u16Data); + break; + case(ETHEREAL_VT_I4): + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_i4, &u32Data); + break; + case(ETHEREAL_VT_UI4): + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_ui4, &u32Data); + break; + case(ETHEREAL_VT_R4): + offset = dissect_dcom_FLOAT(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_r4, &f32Data); + break; + case(ETHEREAL_VT_R8): + offset = dissect_dcom_DOUBLE(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_r8, &f64Data); + break; + case(ETHEREAL_VT_DATE): + offset = dissect_dcom_DATE(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_date, &f64Data); + break; + case(ETHEREAL_VT_BSTR): + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_BSTR(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_vt_bstr, cData, sizeof(cData) ); + } + break; + case(ETHEREAL_VT_ARRAY): + offset = dissect_dcom_SAFEARRAY(tvb, offset, pinfo, sub_tree, drep, + 0); + break; + case(ETHEREAL_VT_ERROR): + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, drep, + 0); + break; + case(ETHEREAL_VT_UNKNOWN): + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer); + break; + default: + /* XXX: add more types here! */ + offset = dissect_dcom_tobedone_data(tvb, offset, pinfo, sub_tree, drep, + 10000); + } + + /* update subtree header */ + proto_item_append_text(sub_item, ": %s", + val_to_str(u16VarType, dcom_variant_type_vals, "Unknown (0x%08x)") ); + + proto_item_set_len(sub_item, offset - u32SubStart); + + return offset; +} + + +int +dissect_dcom_append_UUID(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, + int hfindex, gchar *field_name, int field_index) +{ + e_uuid_t uuid; + gchar *uuid_name; + + + offset = dissect_dcom_UUID(tvb, offset, pinfo, tree, drep, + hfindex, &uuid); + + /* update column info now */ + if (check_col(pinfo->cinfo, COL_INFO)) { + /* XXX: improve it: getting the hash value is done the second time here */ + + /* look for a registered uuid name */ + uuid_name = dcerpc_get_uuid_name(&uuid, 0); + + if (field_index != -1) { + col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]=%s", + field_name, field_index, (uuid_name) ? uuid_name : "???"); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%s", + field_name, (uuid_name) ? uuid_name : "???"); + } + } + + return offset; +} + + +/* get a zero terminated wide character string from tvb */ +/* XXX: is there a function existing somewhere, already implementing this? */ +int +dcom_tvb_get_nwstringz0(tvbuff_t *tvb, gint offset, guint32 maxlength, gchar *pszStr) +{ + guint32 u32Idx; + guint32 u32Tmp; + + + /* get LPWSTR to ascii */ + g_assert(maxlength > 0); + u32Idx = 0; + pszStr[0] = 0; + while (u32Idx < maxlength-1) { + /* XXX: is this really correct? */ + /* Is the marshalling direction of an WCHAR always fixed? */ + pszStr[u32Idx] = tvb_get_guint8(tvb, offset++); + u32Tmp = tvb_get_guint8(tvb, offset++); + + if (pszStr[u32Idx] == 0 && u32Tmp == 0) { + pszStr[++u32Idx] = 0; + break; + } + + u32Idx++; + pszStr[u32Idx] = 0; + } + + return offset; +} + + +/* dissect a LPWSTR into a given buffer */ +/* use FT_STRING for hfindex */ +/* u32MaxStr is maximum length of string (including trailing zero) */ +int +dissect_dcom_indexed_LPWSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex, + gchar *pszStr, guint32 u32MaxStr, int field_index) +{ + guint32 u32MaxCount; + guint32 u32Offset; + guint32 u32ArraySize; + guint32 u32StrStart; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + gchar *pszEscaped; + guint32 u32Max = u32MaxStr; + + + /* alignment of 4 needed */ + if (offset % 4) { + offset += 4 - (offset % 4); + } + + /* add subtree item */ + sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, ""); + sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr); + u32SubStart = offset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_max_count, &u32MaxCount); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_offset, &u32Offset); + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, drep, + &u32ArraySize); + + u32ArraySize++; /* u32MaxStr is including zero termination */ + if (u32ArraySize < u32MaxStr) { + u32MaxStr = u32ArraySize; + } + + u32StrStart = offset; + offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, pszStr); + + pszEscaped = g_strescape(pszStr, ""); + proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszEscaped); + + /* update subtree header */ + if (field_index != -1) { + proto_item_set_text(sub_item, "%s[%u]: \"%s\"", + proto_registrar_get_name(hfindex), + field_index, pszEscaped); + } else { + proto_item_append_text(sub_item, "\"%s\"", pszEscaped); + } + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Max = MIN(u32Max, strlen(pszEscaped) + 1); + memcpy(pszStr, pszEscaped, u32Max); + pszStr[u32Max-1] = 0; + + g_free(pszEscaped); + + return offset; +} + + +int +dissect_dcom_LPWSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex, + gchar *pszStr, guint32 u32MaxStr) +{ + + + return dissect_dcom_indexed_LPWSTR(tvb, offset, pinfo, tree, drep, + hfindex, pszStr, u32MaxStr, -1); +} + + +/* dissect a BSTR to tree and into a given buffer (use FT_STRING for hfindex) */ +/* u32MaxStr is maximum length of string (including trailing zero) */ +/* (Hint: the BSTR space is always as long as the maximum size) */ +int +dissect_dcom_BSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex, + gchar *pszStr, guint32 u32MaxStr) +{ + guint32 u32MaxCount; + guint32 u32ArraySize; + guint32 u32StrStart; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32ByteLength; + guint32 u32RealOffset; + gchar* pszEscaped; + guint32 u32Max = u32MaxStr; + + /* alignment of 4 needed */ + if (offset % 4) { + offset += 4 - (offset % 4); + } + + /* add subtree item */ + sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, ""); + sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr); + u32SubStart = offset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_max_count, &u32MaxCount); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_byte_length, &u32ByteLength); + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, drep, + &u32ArraySize); + + u32RealOffset = offset + u32ArraySize*2; + + u32ArraySize++; /* u32MaxStr is including zero termination */ + if (u32ArraySize < u32MaxStr) { + u32MaxStr = u32ArraySize; + } + + u32StrStart = offset; + offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, pszStr); + + pszEscaped = g_strescape(pszStr, ""); + proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszEscaped); + + /* update subtree header */ + proto_item_append_text(sub_item, "\"%s\"", pszEscaped); + proto_item_set_len(sub_item, u32RealOffset - u32SubStart); + + u32Max = MIN(u32Max, strlen(pszEscaped) + 1); + memcpy(pszStr, pszEscaped, u32Max); + pszStr[u32Max-1] = 0; + + g_free(pszEscaped); + + return u32RealOffset; +} + + +/* dissect an DUALSTRINGARRAY */ +int +dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex) +{ + guint16 u16NumEntries; + guint16 u16SecurityOffset; + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + guint32 u32Start; + guint16 u16TowerId; + guint16 u16SecurityAuthnSvc; + guint16 u16SecurityAuthzSvc; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint32 u32StringBindings = 0; + guint32 u32SecurityBindings = 0; + proto_item *subsub_item; + proto_tree *subsub_tree; + guint32 u32SubSubStart; + + + /* add subtree header */ + sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_dcom_dualstringarray); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_dualstringarray_num_entries, &u16NumEntries); + /* from here, alignment is ok */ + u32SubStart = offset - 2; + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_dualstringarray_security_offset, &u16SecurityOffset); + + /* STRINGBINDINGs until first wchar zero */ + while ( tvb_get_ntohs(tvb, offset) ) { + u32StringBindings++; + + subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_string, tvb, offset, 0, FALSE); + subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding); + u32SubSubStart = offset; + + offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, drep, + hf_dcom_dualstringarray_string_tower_id, &u16TowerId); + u32Start = offset; + offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr); + proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_string_network_addr, + tvb, u32Start, offset - u32Start, szStr); + + proto_item_append_text(subsub_item, "[%u]: TowerId=%s, NetworkAddr=\"%s\"", + u32StringBindings, + val_to_str(u16TowerId, hf_dcom_dualstringarray_tower_id_vals, "Unknown (0x%04x"), + szStr); + proto_item_set_len(subsub_item, offset - u32SubSubStart); + } + offset += 2; + + /* SECURITYBINDINGs until first wchar zero */ + while ( tvb_get_ntohs(tvb, offset) ) { + u32SecurityBindings++; + + subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_security, tvb, offset, 0, FALSE); + subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding); + u32SubSubStart = offset; + + offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, drep, + hf_dcom_dualstringarray_security_authn_svc, + &u16SecurityAuthnSvc); + offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, drep, + hf_dcom_dualstringarray_security_authz_svc, + &u16SecurityAuthzSvc); + + u32Start = offset; + offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr); + proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_security_princ_name, + tvb, u32Start, offset - u32Start, szStr); + + proto_item_append_text(subsub_item, "[%u]: AuthnSvc=0x%04x, AuthzSvc=0x%04x, PrincName=\"%s\"", + u32SecurityBindings, u16SecurityAuthnSvc, u16SecurityAuthzSvc, szStr); + proto_item_set_len(subsub_item, offset - u32SubSubStart); + } + offset += 2; + + /* append info to subtree header */ + proto_item_append_text(sub_item, ": STRINGBINDINGs=%u, SECURITYBINDINGs=%u", + u32StringBindings, u32SecurityBindings); + proto_item_set_len(sub_item, offset - u32SubStart); + + return offset; +} + + +/* dissect an STDOBJREF */ +int +dissect_dcom_STDOBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex) +{ + guint32 u32Flags; + guint32 u32PublicRefs; + unsigned char pu64Oxid[8]; + unsigned char pu64Oid[8]; + e_uuid_t ipid; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + if (hfindex); + + /* add subtree header */ + sub_item = proto_tree_add_item(tree, hf_dcom_stdobjref, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_dcom_stdobjref); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_stdobjref_flags, &u32Flags); + /* from here, alignment is ok */ + u32SubStart = offset - 4; + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_stdobjref_public_refs, &u32PublicRefs); + offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_stdobjref_oxid, pu64Oxid); + offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_stdobjref_oid, pu64Oid); + offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_stdobjref_ipid, &ipid); + + /* append info to subtree header */ + proto_item_append_text(sub_item, ": PublicRefs=%u IPID=%s", + u32PublicRefs, dcom_uuid_to_str(&ipid)); + proto_item_set_len(sub_item, offset - u32SubStart); + + return offset; +} + + +/* dissect an OBJREF */ +int +dissect_dcom_OBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex) +{ + guint32 u32Signature; + guint32 u32Flags; + e_uuid_t iid; + e_uuid_t clsid; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + /* add subtree header */ + sub_item = proto_tree_add_item(tree, hf_dcom_objref, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_dcom_objref); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_objref_signature, &u32Signature); + /* from here, alignment is ok */ + u32SubStart = offset - 4; + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_objref_flags, &u32Flags); + offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_objref_iid, &iid); + + + switch(u32Flags) { + case(0x1): /* standard */ +/* XXX: which hfindex to use here? */ + offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex); + offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_objref_resolver_address); + break; + case(0x2): /* handler (untested) */ +/* XXX: which hfindex to use here? */ + offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex); + offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_objref_clsid, &clsid); + offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_objref_resolver_address); + break; + case(0x4): /* XXX: custom */ + offset = dissect_dcom_tobedone_data(tvb, offset, pinfo, sub_tree, drep, 10000); + break; + } + + /* append info to subtree header */ + proto_item_set_len(sub_item, offset - u32SubStart); + + return offset; +} + + + +/* dissect an MInterfacePointer */ +int +dissect_dcom_MInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex) +{ + guint32 u32CntData; + guint32 u32ArraySize; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + if (!hfindex) { + hfindex = hf_dcom_interface_pointer; + } + + /* add subtree header */ + sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, FALSE); + sub_tree = proto_item_add_subtree(sub_item, ett_dcom_interface_pointer); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, + hf_dcom_ip_cnt_data, &u32CntData); + u32SubStart = offset - 4; + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, drep, &u32ArraySize); + + offset = dissect_dcom_OBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex); + + /* append info to subtree header */ + proto_item_set_len(sub_item, offset - u32SubStart); + + return offset; +} + + +/* dissect a pointer to a MInterfacePointer */ +int +dissect_dcom_PMInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex) +{ + guint32 u32Pointer; + + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, drep, hfindex); + } + + return offset; +} + + + +void dcom_register_server_coclass(int proto, int ett, e_uuid_t *uuid, guint16 ver, + dcerpc_sub_dissector *sub_dissectors, int opnum_hf) { + + /* XXX: this must be simply the name registration of the UUID, + * not a whole sub_dissector registration */ + /* but this is currently not possible :-( */ +/* dcerpc_init_uuid (proto, ett, uuid, ver, sub_dissectors, opnum_hf);*/ +} + + +void +proto_register_dcom (void) +{ + + static hf_register_info hf_dcom_this_array[] = { + { &hf_dcom_this_version_major, + { "VersionMajor", "dcom.this.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_this_version_minor, + { "VersionMinor", "dcom.this.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_this_flags, + { "Flags", "dcom.this.flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_this_res, + { "Reserved", "dcom.this.res", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_this_cid, + { "Causality ID", "dcom.this.uuid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }} + }; + + static hf_register_info hf_dcom_that_array[] = { + { &hf_dcom_that_flags, + { "Flags", "dcom.that.flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }} + }; + + static hf_register_info hf_dcom_extent_array[] = { + { &hf_dcom_extent, + { "Extension", "dcom.extent", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_dcom_extent_array_count, + { "Extension Count", "dcom.extent.array_count", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_extent_array_res, + { "Reserved", "dcom.extent.array_res", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_extent_size, + { "Extension Size", "dcom.extent.size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_extent_id, + { "Extension Id", "dcom.extent.id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }} + }; + + static hf_register_info hf_dcom_array[] = { + { &hf_dcom_version_major, + { "VersionMajor", "dcom.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_version_minor, + { "VersionMinor", "dcom.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_hresult, + { "HResult", "dcom.hresult", FT_UINT32, BASE_HEX, VALS(dcom_hresult_vals), 0x0, "", HFILL }}, + { &hf_dcom_max_count, + { "MaxCount", "dcom.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_offset, + { "Offset", "dcom.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_byte_length, + { "ByteLength", "dcom.byte_length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_actual_count, + { "ActualCount", "dcom.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_tobedone, + { "ToBeDone", "dcom.tobedone", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_tobedone_len, + { "ToBeDoneLen", "dcom.tobedone_len", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_variant, + { "Variant", "dcom.variant", FT_NONE, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_variant_type, + { "VarType", "dcom.variant_type", FT_UINT16, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, "", HFILL }}, + { &hf_dcom_variant_type32, + { "VarType32", "dcom.variant_type32", FT_UINT32, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, "", HFILL }}, + { &hf_dcom_variant_size, + { "Size", "dcom.variant_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_variant_rpc_res, + { "RPC-Reserved", "dcom.variant_rpc_res", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_variant_wres, + { "Reserved", "dcom.variant_wres", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_array_size, + { "(ArraySize)", "dcom.array_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_pointer_val, + { "(PointerVal)", "dcom.pointer_val", FT_UINT32, BASE_HEX, VALS(dcom_dcerpc_pointer_vals), 0x0, "", HFILL }} + }; + + static hf_register_info hf_dcom_interface_pointer_array[] = { + { &hf_dcom_interface_pointer, + { "InterfacePointer", "dcom.ifp", FT_NONE, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_ip_cnt_data, + { "CntData", "dcom.ip_cnt_data", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }} + }; + + static hf_register_info hf_dcom_objref_array[] = { + { &hf_dcom_objref, + { "OBJREF", "dcom.objref", FT_NONE, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_objref_signature, + { "Signature", "dcom.objref.signature", FT_UINT32, BASE_HEX, VALS(dcom_objref_signature_vals), 0x0, "", HFILL }}, + { &hf_dcom_objref_flags, + { "Flags", "dcom.objref.flags", FT_UINT32, BASE_HEX, VALS(dcom_objref_flag_vals), 0x0, "", HFILL }}, + { &hf_dcom_objref_iid, + { "IID", "dcom.objref.iid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_dcom_objref_clsid, + { "CLSID", "dcom.objref.clsid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_dcom_objref_resolver_address, + { "ResolverAddress", "dcom.objref.resolver_address", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }} + }; + + static hf_register_info hf_dcom_stdobjref_array[] = { + { &hf_dcom_stdobjref, + { "STDOBJREF", "dcom.stdobjref", FT_NONE, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_stdobjref_flags, + { "Flags", "dcom.stdobjref.flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_stdobjref_public_refs, + { "PublicRefs", "dcom.stdobjref.public_refs", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_stdobjref_oxid, + { "OXID", "dcom.stdobjref.oxid", FT_UINT64, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_stdobjref_oid, + { "OID", "dcom.stdobjref.oid", FT_UINT64, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_stdobjref_ipid, + { "IPID", "dcom.stdobjref.ipid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }} + }; + + static hf_register_info hf_dcom_dualstringarray_array[] = { + { &hf_dcom_dualstringarray_num_entries, + { "NumEntries", "dcom.dualstringarray.num_entries", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_dualstringarray_security_offset, + { "SecurityOffset", "dcom.dualstringarray.security_offset", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_dualstringarray_string, + { "StringBinding", "dcom.dualstringarray.string", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_dcom_dualstringarray_string_tower_id, + { "TowerId", "dcom.dualstringarray.tower_id", FT_UINT16, BASE_HEX, VALS(hf_dcom_dualstringarray_tower_id_vals), 0x0, "", HFILL }}, + { &hf_dcom_dualstringarray_string_network_addr, + { "NetworkAddr", "dcom.dualstringarray.network_addr", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_dcom_dualstringarray_security, + { "SecurityBinding", "dcom.dualstringarray.security", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_dcom_dualstringarray_security_authn_svc, + { "AuthnSvc", "dcom.dualstringarray.security_authn_svc", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_dualstringarray_security_authz_svc, + { "AuthzSvc", "dcom.dualstringarray.security_authz_svc", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_dualstringarray_security_princ_name, + { "PrincName", "dcom.dualstringarray.security_princ_name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }} + }; + + static hf_register_info hf_dcom_vt_array[] = { + { &hf_dcom_vt_bool, + { "VT_BOOL", "dcom.vt.bool", FT_UINT16, BASE_HEX, VALS(dcom_vt_bool_vals), 0x0, "", HFILL }}, + { &hf_dcom_vt_i1, + { "VT_I1", "dcom.vt.i1", FT_INT8, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_vt_i2, + { "VT_I2", "dcom.vt.i2", FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_vt_i4, + { "VT_I4", "dcom.vt.i4", FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_vt_i8, + { "VT_I8", "dcom.vt.i8", FT_INT64, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_vt_ui1, + { "VT_UI1", "dcom.vt.ui1", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_vt_ui2, + { "VT_UI2", "dcom.vt.ui2", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_vt_ui4, + { "VT_UI4", "dcom.vt.ui4", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_vt_r4, + { "VT_R4", "dcom.vt.r4", FT_FLOAT, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_dcom_vt_r8, + { "VT_R8", "dcom.vt.r8", FT_DOUBLE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_dcom_vt_date, + { "VT_DATE", "dcom.vt.date", FT_DOUBLE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_dcom_vt_bstr, + { "VT_BSTR", "dcom.vt.bstr", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }} + }; + + static hf_register_info hf_dcom_sa_array[] = { + { &hf_dcom_safearray, + { "SAFEARRAY", "dcom.sa", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_dcom_sa_dims32, + { "Dims32", "dcom.sa.dims32", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_sa_dims16, + { "Dims16", "dcom.sa.dims16", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_sa_features, + { "Features", "dcom.sa.features", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_sa_element_size, + { "ElementSize", "dcom.sa.element_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_sa_locks, + { "Locks", "dcom.sa.locks", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_sa_vartype32, + { "VarType32", "dcom.sa.vartype", FT_UINT32, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, "", HFILL }}, + { &hf_dcom_sa_vartype16, + { "VarType16", "dcom.sa.vartype", FT_UINT16, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, "", HFILL }}, + { &hf_dcom_sa_elements, + { "Elements", "dcom.sa.elements", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_sa_bound_elements, + { "BoundElements", "dcom.sa.bound_elements", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_dcom_sa_low_bound, + { "LowBound", "dcom.sa.low_bound", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + + { &hf_dcom_sa_features_auto, + { "AUTO", "dcom.sa.features_auto", FT_BOOLEAN, 16, TFS (&flags_set_truth), ETHEREAL_FADF_AUTO, "", HFILL }}, + { &hf_dcom_sa_features_static, + { "STATIC", "dcom.sa.features_static", FT_BOOLEAN, 16, TFS (&flags_set_truth), ETHEREAL_FADF_STATIC, "", HFILL }}, + { &hf_dcom_sa_features_embedded, + { "EMBEDDED", "dcom.sa.features_embedded", FT_BOOLEAN, 16, TFS (&flags_set_truth), ETHEREAL_FADF_EMBEDDED, "", HFILL }}, + { &hf_dcom_sa_features_fixedsize, + { "FIXEDSIZE", "dcom.sa.features_fixedsize", FT_BOOLEAN, 16, TFS (&flags_set_truth), ETHEREAL_FADF_FIXEDSIZE, "", HFILL }}, + { &hf_dcom_sa_features_record, + { "RECORD", "dcom.sa.features_record", FT_BOOLEAN, 16, TFS (&flags_set_truth), ETHEREAL_FADF_RECORD, "", HFILL }}, + { &hf_dcom_sa_features_have_iid, + { "HAVEIID", "dcom.sa.features_have_iid", FT_BOOLEAN, 16, TFS (&flags_set_truth), ETHEREAL_FADF_HAVEIID, "", HFILL }}, + { &hf_dcom_sa_features_have_vartype, + { "HAVEVARTYPE", "dcom.sa.features_have_vartype", FT_BOOLEAN, 16, TFS (&flags_set_truth), ETHEREAL_FADF_HAVEVARTYPE, "", HFILL }}, + { &hf_dcom_sa_features_bstr, + { "BSTR", "dcom.sa.features_bstr", FT_BOOLEAN, 16, TFS (&flags_set_truth), ETHEREAL_FADF_BSTR, "", HFILL }}, + { &hf_dcom_sa_features_unknown, + { "UNKNOWN", "dcom.sa.features_unknown", FT_BOOLEAN, 16, TFS (&flags_set_truth), ETHEREAL_FADF_UNKNOWN, "", HFILL }}, + { &hf_dcom_sa_features_dispatch, + { "DISPATCH", "dcom.sa.features_dispatch", FT_BOOLEAN, 16, TFS (&flags_set_truth), ETHEREAL_FADF_DISPATCH, "", HFILL }}, + { &hf_dcom_sa_features_variant, + { "VARIANT", "dcom.sa.features_variant", FT_BOOLEAN, 16, TFS (&flags_set_truth), ETHEREAL_FADF_VARIANT, "", HFILL }} + }; + + static gint *ett_dcom[] = { + &ett_dcom_this, + &ett_dcom_that, + &ett_dcom_extent, + &ett_dcom_lpwstr, + &ett_dcom_interface_pointer, + &ett_dcom_objref, + &ett_dcom_stdobjref, + &ett_dcom_dualstringarray, + &ett_dcom_dualstringarray_binding, + &ett_dcom_variant, + &ett_dcom_safearray, + &ett_dcom_sa_features + }; + + module_t *dcom_module; + + + /* currently, the DCOM protocol "itself" has no real protocol dissector */ + /* we only need this, to register some generic elements */ + proto_dcom = proto_register_protocol ("DCOM", "DCOM", "dcom"); + proto_register_field_array(proto_dcom, hf_dcom_this_array, array_length(hf_dcom_this_array)); + proto_register_field_array(proto_dcom, hf_dcom_that_array, array_length(hf_dcom_that_array)); + proto_register_field_array(proto_dcom, hf_dcom_extent_array, array_length(hf_dcom_extent_array)); + proto_register_field_array(proto_dcom, hf_dcom_array, array_length(hf_dcom_array)); + proto_register_field_array(proto_dcom, hf_dcom_objref_array, array_length(hf_dcom_objref_array)); + proto_register_field_array(proto_dcom, hf_dcom_stdobjref_array, array_length(hf_dcom_stdobjref_array)); + proto_register_field_array(proto_dcom, hf_dcom_dualstringarray_array, array_length(hf_dcom_dualstringarray_array)); + proto_register_field_array(proto_dcom, hf_dcom_interface_pointer_array, array_length(hf_dcom_interface_pointer_array)); + proto_register_field_array(proto_dcom, hf_dcom_vt_array, array_length(hf_dcom_vt_array)); + proto_register_field_array(proto_dcom, hf_dcom_sa_array, array_length(hf_dcom_sa_array)); + proto_register_subtree_array (ett_dcom, array_length (ett_dcom)); + + + /* preferences */ + dcom_module = prefs_register_protocol(proto_dcom, proto_reg_handoff_dcom); + + prefs_register_bool_preference(dcom_module, "display_unmarshalling_details", + "Display DCOM unmarshalling details", + "Display some DCOM unmarshalled fields " + "usually hidden", + &dcom_prefs_display_unmarshalling_details); +} + + +void +proto_reg_handoff_dcom (void) +{ + + /* Currently, we have nothing to register for DCOM */ +} + diff --git a/epan/dissectors/packet-dcom.h b/epan/dissectors/packet-dcom.h new file mode 100644 index 0000000000..091f1bf866 --- /dev/null +++ b/epan/dissectors/packet-dcom.h @@ -0,0 +1,158 @@ +/* packet-dcom.h + * Routines for DCOM generics + * + * $Id$ + * + * Ethereal - 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PACKET_DCERPC_DCOM_H +#define __PACKET_DCERPC_DCOM_H + + +extern const value_string dcom_hresult_vals[]; +extern const value_string dcom_variant_type_vals[]; + +/* preferences */ +extern int dcom_prefs_display_unmarshalling_details; + + +/* the essential DCOM this and that, starting every call */ +extern int +dissect_dcom_this(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep); +extern int +dissect_dcom_that(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep); + + +/* dissection of somewhat more simple data types */ +#define dissect_dcom_BOOLEAN dissect_ndr_uint8 +#define dissect_dcom_BYTE dissect_ndr_uint8 +#define dissect_dcom_WORD dissect_ndr_uint16 +#define dissect_dcom_DWORD dissect_ndr_uint32 +#define dissect_dcom_ID dissect_ndr_uint64 +#define dissect_dcom_UUID dissect_ndr_uuid_t +#define dissect_dcom_FILETIME dissect_ndr_uint64 /* ToBeDone */ +#define dissect_dcom_VARIANT_BOOL dissect_ndr_uint16 +#define dissect_dcom_FLOAT dissect_ndr_float +#define dissect_dcom_DOUBLE dissect_ndr_double +#define dissect_dcom_DATE dissect_ndr_double + +extern int +dissect_dcom_append_UUID(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, + int hfindex, gchar *field_name, int field_index); + +extern int +dissect_dcom_indexed_WORD(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, + int hfindex, guint16 * pu16WORD, int field_index); + +extern int +dissect_dcom_indexed_DWORD(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, + int hfindex, guint32 * pu32DWORD, int field_index); + +extern int +dissect_dcom_HRESULT(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, guint32 * pu32hresult); + +extern int +dissect_dcom_indexed_HRESULT(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, + guint32 * pu32hresult, int field_index); + +extern int +dissect_dcom_COMVERSION(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, + guint16 * pu16version_major, guint16 * pu16version_minor); + +extern int +dissect_dcom_LPWSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex, + gchar *psz_buffer, guint32 u32max_buffer); + +extern int +dissect_dcom_indexed_LPWSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex, + gchar *pszStr, guint32 u32MaxStr, int field_index); + +extern int +dissect_dcom_BSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex, + gchar *psz_buffer, guint32 u32max_buffer); + +extern int +dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex); + +extern int +dissect_dcom_STDOBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex); + +extern int +dissect_dcom_OBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex); + +extern int +dissect_dcom_MInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex); +extern int +dissect_dcom_PMInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex); + +extern int +dissect_dcom_VARTYPE(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, + guint16 *pu16Vartype); + +extern int +dissect_dcom_VARIANT(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, int hfindex); + +/* dcom "dcerpc internal" unmarshalling */ +extern int +dissect_dcom_dcerpc_array_size(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, guint32 *pu32array_size); + +extern int +dissect_dcom_dcerpc_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, guint32 *pu32pointer); + +/* mark things to be done */ +extern int +dissect_dcom_tobedone_data(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, int length); + +/* very simple parameter-profiles dissectors (for very simple requests ;-) */ +/* request: no parameters */ +extern int +dissect_dcom_simple_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep); +/* response: only HRESULT */ +extern int +dissect_dcom_simple_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep); + +void dcom_register_server_coclass(int proto, int ett, + e_uuid_t *uuid, guint16 ver, + dcerpc_sub_dissector *sub_dissectors, int opnum_hf); + +#endif /* packet-dcerpc-dcom.h */