diff options
author | ulfl <ulfl@f5534014-38df-0310-8fa8-9805f1628bb7> | 2006-08-11 19:15:12 +0000 |
---|---|---|
committer | ulfl <ulfl@f5534014-38df-0310-8fa8-9805f1628bb7> | 2006-08-11 19:15:12 +0000 |
commit | a5ff7961c30f0ff0fd480b6f82426c2e380ba2bb (patch) | |
tree | 74f0bfcbe9f7f0b8c52cb3c6b22a0726a0bcc4a7 /epan | |
parent | 17d776e90c75c2ece7a681dd0e39b227f606c4ea (diff) |
add an experimental DCOM object "database" based on the exchanged interface pointers
add a lot more PROFINET CBA dissection output based on these DCOM context information
still need some improvements, e.g. dissection uses a simple (slow) linear list search
changes are fuzz-tested
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@18882 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-dcom-cba-acco.c | 1598 | ||||
-rw-r--r-- | epan/dissectors/packet-dcom-cba-acco.h | 50 | ||||
-rw-r--r-- | epan/dissectors/packet-dcom-cba.c | 100 | ||||
-rw-r--r-- | epan/dissectors/packet-dcom-dispatch.c | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-dcom-oxid.c | 4 | ||||
-rw-r--r-- | epan/dissectors/packet-dcom-remact.c | 28 | ||||
-rw-r--r-- | epan/dissectors/packet-dcom-remunkn.c | 64 | ||||
-rw-r--r-- | epan/dissectors/packet-dcom-sysact.c | 4 | ||||
-rw-r--r-- | epan/dissectors/packet-dcom.c | 313 | ||||
-rw-r--r-- | epan/dissectors/packet-dcom.h | 52 |
10 files changed, 2076 insertions, 139 deletions
diff --git a/epan/dissectors/packet-dcom-cba-acco.c b/epan/dissectors/packet-dcom-cba-acco.c index c2d7b351bb..10468460bb 100644 --- a/epan/dissectors/packet-dcom-cba-acco.c +++ b/epan/dissectors/packet-dcom-cba-acco.c @@ -34,6 +34,8 @@ #include <glib.h> #include <epan/packet.h> #include <epan/expert.h> +#include <epan/emem.h> +#include <epan/addr_resolv.h> #include "packet-dcerpc.h" #include "packet-dcom.h" #include "packet-dcom-cba-acco.h" @@ -73,6 +75,14 @@ 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_connect_in = -1; +static int hf_cba_disconnect_in = -1; +static int hf_cba_connectcr_in = -1; +static int hf_cba_disconnectcr_in = -1; +static int hf_cba_disconnectme_in = -1; +static int hf_cba_data_first_in = -1; +static int hf_cba_data_last_in = -1; + static int hf_cba_acco_server_pICBAAccoCallback = -1; static int hf_cba_acco_server_first_connect = -1; @@ -136,6 +146,8 @@ gint ett_cba_getconnectionout = -1; gint ett_cba_readitemout = -1; gint ett_cba_writeitemin = -1; gint ett_cba_acco_serversrt_cr_flags = -1; +gint ett_cba_frame_info = -1; +gint ett_cba_conn_info = -1; static int proto_ICBAAccoMgt = -1; static gint ett_ICBAAccoMgt = -1; @@ -240,6 +252,788 @@ static const true_false_string cba_acco_call_flags = { "Provider calls Consumer (FALSE)" }; +static const value_string cba_qos_type_short_vals[] = { + { 0x00, "DCOM" }, + { 0x01, "DCOM(sec)" }, /* obsolete */ + { 0x02, "Status" }, + { 0x03, "HMI" }, + { 0x20, "Const" }, + { 0x30, "SRT" }, + { 0, NULL } +}; + + +typedef struct cba_frame_s { + cba_ldev_t *consparent; + cba_ldev_t *provparent; + GList *conns; + guint packet_connect; + guint packet_disconnect; + guint packet_disconnectme; + guint packet_first; + guint packet_last; + + guint16 length; + const guint8 consmac[6]; + guint16 conscrid; + guint32 provcrid; + guint32 conncrret; + guint16 qostype; + guint16 qosvalue; + guint16 offset; +} cba_frame_t; + +typedef struct cba_connection_s { + cba_ldev_t *consparentacco; + cba_ldev_t *provparentacco; + cba_frame_t *parentframe; + guint packet_connect; + guint packet_disconnect; + guint packet_disconnectme; + guint packet_first; + guint packet_last; + + guint16 length; + guint32 consid; + guint32 provid; + const gchar *provitem; + guint32 connret; + guint16 typedesclen; + guint16 *typedesc; + guint16 qostype; + guint16 qosvalue; + guint16 frame_offset; +} cba_connection_t; + + +typedef struct server_frame_call_s { + guint frame_count; + cba_frame_t **frames; +} server_frame_call_t; + + +typedef struct server_connect_call_s { + guint conn_count; + cba_frame_t *frame; + cba_connection_t **conns; +} server_connect_call_t; + +typedef struct server_disconnectme_call_s { + cba_ldev_t *cons; + cba_ldev_t *prov; +} server_disconnectme_call_t; + + +GList *cba_pdevs; + + +void +cba_connection_dump(cba_connection_t *conn, char *role) +{ + if(conn->qostype != 0x30) { + g_warning(" %s#%5u: CID:0x%8x PID:0x%8x PItem:\"%s\" Type:%s QoS:%s/%u Ret:%s Data#%5u-#%5u", + role, + conn->packet_connect, + conn->consid, conn->provid, conn->provitem, + conn->typedesclen != 0 ? val_to_str(conn->typedesc[0], dcom_variant_type_vals, "Unknown (0x%08x)") : "-", + val_to_str(conn->qostype, cba_qos_type_short_vals, "0x%x"), conn->qosvalue, + conn->connret==-1 ? "[pending]" : val_to_str(conn->connret, dcom_hresult_vals, "Unknown (0x%08x)"), + conn->packet_first, conn->packet_last); + } else { + g_warning(" %s#%5u: CID:0x%8x PID:0x%8x PItem:\"%s\" Type:%s QoS:%s/%u Ret:%s Off:%u", + role, + conn->packet_connect, + conn->consid, conn->provid, conn->provitem, + conn->typedesclen != 0 ? val_to_str(conn->typedesc[0], dcom_variant_type_vals, "Unknown (0x%08x)") : "-", + val_to_str(conn->qostype, cba_qos_type_short_vals, "0x%x"), conn->qosvalue, + conn->connret==-1 ? "[pending]" : val_to_str(conn->connret, dcom_hresult_vals, "Unknown (0x%08x)"), + conn->frame_offset); + } +} + + +void +cba_object_dump(void) +{ + GList *pdevs; + GList *ldevs; + GList *frames; + GList *conns; + cba_pdev_t *pdev; + cba_ldev_t *ldev; + cba_frame_t *frame; + + + + + for(pdevs = cba_pdevs; pdevs != NULL; pdevs = g_list_next(pdevs)) { + pdev = pdevs->data; + g_warning("PDev #%5u: %s IFs:%u", pdev->first_packet, ip_to_str(pdev->ip), + pdev->object ? g_list_length(pdev->object->interfaces) : 0); + + for(ldevs = pdev->ldevs; ldevs != NULL; ldevs = g_list_next(ldevs)) { + ldev = ldevs->data; + g_warning(" LDev#%5u: \"%s\" LDevIFs:%u AccoIFs:%u", ldev->first_packet, ldev->name, + ldev->ldev_object ? g_list_length(ldev->ldev_object->interfaces) : 0, + ldev->acco_object ? g_list_length(ldev->acco_object->interfaces) : 0); + for(frames = ldev->consframes; frames != NULL; frames = g_list_next(frames)) { + frame = frames->data; + g_warning(" ConsFrame#%5u: CCRID:0x%x PCRID:0x%x Len:%u Ret:%s Data#%5u-#%5u", + frame->packet_connect, frame->conscrid, frame->provcrid, frame->length, + frame->conncrret==-1 ? "[pending]" : val_to_str(frame->conncrret, dcom_hresult_vals, "Unknown (0x%08x)"), + frame->packet_first, frame->packet_last); + for(conns = frame->conns; conns != NULL; conns = g_list_next(conns)) { + cba_connection_dump(conns->data, "ConsConn"); + } + } + for(frames = ldev->provframes; frames != NULL; frames = g_list_next(frames)) { + frame = frames->data; + g_warning(" ProvFrame#%5u: CCRID:0x%x PCRID:0x%x Len:%u Ret:%s Data#%5u-#%5u", + frame->packet_connect, frame->conscrid, frame->provcrid, frame->length, + frame->conncrret==-1 ? "[pending]" : val_to_str(frame->conncrret, dcom_hresult_vals, "Unknown (0x%08x)"), + frame->packet_first, frame->packet_last); + for(conns = frame->conns; conns != NULL; conns = g_list_next(conns)) { + cba_connection_dump(conns->data, "ProvConn"); + } + } + for(conns = ldev->consconns; conns != NULL; conns = g_list_next(conns)) { + cba_connection_dump(conns->data, "ConsConn"); + } + for(conns = ldev->provconns; conns != NULL; conns = g_list_next(conns)) { + cba_connection_dump(conns->data, "ProvConn"); + } + } + } +} + + +cba_pdev_t * +cba_pdev_find(packet_info *pinfo, const char *ip, e_uuid_t *ipid) +{ + cba_pdev_t *pdev; + dcom_interface_t *interf; + + + interf = dcom_interface_find(pinfo, ip, ipid); + if(interf != NULL) { + pdev = interf->parent->private_data; + if(pdev == NULL) { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "pdev_find: no pdev for IP:%s IPID:%s", + ip_to_str(ip), dcom_uuid_to_str(ipid)); + } + } else { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "pdev_find: unknown interface of IP:%s IPID:%s", + ip_to_str(ip), dcom_uuid_to_str(ipid)); + pdev = NULL; + } + + return pdev; +} + + +cba_pdev_t * +cba_pdev_add(packet_info *pinfo, const char *ip) +{ + GList *cba_iter; + cba_pdev_t *pdev; + + + /* find pdev */ + for(cba_iter = cba_pdevs; cba_iter != NULL; cba_iter = g_list_next(cba_iter)) { + pdev = cba_iter->data; + if(memcmp(pdev->ip, ip, 4) == 0) { + return pdev; + } + } + + /* not found, create a new */ + pdev = se_alloc(sizeof(cba_pdev_t)); + memcpy( (void *) (pdev->ip), ip, 4); + pdev->first_packet = pinfo->fd->num; + pdev->ldevs = NULL; + pdev->object = NULL; + cba_pdevs = g_list_append(cba_pdevs, pdev); + + return pdev; +} + + +void +cba_pdev_link(packet_info *pinfo, cba_pdev_t *pdev, dcom_interface_t *pdev_interf) +{ + + /* "crosslink" pdev interface and it's object */ + pdev->object = pdev_interf->parent; + pdev_interf->private_data = pdev; + if(pdev_interf->parent) { + pdev_interf->parent->private_data = pdev; + } +} + + +void +cba_ldev_link(packet_info *pinfo, cba_ldev_t *ldev, dcom_interface_t *ldev_interf) +{ + + /* "crosslink" interface and it's object */ + ldev->ldev_object = ldev_interf->parent; + ldev_interf->private_data = ldev; + if(ldev_interf->parent) { + ldev_interf->parent->private_data = ldev; + } +} + + +void +cba_ldev_link_acco(packet_info *pinfo, cba_ldev_t *ldev, dcom_interface_t *acco_interf) +{ + + /* "crosslink" interface and it's object */ + ldev->acco_object = acco_interf->parent; + acco_interf->private_data = ldev; + if(acco_interf->parent) { + acco_interf->parent->private_data = ldev; + } +} + + +cba_ldev_t * +cba_ldev_add(packet_info *pinfo, cba_pdev_t *pdev, const char *name) +{ + GList *cba_iter; + cba_ldev_t *ldev; + + + /* find ldev */ + for(cba_iter = pdev->ldevs; cba_iter != NULL; cba_iter = g_list_next(cba_iter)) { + ldev = cba_iter->data; + if(strcmp(ldev->name, name) == 0) { + return ldev; + } + } + + /* not found, create a new */ + ldev = se_alloc(sizeof(cba_ldev_t)); + ldev->name = se_strdup(name); + ldev->first_packet = pinfo->fd->num; + ldev->ldev_object = NULL; + ldev->acco_object = NULL; + ldev->parent = pdev; + + ldev->provframes = NULL; + ldev->consframes = NULL; + ldev->provconns = NULL; + ldev->consconns = NULL; + + pdev->ldevs = g_list_append(pdev->ldevs, ldev); + + return ldev; +} + + +cba_ldev_t * +cba_ldev_find(packet_info *pinfo, const gchar *ip, e_uuid_t *ipid) { + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + dcom_interface_t *interf; + cba_ldev_t *ldev; + + + interf = dcom_interface_find(pinfo, ip, ipid); + if(interf != NULL) { + ldev = interf->private_data; + + if(ldev == NULL) { + ldev = interf->parent->private_data; + } + if(ldev == NULL) { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "ldev_find: no ldev for IP:%s IPID:%s", + ip_to_str(ip), dcom_uuid_to_str(&info->call_data->object_uuid)); + } + } else { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "ldev_find: unknown interface of IP:%s IPID:%s", + ip_to_str(ip), dcom_uuid_to_str(&info->call_data->object_uuid)); + ldev = NULL; + } + + /*g_warning("cba_ldev_find#%u: private:0x%x parent:0x%x", + pinfo->fd->num, interf->private_data, interf->parent ? interf->parent->private_data: NULL);*/ + + return ldev; +} + + +cba_ldev_t * +cba_acco_add(packet_info *pinfo, const char *acco) +{ + char *ip_str; + char *delim; + guint32 ip; + cba_pdev_t *pdev; + cba_ldev_t *ldev; + + + ip_str = g_strdup(acco); + delim = strchr(ip_str, '!'); + if(delim == NULL) { + g_free(ip_str); + return NULL; + } + *delim = 0; + + if(!get_host_ipaddr(ip_str, &ip)) { + g_free(ip_str); + return NULL; + } + ip = ntohl(ip); + + pdev = cba_pdev_add(pinfo, (char *) &ip); + delim++; + + ldev = cba_ldev_add(pinfo, pdev, delim); + + g_free(ip_str); + + return ldev; +} + + +gboolean +cba_packet_in_range(packet_info *pinfo, guint packet_connect, guint packet_disconnect, guint packet_disconnectme) +{ + + if(packet_connect == 0) { + g_warning("cba_packet_in_range#%u: packet_connect not set?", pinfo->fd->num); + } + + if(packet_connect == 0 || pinfo->fd->num < packet_connect) { + return FALSE; + } + if(packet_disconnect != 0 && pinfo->fd->num > packet_disconnect) { + return FALSE; + } + if(packet_disconnectme != 0 && pinfo->fd->num > packet_disconnectme) { + return FALSE; + } + + return TRUE; +} + + +void +cba_frame_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, cba_frame_t *frame) +{ + proto_item *item; + proto_item *sub_item; + proto_tree *sub_tree; + + if (tree) { + sub_item = proto_tree_add_text(tree, tvb, 0, 0, "Cons:\"%s\" CCRID:0x%x Prov:\"%s\" PCRID:0x%x QoS:%s/%ums Len:%u", + frame->consparent ? frame->consparent->name : "", frame->conscrid, + frame->provparent ? frame->provparent->name : "", frame->provcrid, + val_to_str(frame->qostype, cba_qos_type_short_vals, "%u"), frame->qosvalue, frame->length); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_frame_info); + PROTO_ITEM_SET_GENERATED(sub_item); + + item = proto_tree_add_uint(sub_tree, hf_cba_acco_conn_qos_type, tvb, 0, 0, frame->qostype); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_conn_qos_value, tvb, 0, 0, frame->qosvalue); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_serversrt_cr_id, tvb, 0, 0, frame->conscrid); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_prov_crid, tvb, 0, 0, frame->provcrid); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_serversrt_cr_length, tvb, 0, 0, frame->length); + PROTO_ITEM_SET_GENERATED(item); + + if(frame->consparent != NULL) { + item = proto_tree_add_string(sub_tree, hf_cba_acco_conn_consumer, tvb, 0, 0, frame->consparent->name); + PROTO_ITEM_SET_GENERATED(item); + } + if(frame->provparent != NULL) { + item = proto_tree_add_string(sub_tree, hf_cba_acco_conn_provider, tvb, 0, 0, frame->provparent->name); + PROTO_ITEM_SET_GENERATED(item); + } + + item = proto_tree_add_uint(sub_tree, hf_cba_connectcr_in, + tvb, 0, 0, frame->packet_connect); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_data_first_in, + tvb, 0, 0, frame->packet_first); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_data_last_in, + tvb, 0, 0, frame->packet_last); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_disconnectcr_in, + tvb, 0, 0, frame->packet_disconnect); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_disconnectme_in, + tvb, 0, 0, frame->packet_disconnectme); + PROTO_ITEM_SET_GENERATED(item); + } +} + + +cba_frame_t * +cba_frame_connect(packet_info *pinfo, cba_ldev_t *cons_ldev, cba_ldev_t *prov_ldev, + guint16 qostype, guint16 qosvalue, const guint8 *consmac, guint16 conscrid, guint16 length) +{ + GList *cba_iter; + cba_frame_t *frame; + + /* find frame */ + for(cba_iter = cons_ldev->consframes; cba_iter != NULL; cba_iter = g_list_next(cba_iter)) { + frame = cba_iter->data; + if( frame->conscrid == conscrid && + memcmp(frame->consmac, consmac, 6) == 0 && + cba_packet_in_range(pinfo, frame->packet_connect, frame->packet_disconnect, frame->packet_disconnectme)) { + return frame; + } + } + + frame = se_alloc(sizeof(cba_frame_t)); + + frame->consparent = cons_ldev; + frame->provparent = prov_ldev; + + frame->packet_connect = pinfo->fd->num; + frame->packet_disconnect = 0; + frame->packet_disconnectme = 0; + frame->packet_first = 0; + frame->packet_last = 0; + + frame->length = length; + memcpy( (guint8 *) (frame->consmac), consmac, sizeof(frame->consmac)); + frame->conscrid = conscrid; + frame->qostype = qostype; + frame->qosvalue = qosvalue; + + frame->offset = 4; + frame->conns = NULL; + + frame->provcrid = 0; + frame->conncrret = -1; + + cons_ldev->consframes = g_list_append(cons_ldev->consframes, frame); + prov_ldev->provframes = g_list_append(prov_ldev->provframes, frame); + + return frame; +} + + +void +cba_frame_disconnect(packet_info *pinfo, cba_frame_t *frame) +{ + + if(frame->packet_disconnect == 0) { + frame->packet_disconnect = pinfo->fd->num; + } + + if(frame->packet_disconnect != pinfo->fd->num) { + g_warning("cba_frame_disconnect#%u: frame already disconnected in #%u", + pinfo->fd->num, frame->packet_disconnect); + } +} + + +void +cba_frame_disconnectme(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, cba_ldev_t *cons_ldev, cba_ldev_t *prov_ldev) +{ + GList *frames; + cba_frame_t *frame; + + + for(frames = cons_ldev->consframes; frames != NULL; frames = g_list_next(frames)) { + frame = frames->data; + + if( frame->provparent == prov_ldev && + cba_packet_in_range(pinfo, frame->packet_connect, frame->packet_disconnect, frame->packet_disconnectme)) { + + cba_frame_info(tvb, pinfo, tree, frame); + + if(frame->packet_disconnectme == 0) { + frame->packet_disconnectme = pinfo->fd->num; + } + + if(frame->packet_disconnectme != pinfo->fd->num) { + g_warning("cba_frame_disconnectme#%u: frame already disconnectme'd in #%u", + pinfo->fd->num, frame->packet_disconnectme); + } + } + } +} + + +cba_frame_t * +cba_frame_find_by_cons(packet_info *pinfo, const guint8 *consmac, guint16 conscrid) +{ + GList *pdevs; + GList *ldevs; + GList *frames; + cba_pdev_t *pdev; + cba_ldev_t *ldev; + cba_frame_t *frame; + + + /* find pdev */ + for(pdevs = cba_pdevs; pdevs != NULL; pdevs = g_list_next(pdevs)) { + pdev = pdevs->data; + + /* find ldev */ + for(ldevs = pdev->ldevs; ldevs != NULL; ldevs = g_list_next(ldevs)) { + ldev = ldevs->data; + + /* find frame */ + for(frames = ldev->consframes; frames != NULL; frames = g_list_next(frames)) { + frame = frames->data; + + if( frame->conscrid == conscrid && + memcmp(frame->consmac, consmac, 6) == 0 && + cba_packet_in_range(pinfo, frame->packet_connect, frame->packet_disconnect, frame->packet_disconnectme)) { + return frame; + } + } + } + } + + return NULL; +} + + +cba_frame_t * +cba_frame_find_by_provcrid(packet_info *pinfo, cba_ldev_t *prov_ldev, guint32 provcrid) +{ + GList *frames; + cba_frame_t *frame; + + + if(prov_ldev == NULL) { + return NULL; + } + + for(frames = prov_ldev->provframes; frames != NULL; frames = g_list_next(frames)) { + frame = frames->data; + + if( frame->provcrid == provcrid && + cba_packet_in_range(pinfo, frame->packet_connect, frame->packet_disconnect, frame->packet_disconnectme)) { + return frame; + } + } + + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, + "find_by_provcrid: couldn't find provider frame for ProvCRID:0x%x", provcrid); + + return NULL; +} + + +void +cba_frame_incoming_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, cba_frame_t *frame) +{ + if(frame->packet_first == 0) { + frame->packet_first = pinfo->fd->num; + } + + if( pinfo->fd->num > frame->packet_last && + cba_packet_in_range(pinfo, frame->packet_connect, frame->packet_disconnect, frame->packet_disconnectme)) { + frame->packet_last = pinfo->fd->num; + } +} + + +void +cba_connection_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, cba_connection_t *conn) +{ + proto_item *item; + proto_item *sub_item; + proto_tree *sub_tree; + + if (tree) { + if(conn->qostype != 0x30) { + sub_item = proto_tree_add_text(tree, tvb, 0, 0, "ProvItem:\"%s\" PID:0x%x CID:0x%x QoS:%s/%ums", + conn->provitem, conn->provid, conn->consid, + val_to_str(conn->qostype, cba_qos_type_short_vals, "%u"), conn->qosvalue); + } else { + sub_item = proto_tree_add_text(tree, tvb, 0, 0, "ProvItem:\"%s\" PID:0x%x CID:0x%x Len:%u", + conn->provitem, conn->provid, conn->consid, conn->length); + } + sub_tree = proto_item_add_subtree(sub_item, ett_cba_conn_info); + PROTO_ITEM_SET_GENERATED(sub_item); + + item = proto_tree_add_string(sub_tree, hf_cba_acco_conn_provider_item, tvb, 0, 0 /* len */, conn->provitem); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_conn_prov_id, tvb, 0, 0 /* len */, conn->provid); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_conn_cons_id, tvb, 0, 0 /* len */, conn->consid); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_serversrt_record_length, tvb, 0, 0 /* len */, conn->length); + PROTO_ITEM_SET_GENERATED(item); + + if(conn->qostype != 0x30) { + item = proto_tree_add_uint(sub_tree, hf_cba_acco_conn_qos_type, + tvb, 0, 0, conn->qostype); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_conn_qos_value, + tvb, 0, 0, conn->qosvalue); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_connect_in, + tvb, 0, 0, conn->packet_connect); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_data_first_in, + tvb, 0, 0, conn->packet_first); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_data_last_in, + tvb, 0, 0, conn->packet_last); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_disconnect_in, + tvb, 0, 0, conn->packet_disconnect); + PROTO_ITEM_SET_GENERATED(item); + item = proto_tree_add_uint(sub_tree, hf_cba_disconnectme_in, + tvb, 0, 0, conn->packet_disconnectme); + PROTO_ITEM_SET_GENERATED(item); + } + } +} + + +cba_connection_t * +cba_connection_connect(packet_info *pinfo, cba_ldev_t *cons_ldev, cba_ldev_t *prov_ldev, cba_frame_t *cons_frame, + guint16 qostype, guint16 qosvalue, const char *provitem, guint32 consid, guint16 length, + guint16 *typedesc, guint16 typedesclen) +{ + GList *cba_iter; + cba_connection_t *conn; + + + /* find connection */ + if(cons_frame != NULL) { + /* SRT: search in frame */ + for(cba_iter = cons_frame->conns; cba_iter != NULL; cba_iter = g_list_next(cba_iter)) { + conn = cba_iter->data; + if(conn->consid == consid) { + return conn; + } + } + } else { + /* DCOM: search in ldev */ + for(cba_iter = cons_ldev->consconns; cba_iter != NULL; cba_iter = g_list_next(cba_iter)) { + conn = cba_iter->data; + if( conn->consid == consid && + cba_packet_in_range(pinfo, conn->packet_connect, conn->packet_disconnect, conn->packet_disconnectme)) { + return conn; + } + } + } + + conn = se_alloc(sizeof(cba_connection_t)); + + conn->consparentacco = cons_ldev; + conn->provparentacco = prov_ldev; + conn->parentframe = cons_frame; + + conn->packet_connect = pinfo->fd->num; + conn->packet_disconnect = 0; + conn->packet_disconnectme = 0; + conn->packet_first = 0; + conn->packet_last = 0; + + conn->consid = consid; + conn->provitem = se_strdup(provitem); + conn->typedesclen = typedesclen; + conn->typedesc = typedesc; + conn->qostype = qostype; + conn->qosvalue = qosvalue; + conn->length = length; + + conn->provid = 0; + conn->connret = -1; + + if(cons_frame != NULL) { + conn->frame_offset = cons_frame->offset; + conn->length = length; + cons_frame->offset += length; + cons_frame->conns = g_list_append(cons_frame->conns, conn); + } else { + conn->frame_offset = 0; + cons_ldev->consconns = g_list_append(cons_ldev->consconns, conn); + prov_ldev->provconns = g_list_append(prov_ldev->provconns, conn); + } + + return conn; +} + + +void +cba_connection_disconnect(packet_info *pinfo, cba_connection_t *conn) +{ + /* XXX - detect multiple disconnects? */ + if(conn->packet_disconnect == 0) { + conn->packet_disconnect = pinfo->fd->num; + } + + if(conn->packet_disconnect != pinfo->fd->num) { + g_warning("connection_disconnect#%u: already disconnected"); + } +} + + +void +cba_connection_disconnectme(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, cba_ldev_t *cons_ldev, cba_ldev_t *prov_ldev) +{ + GList *conns; + cba_connection_t *conn; + + + for(conns = cons_ldev->consframes; conns != NULL; conns = g_list_next(conns)) { + conn = conns->data; + + if( conn->provparentacco == prov_ldev && + cba_packet_in_range(pinfo, conn->packet_connect, conn->packet_disconnect, conn->packet_disconnectme)) { + + cba_connection_info(tvb, pinfo, tree, conn); + + if(conn->packet_disconnectme == 0) { + conn->packet_disconnectme = pinfo->fd->num; + } + + if(conn->packet_disconnectme != pinfo->fd->num) { + g_warning("connection_disconnectme#%u: already disconnectme'd"); + } + } + } +} + + +cba_connection_t * +cba_connection_find_by_provid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, cba_ldev_t *prov_ldev, guint32 provid) +{ + GList *cba_iter; + cba_connection_t *conn; + + + for(cba_iter = prov_ldev->provconns; cba_iter != NULL; cba_iter = g_list_next(cba_iter)) { + conn = cba_iter->data; + if( conn->provid == provid && + cba_packet_in_range(pinfo, conn->packet_connect, conn->packet_disconnect, conn->packet_disconnectme)) { + return conn; + } + } + return NULL; +} + + +void +cba_connection_incoming_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, cba_connection_t *conn) +{ + if(conn->packet_first == 0) { + conn->packet_first = pinfo->fd->num; + } + + if( pinfo->fd->num > conn->packet_last && + cba_packet_in_range(pinfo, conn->packet_connect, conn->packet_disconnect, conn->packet_disconnectme)) { + conn->packet_last = pinfo->fd->num; + } +} + /* dissect a response containing an array of hresults (e.g: ICBAAccoMgt::RemoveConnections) */ static int @@ -285,7 +1079,7 @@ dissect_HResultArray_resp(tvbuff_t *tvb, int offset, static int -dissect_ICBAAccoServer_HResultArray_resp(tvbuff_t *tvb, int offset, +dissect_ICBAAccoServer_SetActivation_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { guint32 u32HResult; @@ -332,7 +1126,54 @@ dissect_ICBAAccoServer_HResultArray_resp(tvbuff_t *tvb, int offset, static int -dissect_ICBAAccoServerSRT_HResultArray_resp(tvbuff_t *tvb, int offset, +dissect_ICBAAccoServerSRT_Disconnect_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; + proto_item *item; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); + PROTO_ITEM_SET_GENERATED(item); + pinfo->profinet_type = 3; + + 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_ICBAAccoServerSRT_SetActivation_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { guint32 u32HResult; @@ -401,10 +1242,19 @@ dissect_ICBAAccoServer_Connect_rqst(tvbuff_t *tvb, int offset, guint32 u32MaxConsLen = sizeof(szCons); guint32 u32Idx; proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + dcom_interface_t *cons_interf; + cba_ldev_t *cons_ldev; + cba_ldev_t *prov_ldev; + cba_connection_t *conn; + server_connect_call_t *call; offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, pinfo->net_dst.data, &info->call_data->object_uuid); + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, TRUE); PROTO_ITEM_SET_GENERATED(item); pinfo->profinet_type = 2; @@ -412,6 +1262,9 @@ dissect_ICBAAccoServer_Connect_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, hf_cba_acco_conn_consumer, szCons, u32MaxConsLen); + /* find the consumer ldev by it's name */ + cons_ldev = cba_acco_add(pinfo, szCons); + 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, @@ -419,7 +1272,16 @@ dissect_ICBAAccoServer_Connect_rqst(tvbuff_t *tvb, int offset, 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_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0, &cons_interf); + if(cons_interf == NULL) { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, + "Server_Connect: consumer interface invalid"); + } + + /* "crosslink" consumer interface and it's object */ + if(cons_interf != NULL && cons_ldev != NULL) { + cba_ldev_link_acco(pinfo, cons_ldev, cons_interf); + } offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, hf_cba_acco_count, &u32Count); @@ -427,6 +1289,17 @@ dissect_ICBAAccoServer_Connect_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, &u32ArraySize); + /* link connections infos to the call */ + if(prov_ldev != NULL && cons_ldev != NULL) { + call = se_alloc(sizeof(server_connect_call_t) + u32ArraySize * sizeof(cba_connection_t *)); + call->conn_count = 0; + call->frame = NULL; + call->conns = (cba_connection_t **) (call+1); + info->call_data->private_data = call; + } else{ + call = NULL; + } + u32VariableOffset = offset + u32ArraySize*16; /* array of CONNECTINs */ @@ -459,6 +1332,24 @@ dissect_ICBAAccoServer_Connect_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, hf_cba_acco_conn_cons_id, &u32ConsID); + /* add to object database */ + if(prov_ldev != NULL && cons_ldev != NULL) { + conn = cba_connection_connect(pinfo, cons_ldev, prov_ldev, /*cons_frame*/ NULL, + u16QoSType, u16QoSValue, szItem, u32ConsID, 0, + /* XXX - VarType must be translated to new type description if it includes an array (0x2000) */ + se_memdup(&u16VarType, 2), 1); + + cba_connection_info(tvb, pinfo, sub_tree, conn); + } else { + conn = NULL; + } + + /* add to current call */ + if(call != NULL) { + call->conn_count++; + call->conns[u32Idx-1] = conn; + } + /* update subtree header */ proto_item_append_text(sub_item, "[%u]: ConsID=0x%x, ProvItem=\"%s\", VarType=%s", u32Idx, u32ConsID, szItem, @@ -502,10 +1393,20 @@ dissect_ICBAAccoServer2_Connect2_rqst(tvbuff_t *tvb, int offset, guint32 u32Idx2; guint16 u16VarType2 = -1; proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + dcom_interface_t *cons_interf; + cba_ldev_t *prov_ldev; + cba_ldev_t *cons_ldev; + cba_connection_t *conn; + server_connect_call_t *call = NULL; + guint16 typedesclen = 0; + guint16 *typedesc = NULL; offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, pinfo->net_dst.data, &info->call_data->object_uuid); item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, TRUE); PROTO_ITEM_SET_GENERATED(item); @@ -514,6 +1415,9 @@ dissect_ICBAAccoServer2_Connect2_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, hf_cba_acco_conn_consumer, szCons, u32MaxConsLen); + /* find the consumer ldev by it's name */ + cons_ldev = cba_acco_add(pinfo, szCons); + 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, @@ -521,7 +1425,23 @@ dissect_ICBAAccoServer2_Connect2_rqst(tvbuff_t *tvb, int offset, 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_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, drep, 0, &cons_interf); + if(cons_interf == NULL) { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, + "Server2_Connect2: consumer interface invalid"); + } + } else { + /* GetConnectionData do it this way */ + cons_interf = NULL; + } + + /* "crosslink" consumer interface and it's object */ + if(cons_interf != NULL && cons_ldev != NULL) { + cba_ldev_link_acco(pinfo, cons_ldev, cons_interf); + } offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, hf_cba_acco_count, &u32Count); @@ -529,6 +1449,17 @@ dissect_ICBAAccoServer2_Connect2_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, &u32ArraySize); + /* link connection infos to the call */ + if(prov_ldev != NULL && cons_ldev != NULL) { + call = se_alloc(sizeof(server_connect_call_t) + u32ArraySize * sizeof(cba_connection_t *)); + call->conn_count = 0; + call->frame = NULL; + call->conns = (cba_connection_t **) (call+1); + info->call_data->private_data = call; + } else{ + call = NULL; + } + u32VariableOffset = offset + u32ArraySize*20; /* array of CONNECTINs */ @@ -557,12 +1488,26 @@ dissect_ICBAAccoServer2_Connect2_rqst(tvbuff_t *tvb, int offset, u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, drep, &u32ArraySize2); + /* limit the allocation to a reasonable size */ + if(u32ArraySize2 < 1000) { + typedesc = se_alloc0(u32ArraySize2 * 2); + typedesclen = u32ArraySize2; + } else { + typedesc = NULL; + typedesclen = 0; + } + /* 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); + + if(typedesc != NULL && u32Idx2 <= typedesclen) { + typedesc[u32Idx2-1] = u16VarType; + } + /* remember first VarType only */ if (u32Idx2 == 1) { u16VarType2 = u16VarType; @@ -582,6 +1527,23 @@ dissect_ICBAAccoServer2_Connect2_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, hf_cba_acco_conn_cons_id, &u32ConsID); + /* add to object database */ + if(prov_ldev != NULL && cons_ldev != NULL) { + conn = cba_connection_connect(pinfo, cons_ldev, prov_ldev, /*cons_frame*/ NULL, + u16QoSType, u16QoSValue, szItem, u32ConsID, 0, + typedesc, typedesclen); + + cba_connection_info(tvb, pinfo, sub_tree, conn); + } else { + conn = NULL; + } + + /* add to current call */ + if(call != NULL) { + call->conn_count++; + call->conns[u32Idx-1] = conn; + } + /* update subtree header */ proto_item_append_text(sub_item, "[%u]: ConsID=0x%x, ProvItem=\"%s\", TypeDesc=%s", u32Idx, u32ConsID, szItem, @@ -605,7 +1567,7 @@ dissect_ICBAAccoServer_Connect_resp(tvbuff_t *tvb, int offset, { guint8 u8FirstConnect; guint32 u32Pointer; - guint32 u32ArraySize; + guint32 u32ArraySize = 0; guint32 u32HResult; guint32 u32Idx = 1; guint32 u32ProvID; @@ -613,10 +1575,19 @@ dissect_ICBAAccoServer_Connect_resp(tvbuff_t *tvb, int offset, proto_tree *sub_tree; guint32 u32SubStart; proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + server_connect_call_t *call = info->call_data->private_data; + cba_connection_t *conn; offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + if(call == NULL) { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, + "Server_Connect: return values ignored from #%u", + info->call_data->req_frame); + } + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); PROTO_ITEM_SET_GENERATED(item); pinfo->profinet_type = 1; @@ -643,6 +1614,15 @@ dissect_ICBAAccoServer_Connect_resp(tvbuff_t *tvb, int offset, offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, drep, &u32HResult, u32Idx); + /* put response data into the connection */ + if(call && u32Idx <= call->conn_count) { + conn = call->conns[u32Idx-1]; + conn->provid = u32ProvID; + conn->connret = u32HResult; + + cba_connection_info(tvb, pinfo, sub_tree, conn); + } + proto_item_append_text(sub_item, "[%u]: ProvID=0x%x %s", u32Idx, u32ProvID, val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); @@ -655,6 +1635,14 @@ dissect_ICBAAccoServer_Connect_resp(tvbuff_t *tvb, int offset, offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); + /* this might be a global HRESULT */ + while(call && u32Idx <= call->conn_count) { + conn = call->conns[u32Idx-1]; + conn->provid = 0; + conn->connret = u32HResult; + u32Idx++; + } + if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, ": %s Cnt=%u -> %s", (u8FirstConnect) ? "First" : "NotFirst", @@ -675,6 +1663,10 @@ dissect_ICBAAccoServer_Disconnect_rqst(tvbuff_t *tvb, int offset, guint32 u32Idx; guint32 u32ProvID; proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + cba_ldev_t *prov_ldev; + cba_connection_t *conn; + server_connect_call_t *call; offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); @@ -689,10 +1681,31 @@ dissect_ICBAAccoServer_Disconnect_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, &u32ArraySize); + prov_ldev = cba_ldev_find(pinfo, pinfo->net_dst.data, &info->call_data->object_uuid); + + /* link connection infos to the call */ + if(prov_ldev != NULL) { + call = se_alloc(sizeof(server_connect_call_t) + u32ArraySize * sizeof(cba_connection_t *)); + call->conn_count = 0; + call->frame = NULL; + call->conns = (cba_connection_t **) (call+1); + info->call_data->private_data = call; + } else{ + call = NULL; + } + u32Idx = 1; while (u32ArraySize--) { offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, drep, hf_cba_acco_conn_prov_id, &u32ProvID, u32Idx); + + /* add to current call */ + if(call != NULL) { + conn = cba_connection_find_by_provid(tvb, pinfo, tree, prov_ldev, u32ProvID); + call->conn_count++; + call->conns[u32Idx-1] = conn; + } + u32Idx++; } @@ -706,6 +1719,69 @@ dissect_ICBAAccoServer_Disconnect_rqst(tvbuff_t *tvb, int offset, static int +dissect_ICBAAccoServer_Disconnect_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; + proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + server_connect_call_t *call = info->call_data->private_data; + cba_connection_t *conn; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + if(call == NULL) { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, + "Server_Disconnect: return values ignored from #%u", + info->call_data->req_frame); + } + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); + PROTO_ITEM_SET_GENERATED(item); + pinfo->profinet_type = 1; + + 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); + + /* mark this connection as disconnected */ + if(call && u32Idx <= call->conn_count) { + conn = call->conns[u32Idx-1]; + cba_connection_disconnect(pinfo, conn); + } + + 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_ICBAAccoServerSRT_Disconnect_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { @@ -745,16 +1821,23 @@ dissect_ICBAAccoServerSRT_Disconnect_rqst(tvbuff_t *tvb, int offset, static int -dissect_ICBAAccoServer_Consumer_rqst(tvbuff_t *tvb, int offset, +dissect_ICBAAccoServer_DisconnectMe_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { gchar szStr[1000]; guint32 u32MaxStr = sizeof(szStr); proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + cba_ldev_t *prov_ldev; + cba_ldev_t *cons_ldev; + server_disconnectme_call_t *call; offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, pinfo->net_dst.data, &info->call_data->object_uuid); + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, TRUE); PROTO_ITEM_SET_GENERATED(item); pinfo->profinet_type = 2; @@ -762,6 +1845,16 @@ dissect_ICBAAccoServer_Consumer_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, hf_cba_acco_conn_consumer, szStr, u32MaxStr); + /* find the consumer ldev by it's name */ + cons_ldev = cba_acco_add(pinfo, szStr); + + if(prov_ldev != NULL && cons_ldev != NULL) { + call = se_alloc(sizeof(server_disconnectme_call_t)); + call->cons = cons_ldev; + call->prov = prov_ldev; + info->call_data->private_data = call; + } + /* update column info now */ if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, " Consumer=\"%s\"", szStr); @@ -771,6 +1864,39 @@ dissect_ICBAAccoServer_Consumer_rqst(tvbuff_t *tvb, int offset, } +static int +dissect_ICBAAccoServer_DisconnectMe_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint32 u32HResult; + proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + server_disconnectme_call_t *call; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); + PROTO_ITEM_SET_GENERATED(item); + pinfo->profinet_type = 1; + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, + &u32HResult); + + call = info->call_data->private_data; + if(call) { + cba_connection_disconnectme(tvb, pinfo, tree, call->cons, call->prov); + } + + 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_ICBAAccoServerSRT_DisconnectMe_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) @@ -778,10 +1904,17 @@ dissect_ICBAAccoServerSRT_DisconnectMe_rqst(tvbuff_t *tvb, int offset, gchar szStr[1000]; guint32 u32MaxStr = sizeof(szStr); proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + cba_ldev_t *prov_ldev; + cba_ldev_t *cons_ldev; + server_disconnectme_call_t *call; offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, pinfo->net_dst.data, &info->call_data->object_uuid); + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, TRUE); PROTO_ITEM_SET_GENERATED(item); pinfo->profinet_type = 4; @@ -789,6 +1922,16 @@ dissect_ICBAAccoServerSRT_DisconnectMe_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, hf_cba_acco_conn_consumer, szStr, u32MaxStr); + /* find the consumer ldev by it's name */ + cons_ldev = cba_acco_add(pinfo, szStr); + + if(prov_ldev != NULL && cons_ldev != NULL) { + call = se_alloc(sizeof(server_disconnectme_call_t)); + call->cons = cons_ldev; + call->prov = prov_ldev; + info->call_data->private_data = call; + } + /* update column info now */ if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, " Consumer=\"%s\"", szStr); @@ -799,22 +1942,29 @@ dissect_ICBAAccoServerSRT_DisconnectMe_rqst(tvbuff_t *tvb, int offset, static int -dissect_ICBAAccoServer_simple_resp(tvbuff_t *tvb, int offset, +dissect_ICBAAccoServerSRT_DisconnectMe_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { guint32 u32HResult; proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + server_disconnectme_call_t *call; offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); - item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); PROTO_ITEM_SET_GENERATED(item); - pinfo->profinet_type = 1; + pinfo->profinet_type = 3; offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); + call = info->call_data->private_data; + if(call) { + cba_frame_disconnectme(tvb, pinfo, tree, call->cons, call->prov); + } + 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)") ); @@ -825,7 +1975,7 @@ dissect_ICBAAccoServer_simple_resp(tvbuff_t *tvb, int offset, static int -dissect_ICBAAccoServerSRT_simple_resp(tvbuff_t *tvb, int offset, +dissect_ICBAAccoServer_Ping_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { guint32 u32HResult; @@ -834,9 +1984,9 @@ dissect_ICBAAccoServerSRT_simple_resp(tvbuff_t *tvb, int offset, offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); - item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); PROTO_ITEM_SET_GENERATED(item); - pinfo->profinet_type = 3; + pinfo->profinet_type = 1; offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); @@ -983,10 +2133,19 @@ dissect_ICBAAccoServerSRT_ConnectCR_rqst(tvbuff_t *tvb, int offset, proto_item *sub_item; proto_tree *sub_tree; guint32 u32SubStart; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + dcom_interface_t *cons_interf; + cba_ldev_t *prov_ldev; + cba_ldev_t *cons_ldev; + cba_frame_t *frame; + server_frame_call_t *call; offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, pinfo->net_dst.data, &info->call_data->object_uuid); + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, TRUE); PROTO_ITEM_SET_GENERATED(item); pinfo->profinet_type = 4; @@ -995,12 +2154,24 @@ dissect_ICBAAccoServerSRT_ConnectCR_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, hf_cba_acco_conn_consumer, szCons, u32MaxConsLen); + /* find the consumer ldev by it's name */ + cons_ldev = cba_acco_add(pinfo, szCons); + 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); + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0, &cons_interf); + if(cons_interf == NULL) { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, + "ServerSRT_ConnectCR: consumer interface invalid"); + } + + /* "crosslink" consumer interface and it's object */ + if(cons_interf != NULL && cons_ldev != NULL) { + cba_ldev_link_acco(pinfo, cons_ldev, cons_interf); + } /* ConsumerMAC (big-endian, 1byte-aligned) */ tvb_memcpy(tvb, u8ConsMac, offset, 6); @@ -1029,6 +2200,16 @@ dissect_ICBAAccoServerSRT_ConnectCR_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, &u32ArraySize); + /* link frame infos to the call */ + if(prov_ldev != NULL && cons_ldev != NULL) { + call = se_alloc(sizeof(server_frame_call_t) + u32ArraySize * sizeof(cba_frame_t *)); + call->frame_count = 0; + call->frames = (cba_frame_t **) (call+1); + info->call_data->private_data = call; + } else{ + call = NULL; + } + u32Idx = 1; while (u32ArraySize--) { /* array of CONNECTINCRs */ @@ -1042,6 +2223,21 @@ dissect_ICBAAccoServerSRT_ConnectCR_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, hf_cba_acco_serversrt_cr_length, &u16CRLength); + /* add to object database */ + if(prov_ldev != NULL && cons_ldev != NULL) { + frame = cba_frame_connect(pinfo, cons_ldev, prov_ldev, u16QoSType, u16QoSValue, u8ConsMac, u16CRID, u16CRLength); + + cba_frame_info(tvb, pinfo, sub_tree, frame); + } else { + frame = NULL; + } + + /* add to current call */ + if(call != NULL) { + call->frame_count++; + call->frames[u32Idx-1] = frame; + } + /* update subtree header */ proto_item_append_text(sub_item, "[%u]: CRID=0x%x, CRLength=%u", u32Idx, u16CRID, u16CRLength); @@ -1076,10 +2272,19 @@ dissect_ICBAAccoServerSRT_ConnectCR_resp(tvbuff_t *tvb, int offset, proto_tree *sub_tree; guint32 u32SubStart; proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + server_frame_call_t *call = info->call_data->private_data; + cba_frame_t *frame; offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + if(call == NULL) { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, + "ServerSRT_ConnectCR: return values ignored from #%u", + info->call_data->req_frame); + } + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); PROTO_ITEM_SET_GENERATED(item); pinfo->profinet_type = 3; @@ -1115,6 +2320,15 @@ dissect_ICBAAccoServerSRT_ConnectCR_resp(tvbuff_t *tvb, int offset, offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, drep, &u32HResult); + /* put response data into the frame */ + if(call && u32Idx <= call->frame_count) { + frame = call->frames[u32Idx-1]; + frame->provcrid = u32ProvCRID; + frame->conncrret = u32HResult; + + cba_frame_info(tvb, pinfo, sub_tree, frame); + } + /* update subtree header */ proto_item_append_text(sub_item, "[%u]: ProvCRID=0x%x, %s", u32Idx, u32ProvCRID, @@ -1128,6 +2342,14 @@ dissect_ICBAAccoServerSRT_ConnectCR_resp(tvbuff_t *tvb, int offset, offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); + /* this might be a global HRESULT */ + while(call && u32Idx <= call->frame_count) { + frame = call->frames[u32Idx-1]; + frame->provcrid = 0; + frame->conncrret = u32HResult; + u32Idx++; + } + if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, ": %s PCRID=0x%x -> %s", (u8FirstConnect) ? "FirstCR" : "NotFirstCR", @@ -1148,9 +2370,16 @@ dissect_ICBAAccoServerSRT_DisconnectCR_rqst(tvbuff_t *tvb, int offset, guint32 u32Idx; guint32 u32ProvCRID; proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + cba_ldev_t *prov_ldev; + cba_frame_t *frame; + server_frame_call_t *call; + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, pinfo->net_dst.data, &info->call_data->object_uuid); item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, TRUE); PROTO_ITEM_SET_GENERATED(item); @@ -1162,10 +2391,28 @@ dissect_ICBAAccoServerSRT_DisconnectCR_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, &u32ArraySize); + /* link frame infos to the call */ + if(prov_ldev != NULL) { + call = se_alloc(sizeof(server_frame_call_t) + u32ArraySize * sizeof(cba_frame_t *)); + call->frame_count = 0; + call->frames = (cba_frame_t **) (call+1); + info->call_data->private_data = call; + } else{ + call = NULL; + } + u32Idx = 1; while (u32ArraySize--) { offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, drep, hf_cba_acco_prov_crid, &u32ProvCRID, u32Idx); + + /* find frame and add it to current call */ + if(call != NULL) { + frame = cba_frame_find_by_provcrid(pinfo, prov_ldev, u32ProvCRID); + call->frame_count++; + call->frames[u32Idx-1] = frame; + } + u32Idx++; } @@ -1179,6 +2426,62 @@ dissect_ICBAAccoServerSRT_DisconnectCR_rqst(tvbuff_t *tvb, int offset, static int +dissect_ICBAAccoServerSRT_DisconnectCR_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; + proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + server_frame_call_t *call = info->call_data->private_data; + cba_frame_t *frame; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); + PROTO_ITEM_SET_GENERATED(item); + pinfo->profinet_type = 3; + + 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); + /* put response data into the frame */ + if(call && u32Idx <= call->frame_count) { + frame = call->frames[u32Idx-1]; + cba_frame_disconnect(pinfo, frame); + } + + 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_ICBAAccoServerSRT_Connect_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { @@ -1203,10 +2506,20 @@ dissect_ICBAAccoServerSRT_Connect_rqst(tvbuff_t *tvb, int offset, guint32 u32ConsID; guint16 u16RecordLength; proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + cba_ldev_t *prov_ldev; + cba_frame_t *frame = NULL; + cba_connection_t *conn; + guint16 typedesclen = 0; + guint16 *typedesc = NULL; + server_connect_call_t *call; offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, pinfo->net_dst.data, &info->call_data->object_uuid); + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, TRUE); PROTO_ITEM_SET_GENERATED(item); pinfo->profinet_type = 4; @@ -1214,6 +2527,12 @@ dissect_ICBAAccoServerSRT_Connect_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, hf_cba_acco_prov_crid, &u32ProvCRID); + frame = cba_frame_find_by_provcrid(pinfo, prov_ldev, u32ProvCRID); + + if(frame != NULL) { + cba_frame_info(tvb, pinfo, tree, frame); + } + offset = dissect_dcom_BYTE(tvb, offset, pinfo, tree, drep, hf_cba_acco_conn_state, &u8State); @@ -1227,6 +2546,17 @@ dissect_ICBAAccoServerSRT_Connect_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, &u32ArraySize); + /* link connections infos to the call */ + if(frame != NULL) { + call = se_alloc(sizeof(server_connect_call_t) + u32ArraySize * sizeof(cba_connection_t *)); + call->conn_count = 0; + call->frame = frame; + call->conns = (cba_connection_t **) (call+1); + info->call_data->private_data = call; + } else{ + call = NULL; + } + u32VariableOffset = offset + u32ArraySize*20; u32Idx = 1; @@ -1255,13 +2585,21 @@ dissect_ICBAAccoServerSRT_Connect_rqst(tvbuff_t *tvb, int offset, u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, drep, &u32ArraySize2); + typedesc = se_alloc0(u32ArraySize2 * 2); + typedesclen = 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 <= typedesclen) { + typedesc[u32Idx2-1] = u16VarType; + } + + /* remember first VarType only */ if (u32Idx2 == 1) { u16VarType2 = u16VarType; } @@ -1277,6 +2615,23 @@ dissect_ICBAAccoServerSRT_Connect_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, drep, hf_cba_acco_serversrt_record_length, &u16RecordLength); + /* add to object database */ + if(frame != NULL) { + conn = cba_connection_connect(pinfo, frame->consparent, frame->provparent, frame, + frame->qostype, frame->qosvalue, szProvItem, u32ConsID, u16RecordLength, + typedesc, typedesclen); + + cba_connection_info(tvb, pinfo, sub_tree, conn); + } else { + conn = NULL; + } + + /* add to current call */ + if(call != NULL) { + call->conn_count++; + call->conns[u32Idx-1] = conn; + } + /* update subtree header */ proto_item_append_text(sub_item, "[%u]: ConsID=0x%x, ProvItem=\"%s\", TypeDesc=%s", u32Idx, u32ConsID, szProvItem, @@ -1312,10 +2667,18 @@ dissect_ICBAAccoServerSRT_Connect_resp(tvbuff_t *tvb, int offset, guint32 u32ProvID; guint32 u32HResult; proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + server_connect_call_t *call = info->call_data->private_data; + cba_connection_t *conn; offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + if(call == NULL) { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, + "ServerSRT_ConnectCR: return values ignored from #%u", info->call_data->req_frame); + } + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); PROTO_ITEM_SET_GENERATED(item); pinfo->profinet_type = 3; @@ -1323,6 +2686,10 @@ dissect_ICBAAccoServerSRT_Connect_resp(tvbuff_t *tvb, int offset, offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer); + if(call && call->frame != NULL) { + cba_frame_info(tvb, pinfo, tree, call->frame); + } + if (u32Pointer) { offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, &u32ArraySize); @@ -1339,6 +2706,15 @@ dissect_ICBAAccoServerSRT_Connect_resp(tvbuff_t *tvb, int offset, offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, drep, &u32HResult, u32Idx); + /* put response data into the frame */ + if(call && u32Idx <= call->conn_count) { + conn = call->conns[u32Idx-1]; + conn->provid = u32ProvID; + conn->connret = u32HResult; + + cba_connection_info(tvb, pinfo, sub_tree, conn); + } + proto_item_append_text(sub_item, "[%u]: ProvID=0x%x %s", u32Idx, u32ProvID, val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); @@ -1351,6 +2727,14 @@ dissect_ICBAAccoServerSRT_Connect_resp(tvbuff_t *tvb, int offset, offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); + /* this might be a global HRESULT */ + while(call && u32Idx <= call->conn_count) { + conn = call->conns[u32Idx-1]; + conn->provid = 0; + conn->connret = u32HResult; + u32Idx++; + } + if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u -> %s", u32Idx-1, @@ -1362,7 +2746,7 @@ dissect_ICBAAccoServerSRT_Connect_resp(tvbuff_t *tvb, int offset, static int -dissect_ICBAAccoMgt2_GetProvIDs_resp(tvbuff_t *tvb, int offset, +dissect_Server_GetProvIDs_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { guint32 u32Count; @@ -1425,7 +2809,7 @@ dissect_ICBAAccoMgt2_GetProvIDs_resp(tvbuff_t *tvb, int offset, static int -dissect_ICBAAccoMgt2_GetProvConnections_rqst(tvbuff_t *tvb, int offset, +dissect_Server_GetProvConnections_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { guint32 u32Count; @@ -1459,7 +2843,7 @@ dissect_ICBAAccoMgt2_GetProvConnections_rqst(tvbuff_t *tvb, int offset, static int -dissect_ICBAAccoMgt2_GetProvConnections_resp(tvbuff_t *tvb, int offset, +dissect_Server_GetProvConnections_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { guint32 u32Count; @@ -1569,7 +2953,7 @@ dissect_ICBAAccoMgt2_GetProvConnections_resp(tvbuff_t *tvb, int offset, int dissect_CBA_Connection_Data(tvbuff_t *tvb, - packet_info *pinfo, proto_tree *tree) + packet_info *pinfo, proto_tree *tree, cba_ldev_t *cons_ldev, cba_frame_t *frame) { guint8 u8Version; guint8 u8Flags; @@ -1593,7 +2977,10 @@ dissect_CBA_Connection_Data(tvbuff_t *tvb, int qc_good = 0; int qc_uncertain = 0; int qc_bad = 0; -/* guint32 bTimeStamped = 0;*/ + GList *conns; + cba_connection_t *conn; + int item_offset; + /*** ALL data in this buffer is NOT aligned and always little endian ordered ***/ @@ -1622,6 +3009,16 @@ dissect_CBA_Connection_Data(tvbuff_t *tvb, offset += 2; u16CountFix = u16Count; + /* show meta information */ + if(frame) { + cba_frame_info(tvb, pinfo, conn_data_tree, frame); + } else { + if(cons_ldev && cons_ldev->name) { + item = proto_tree_add_string(conn_data_tree, hf_cba_acco_conn_consumer, tvb, offset, 0, cons_ldev->name); + PROTO_ITEM_SET_GENERATED(item); + } + } + /* update column info now */ #if 0 if (check_col(pinfo->cinfo, COL_INFO)) @@ -1677,6 +3074,8 @@ dissect_CBA_Connection_Data(tvbuff_t *tvb, 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); + item_offset = offset; + /* add item header fields */ if (sub_tree) { proto_tree_add_item(sub_tree, hf_cba_acco_cb_item_length, tvb, offset, 2, TRUE); @@ -1748,12 +3147,38 @@ dissect_CBA_Connection_Data(tvbuff_t *tvb, tvb_get_ptr(tvb, offset, u16DataLen)); offset += u16DataLen; + if(frame != NULL ) { + /* find offset in SRT */ + /* XXX - expensive! */ + cba_frame_incoming_data(tvb, pinfo, sub_tree, frame); + for(conns = frame->conns; conns != NULL; conns = g_list_next(conns)) { + conn = conns->data; + if(conn->frame_offset == item_offset) { + cba_connection_info(tvb, pinfo, sub_tree, conn); + break; + } + } + } else { + /* find consID in ldev */ + /* XXX - expensive! */ + if(cons_ldev != NULL) { + for(conns = cons_ldev->consconns; conns != NULL; conns = g_list_next(conns)) { + conn = conns->data; + if(conn->consid == u32ID) { + cba_connection_info(tvb, pinfo, sub_tree, conn); + cba_connection_incoming_data(tvb, pinfo, sub_tree, conn); + break; + } + } + } + } + u32ItemIdx++; } if (u8Version == 1) { proto_item_append_text(conn_data_item, - ": Version=0x%x (OnDataChanged), Flags=0x%x, Count=%u", + ": Version=0x%x (DCOM), Flags=0x%x, Count=%u", u8Version, u8Flags, u16CountFix); } else { proto_item_append_text(conn_data_item, @@ -1777,6 +3202,7 @@ dissect_CBA_Connection_Data_heur(tvbuff_t *tvb, guint8 u8Version; guint8 u8Flags; guint16 u16FrameID; + cba_frame_t *frame; /* the tvb will NOT contain the frame_id here! */ u16FrameID = GPOINTER_TO_UINT(pinfo->private_data); @@ -1797,7 +3223,9 @@ dissect_CBA_Connection_Data_heur(tvbuff_t *tvb, if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_add_str(pinfo->cinfo, COL_PROTOCOL, "PN-CBA"); - dissect_CBA_Connection_Data(tvb, pinfo, tree); + frame = cba_frame_find_by_cons(pinfo, pinfo->dl_dst.data, u16FrameID); + + dissect_CBA_Connection_Data(tvb, pinfo, tree, frame ? frame->consparent : NULL, frame); return TRUE; } @@ -1811,10 +3239,15 @@ dissect_ICBAAccoCallback_OnDataChanged_rqst(tvbuff_t *tvb, int offset, guint32 u32ArraySize; tvbuff_t *next_tvb; proto_item *item; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + cba_ldev_t *cons_ldev; offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + /* get corresponding provider ldev */ + cons_ldev = cba_ldev_find(pinfo, pinfo->net_dst.data, &info->call_data->object_uuid); + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); PROTO_ITEM_SET_GENERATED(item); pinfo->profinet_type = 1; @@ -1831,7 +3264,7 @@ dissect_ICBAAccoCallback_OnDataChanged_rqst(tvbuff_t *tvb, int offset, /* dissect PROFINET component data (without header) */ next_tvb = tvb_new_subset(tvb, offset, -1, -1); - offset += dissect_CBA_Connection_Data(next_tvb, pinfo, tree); + offset += dissect_CBA_Connection_Data(next_tvb, pinfo, tree, cons_ldev, NULL /* frame */); /* XXX */ /* tvb_free(next_tvb);*/ @@ -1840,7 +3273,7 @@ dissect_ICBAAccoCallback_OnDataChanged_rqst(tvbuff_t *tvb, int offset, } -static int +static int dissect_ICBAAccoCallback_OnDataChanged_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { @@ -1910,6 +3343,45 @@ dissect_ICBAAccoCallback_Gnip_resp(tvbuff_t *tvb, int offset, static int +dissect_ICBAAccoServer2_GetConnectionData_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + proto_item *item; + cba_ldev_t *cons_ldev; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + cba_ldev_t **call; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, TRUE); + PROTO_ITEM_SET_GENERATED(item); + pinfo->profinet_type = 2; + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, drep, + hf_cba_acco_conn_consumer, szStr, u32MaxStr); + + cons_ldev = cba_acco_add(pinfo, szStr); + + /* link ldev to the call */ + if(cons_ldev != NULL) { + call = se_alloc(sizeof(cba_ldev_t *)); + *call = cons_ldev; + info->call_data->private_data = call; + } + + /* 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_ICBAAccoServer2_GetConnectionData_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { @@ -1919,10 +3391,18 @@ dissect_ICBAAccoServer2_GetConnectionData_resp(tvbuff_t *tvb, int offset, guint32 u32Pointer; guint32 u32HResult; proto_item *item; - + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + cba_ldev_t **call = info->call_data->private_data; + cba_ldev_t *cons_ldev = (call!=NULL) ? *call : NULL; + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + if(cons_ldev == NULL) { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, + "Server2_GCD: return values ignored from #%u", info->call_data->req_frame); + } + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); PROTO_ITEM_SET_GENERATED(item); pinfo->profinet_type = 1; @@ -1942,7 +3422,7 @@ dissect_ICBAAccoServer2_GetConnectionData_resp(tvbuff_t *tvb, int offset, /* dissect PROFINET component data (without header) */ next_tvb = tvb_new_subset(tvb, offset, -1, -1); - offset += dissect_CBA_Connection_Data(next_tvb, pinfo, tree); + offset += dissect_CBA_Connection_Data(next_tvb, pinfo, tree, (call != NULL) ? *call : NULL, NULL /* frame */); /* XXX */ /* tvb_free(next_tvb);*/ @@ -2106,14 +3586,18 @@ dissect_ICBAAccoMgt_AddConnections_resp(tvbuff_t *tvb, int offset, 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", u32Count); + } + } + 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, + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); } @@ -3148,8 +4632,8 @@ static dcerpc_sub_dissector ICBAAccoMgt_dissectors[] = { {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_ICBAAccoMgt2_GetProvIDs_resp }, - {18, "GetProvConnections", dissect_ICBAAccoMgt2_GetProvConnections_rqst, dissect_ICBAAccoMgt2_GetProvConnections_resp }, + {17, "GetProvIDs", dissect_dcom_simple_rqst, dissect_Server_GetProvIDs_resp }, + {18, "GetProvConnections", dissect_Server_GetProvConnections_rqst, dissect_Server_GetProvConnections_resp }, {19, "GetDiagnosis", dissect_ICBAAccoMgt_GetDiagnosis_rqst, dissect_ICBAAccoMgt_GetDiagnosis_resp }, { 0, NULL, NULL, NULL }, }; @@ -3175,13 +4659,13 @@ static dcerpc_sub_dissector ICBAAccoServer_dissectors[] = { { 2, "Release", NULL, NULL }, { 3, "Connect", dissect_ICBAAccoServer_Connect_rqst, dissect_ICBAAccoServer_Connect_resp }, - { 4, "Disconnect", dissect_ICBAAccoServer_Disconnect_rqst, dissect_ICBAAccoServer_HResultArray_resp }, - { 5, "DisconnectMe", dissect_ICBAAccoServer_Consumer_rqst, dissect_ICBAAccoServer_simple_resp }, - { 6, "SetActivation", dissect_ICBAAccoServer_SetActivation_rqst, dissect_ICBAAccoServer_HResultArray_resp }, - { 7, "Ping", dissect_ICBAAccoServer_Ping_rqst, dissect_ICBAAccoServer_simple_resp }, + { 4, "Disconnect", dissect_ICBAAccoServer_Disconnect_rqst, dissect_ICBAAccoServer_Disconnect_resp }, + { 5, "DisconnectMe", dissect_ICBAAccoServer_DisconnectMe_rqst, dissect_ICBAAccoServer_DisconnectMe_resp }, + { 6, "SetActivation", dissect_ICBAAccoServer_SetActivation_rqst, dissect_ICBAAccoServer_SetActivation_resp }, + { 7, "Ping", dissect_ICBAAccoServer_Ping_rqst, dissect_ICBAAccoServer_Ping_resp }, /* stage 2 */ { 8, "Connect2", dissect_ICBAAccoServer2_Connect2_rqst, dissect_ICBAAccoServer_Connect_resp }, - { 9, "GetConnectionData", dissect_ICBAAccoServer_Consumer_rqst, dissect_ICBAAccoServer2_GetConnectionData_resp }, + { 9, "GetConnectionData", dissect_ICBAAccoServer2_GetConnectionData_rqst, dissect_ICBAAccoServer2_GetConnectionData_resp }, { 0, NULL, NULL, NULL }, }; @@ -3193,12 +4677,11 @@ static dcerpc_sub_dissector ICBAAccoServerSRT_dissectors[] = { { 2, "Release", NULL, NULL }, { 3, "ConnectCR", dissect_ICBAAccoServerSRT_ConnectCR_rqst, dissect_ICBAAccoServerSRT_ConnectCR_resp }, - { 4, "DisconnectCR", dissect_ICBAAccoServerSRT_DisconnectCR_rqst, dissect_ICBAAccoServerSRT_HResultArray_resp }, + { 4, "DisconnectCR", dissect_ICBAAccoServerSRT_DisconnectCR_rqst, dissect_ICBAAccoServerSRT_DisconnectCR_resp }, { 5, "Connect", dissect_ICBAAccoServerSRT_Connect_rqst, dissect_ICBAAccoServerSRT_Connect_resp }, - { 6, "Disconnect", dissect_ICBAAccoServerSRT_Disconnect_rqst, dissect_ICBAAccoServerSRT_HResultArray_resp }, - { 7, "DisconnectMe", dissect_ICBAAccoServerSRT_DisconnectMe_rqst, dissect_ICBAAccoServerSRT_simple_resp }, - { 8, "SetActivation", dissect_ICBAAccoServerSRT_SetActivation_rqst, dissect_ICBAAccoServerSRT_HResultArray_resp }, - + { 6, "Disconnect", dissect_ICBAAccoServerSRT_Disconnect_rqst, dissect_ICBAAccoServerSRT_Disconnect_resp }, + { 7, "DisconnectMe", dissect_ICBAAccoServerSRT_DisconnectMe_rqst, dissect_ICBAAccoServerSRT_DisconnectMe_resp }, + { 8, "SetActivation", dissect_ICBAAccoServerSRT_SetActivation_rqst, dissect_ICBAAccoServerSRT_SetActivation_resp }, { 0, NULL, NULL, NULL }, }; @@ -3373,6 +4856,27 @@ proto_register_dcom_cba_acco (void) { "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 }}, + { &hf_cba_connect_in, + { "Connect in frame", "cba.connect_in", FT_FRAMENUM, BASE_NONE, + NULL, 0, "This connection Connect was in the packet with this number", HFILL }}, + { &hf_cba_disconnect_in, + { "Disconnect in frame", "cba.disconnect_in", FT_FRAMENUM, BASE_NONE, + NULL, 0, "This connection Disconnect was in the packet with this number", HFILL }}, + { &hf_cba_connectcr_in, + { "ConnectCR in frame", "cba.connect_in", FT_FRAMENUM, BASE_NONE, + NULL, 0, "This frame ConnectCR was in the packet with this number", HFILL }}, + { &hf_cba_disconnectcr_in, + { "DisconnectCR in frame", "cba.disconnect_in", FT_FRAMENUM, BASE_NONE, + NULL, 0, "This frame DisconnectCR was in the packet with this number", HFILL }}, + { &hf_cba_disconnectme_in, + { "DisconnectMe in frame", "cba.disconnectme_in", FT_FRAMENUM, BASE_NONE, + NULL, 0, "This connection/frame DisconnectMe was in the packet with this number", HFILL }}, + { &hf_cba_data_first_in, + { "First data in frame", "cba.data_first_in", FT_FRAMENUM, BASE_NONE, + NULL, 0, "The first data of this connection/frame in the packet with this number", HFILL }}, + { &hf_cba_data_last_in, + { "Last data in frame", "cba.data_last_in", FT_FRAMENUM, BASE_NONE, + NULL, 0, "The last data of this connection/frame in the packet with this number", HFILL }}, }; ett5[0] = &ett_ICBAAccoMgt; @@ -3414,11 +4918,13 @@ proto_register_dcom_cba_acco (void) 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; + ett5[0] = &ett_ICBAAccoSync; + ett5[1] = &ett_cba_readitemout; + ett5[2] = &ett_cba_writeitemin; + ett5[3] = &ett_cba_frame_info; + ett5[4] = &ett_cba_conn_info; proto_ICBAAccoSync = proto_register_protocol ("ICBAAccoSync", "ICBAAccoSync", "cba_acco_sync"); - proto_register_subtree_array (ett3, array_length (ett3)); + proto_register_subtree_array (ett5, array_length (ett5)); } diff --git a/epan/dissectors/packet-dcom-cba-acco.h b/epan/dissectors/packet-dcom-cba-acco.h index 73ca6441ee..d7d2438a0a 100644 --- a/epan/dissectors/packet-dcom-cba-acco.h +++ b/epan/dissectors/packet-dcom-cba-acco.h @@ -25,8 +25,54 @@ #ifndef __PACKET_DCERPC_DCOM_CBA_ACCO_H #define __PACKET_DCERPC_DCOM_CBA_ACCO_H -int +typedef struct cba_pdev_s { + GList *ldevs; + dcom_object_t *object; + gint first_packet; + + const guint8 ip[4]; +} cba_pdev_t; + +typedef struct cba_ldev_s { + GList *provframes; + GList *consframes; + GList *provconns; + GList *consconns; + dcom_object_t *ldev_object; + dcom_object_t *acco_object; + cba_pdev_t *parent; + gint first_packet; + + const char *name; +} cba_ldev_t; + + +extern GList *cba_pdevs; + +extern cba_pdev_t * +cba_pdev_find(packet_info *pinfo, const char *ip, e_uuid_t *ipid); + +extern void +cba_pdev_link(packet_info *pinfo, cba_pdev_t *pdev, dcom_interface_t *pdev_interf); + +extern cba_pdev_t * +cba_pdev_add(packet_info *pinfo, const char *ip); + +extern void +cba_ldev_link(packet_info *pinfo, cba_ldev_t *ldev, dcom_interface_t *ldev_interf); + +extern void +cba_ldev_link_acco(packet_info *pinfo, cba_ldev_t *ldev, dcom_interface_t *acco_interf); + +extern cba_ldev_t * +cba_ldev_find(packet_info *pinfo, const gchar *ip, e_uuid_t *ipid); + +extern cba_ldev_t * +cba_ldev_add(packet_info *pinfo, cba_pdev_t *pdev, const char *name); + + +/*int dissect_CBA_Connection_Data(tvbuff_t *tvb, packet_info *pinfo, - proto_tree *tree); + proto_tree *tree, cba_ldev_t *ldev, cba_frame_t *frame);*/ #endif /* packet-dcerpc-dcom-cba-acco.h */ diff --git a/epan/dissectors/packet-dcom-cba.c b/epan/dissectors/packet-dcom-cba.c index a0164f4d2e..d273d29d6e 100644 --- a/epan/dissectors/packet-dcom-cba.c +++ b/epan/dissectors/packet-dcom-cba.c @@ -33,9 +33,12 @@ #include <glib.h> #include <epan/packet.h> +#include <epan/emem.h> +#include <epan/expert.h> #include "packet-dcerpc.h" #include "packet-dcom.h" #include "packet-dcom-dispatch.h" +#include "packet-dcom-cba-acco.h" static int hf_cba_opnum = -1; @@ -569,6 +572,8 @@ dissect_ICBAPhysicalDevice_get_LogicalDevice_rqst(tvbuff_t *tvb, int offset, guint32 u32Pointer; gchar szStr[1000]; guint32 u32MaxStr = sizeof(szStr); + dcerpc_info *info = (dcerpc_info *) pinfo->private_data; + gchar *call; offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); @@ -579,7 +584,12 @@ dissect_ICBAPhysicalDevice_get_LogicalDevice_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_BSTR(tvb, offset, pinfo, tree, drep, hf_cba_name, szStr, u32MaxStr); } - + + if(szStr != NULL) { + call = se_strdup(szStr); + info->call_data->private_data = call; + } + if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\"", szStr); } @@ -593,11 +603,31 @@ dissect_ICBAPhysicalDevice_get_LogicalDevice_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { guint32 u32HResult; + dcerpc_info *info = (dcerpc_info *) pinfo->private_data; + gchar *ldev_name = info->call_data->private_data; + dcom_interface_t *pdev_interf; + dcom_interface_t *ldev_interf; + cba_pdev_t *pdev; + cba_ldev_t *ldev; offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); - offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0); + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0, &ldev_interf); + + /* try to read the ldev name from the request */ + if(ldev_name != NULL && ldev_interf != NULL) { + /* XXX - this is a hack to create a pdev interface */ + /* as I currently don't understand the objref process for a root interface! */ + pdev_interf = dcom_interface_new(pinfo, pinfo->net_dst.data, &uuid_ICBAPhysicalDevice, 0, 0, &info->call_data->object_uuid); + if(pdev_interf != NULL) { + pdev = cba_pdev_add(pinfo, pinfo->net_dst.data); + cba_pdev_link(pinfo, pdev, pdev_interf); + + ldev = cba_ldev_add(pinfo, pdev, ldev_name); + cba_ldev_link(pinfo, ldev, ldev_interf); + } + } offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); @@ -730,7 +760,38 @@ dissect_Revision_resp(tvbuff_t *tvb, int offset, static int -dissect_get_Name_resp(tvbuff_t *tvb, int offset, +dissect_ICBALogicalDevice_get_Name_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + 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, + hf_cba_name, 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_RTAuto_get_Name_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { @@ -743,11 +804,25 @@ dissect_ICBALogicalDevice_get_ACCO_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep) { guint32 u32HResult; + dcom_interface_t *acco_interf; + dcerpc_info *info = (dcerpc_info *) pinfo->private_data; + cba_ldev_t *ldev; offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); - offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0); + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0, &acco_interf); + if(acco_interf == NULL) { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, + "LDev_get_ACCO: can't resolve ACCO interface pointer"); + } + + ldev = cba_ldev_find(pinfo, pinfo->net_src.data, &info->call_data->object_uuid); + + /* "crosslink" interface and it's object */ + if(ldev != NULL && acco_interf != NULL) { + cba_ldev_link_acco(pinfo, ldev, acco_interf); + } offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); @@ -769,7 +844,7 @@ dissect_ICBALogicalDevice_get_RTAuto_resp(tvbuff_t *tvb, int offset, offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); - offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0); + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0, NULL); offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); @@ -857,7 +932,7 @@ dissect_Advise_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); - offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0); + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0, NULL); return offset; } @@ -1001,7 +1076,7 @@ dissect_ICBAPhysicalDevicePCEvent_OnLogicalDeviceAdded_rqst(tvbuff_t *tvb, int o 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_PMInterfacePointer(tvb, offset, pinfo, tree, drep, 0, NULL); offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); @@ -1158,7 +1233,7 @@ static dcerpc_sub_dissector ICBALogicalDevice_dissectors[] = { { 5, "GetIDsOfNames", dissect_IDispatch_GetIDsOfNames_rqst, dissect_IDispatch_GetIDsOfNames_resp }, { 6, "Invoke", dissect_IDispatch_Invoke_rqst, dissect_IDispatch_Invoke_resp }, - { 7, "get_Name", dissect_dcom_simple_rqst, dissect_get_Name_resp }, + { 7, "get_Name", dissect_dcom_simple_rqst, dissect_ICBALogicalDevice_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 }, @@ -1262,7 +1337,7 @@ static dcerpc_sub_dissector ICBARTAuto_dissectors[] = { { 5, "GetIDsOfNames", dissect_IDispatch_GetIDsOfNames_rqst, dissect_IDispatch_GetIDsOfNames_resp }, { 6, "Invoke", dissect_IDispatch_Invoke_rqst, dissect_IDispatch_Invoke_resp }, - { 7, "get_Name", dissect_dcom_simple_rqst, dissect_get_Name_resp }, + { 7, "get_Name", dissect_dcom_simple_rqst, dissect_RTAuto_get_Name_resp }, { 8, "Revision", dissect_dcom_simple_rqst, dissect_Revision_resp }, /* stage 2 */ @@ -1290,6 +1365,11 @@ static dcerpc_sub_dissector ICBASystemProperties_dissectors[] = { }; +static void cba_reinit( void) { + cba_pdevs = NULL; +} + + /* register protocol */ void proto_register_dcom_cba (void) @@ -1451,6 +1531,8 @@ proto_register_dcom_cba (void) ett[0] = &ett_ICBASystemProperties; proto_ICBASystemProperties = proto_register_protocol ("ICBASystemProperties", "ICBASysProp", "cba_sysprop"); proto_register_subtree_array (ett, array_length (ett)); + + register_init_routine(cba_reinit); } diff --git a/epan/dissectors/packet-dcom-dispatch.c b/epan/dissectors/packet-dcom-dispatch.c index bca151fe9d..3e489c7dc0 100644 --- a/epan/dissectors/packet-dcom-dispatch.c +++ b/epan/dissectors/packet-dcom-dispatch.c @@ -147,7 +147,7 @@ dissect_IDispatch_GetTypeInfo_resp(tvbuff_t *tvb, int offset, offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer); if (u32Pointer) { - offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, drep, hf_dispatch_itinfo); + offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, drep, hf_dispatch_itinfo, NULL /* XXX */); } /* HRESULT of call */ diff --git a/epan/dissectors/packet-dcom-oxid.c b/epan/dissectors/packet-dcom-oxid.c index 95fadcb31f..d4580673ce 100644 --- a/epan/dissectors/packet-dcom-oxid.c +++ b/epan/dissectors/packet-dcom-oxid.c @@ -239,7 +239,7 @@ dissect_oxid_resolve_oxid2_resp(tvbuff_t *tvb, int offset, &u32ArraySize); offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, tree, drep, - hf_oxid_bindings); + hf_oxid_bindings, NULL); offset = dissect_dcom_UUID(tvb, offset, pinfo, tree, drep, hf_oxid_ipid, &ipid); @@ -275,7 +275,7 @@ dissect_oxid_server_alive2_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, dissect_dcerpc_uint64(tvb , offset, pinfo, tree, drep, hf_oxid_Unknown1, NULL); offset += 8; - offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, tree, drep, hf_oxid_ds_array); + offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, tree, drep, hf_oxid_ds_array, NULL); /* unknown field 2 */ dissect_dcerpc_uint64(tvb, offset, pinfo, tree, drep, hf_oxid_Unknown2, NULL); diff --git a/epan/dissectors/packet-dcom-remact.c b/epan/dissectors/packet-dcom-remact.c index a90268e2e7..93e5671f21 100644 --- a/epan/dissectors/packet-dcom-remact.c +++ b/epan/dissectors/packet-dcom-remact.c @@ -39,8 +39,6 @@ static int hf_remact_opnum = -1; -static int hf_remact_clsid = -1; -static int hf_remact_iid = -1; static int hf_remact_requested_protseqs = -1; static int hf_remact_protseqs = -1; static int hf_remact_interfaces = -1; @@ -50,9 +48,7 @@ static int hf_remact_object_name = -1; static int hf_remact_object_storage = -1; static int hf_remact_interface_data = -1; -static int hf_remact_oxid = -1; static int hf_remact_oxid_bindings = -1; -static int hf_remact_ipid = -1; static int hf_remact_authn_hint = -1; static const value_string dcom_protseq_vals[] = { @@ -86,6 +82,8 @@ dissect_remact_remote_activation_rqst(tvbuff_t *tvb, int offset, guint32 u32ArraySize; guint32 u32ItemIdx; guint16 u16ProtSeqs; + e_uuid_t clsid; + e_uuid_t iid; gchar szObjName[1000] = { 0 }; guint32 u32ObjNameLen = sizeof(szObjName); @@ -93,7 +91,7 @@ dissect_remact_remote_activation_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); offset = dissect_dcom_append_UUID(tvb, offset, pinfo, tree, drep, - hf_remact_clsid, "CLSID", -1); + hf_dcom_clsid, "CLSID", -1, &clsid); offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer); @@ -103,7 +101,7 @@ dissect_remact_remote_activation_rqst(tvbuff_t *tvb, int offset, } offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, - hf_remact_object_storage); + hf_remact_object_storage, NULL /* XXX */); offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, hf_remact_client_impl_level, &u32ClientImpLevel); @@ -121,7 +119,7 @@ dissect_remact_remote_activation_rqst(tvbuff_t *tvb, int offset, u32ItemIdx = 1; while (u32Interfaces--) { offset = dissect_dcom_append_UUID(tvb, offset, pinfo, tree, drep, - hf_remact_iid, "IID", u32ArraySize); + hf_dcom_iid, "IID", u32ArraySize, &iid); u32ItemIdx++; } @@ -161,18 +159,18 @@ dissect_remact_remote_activation_resp(tvbuff_t *tvb, int offset, offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); offset = dissect_dcom_ID(tvb, offset, pinfo, tree, drep, - hf_remact_oxid, NULL); + hf_dcom_oxid, NULL); 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); offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, tree, drep, - hf_remact_oxid_bindings); + hf_remact_oxid_bindings, NULL); } offset = dissect_dcom_UUID(tvb, offset, pinfo, tree, drep, - hf_remact_ipid, &ipid); + hf_dcom_ipid, &ipid); offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep, hf_remact_authn_hint, &u32AuthnHint); offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, tree, drep, @@ -189,7 +187,7 @@ dissect_remact_remote_activation_resp(tvbuff_t *tvb, int offset, &u32Pointer); if (u32Pointer) { u32VariableOffset = dissect_dcom_MInterfacePointer(tvb, u32VariableOffset, pinfo, tree, drep, - hf_remact_interface_data); + hf_remact_interface_data, NULL /* XXX */); } } offset = u32VariableOffset; @@ -235,10 +233,6 @@ proto_register_remact (void) { &hf_remact_opnum, { "Operation", "remact_opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }}, - { &hf_remact_clsid, - { "CLSID", "remact_clsid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, - { &hf_remact_iid, - { "IID", "remact_iid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, { &hf_remact_requested_protseqs, { "RequestedProtSeqs", "remact_req_prot_seqs", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf_remact_protseqs, @@ -256,12 +250,8 @@ proto_register_remact (void) { &hf_remact_interface_data, { "InterfaceData", "remact_interface_data", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}, - { &hf_remact_oxid, - { "OXID", "remact_oxid", FT_UINT64, BASE_HEX, NULL, 0x0, "", HFILL }}, { &hf_remact_oxid_bindings, { "OxidBindings", "hf_remact_oxid_bindings", FT_NONE, BASE_DEC, NULL, 0x0, "", HFILL }}, - { &hf_remact_ipid, - { "IPID", "remact_ipid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, { &hf_remact_authn_hint, { "AuthnHint", "remact_authn_hint", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, }; diff --git a/epan/dissectors/packet-dcom-remunkn.c b/epan/dissectors/packet-dcom-remunkn.c index 4f608681d8..d7f29aaf08 100644 --- a/epan/dissectors/packet-dcom-remunkn.c +++ b/epan/dissectors/packet-dcom-remunkn.c @@ -33,6 +33,7 @@ #include <glib.h> #include <epan/packet.h> +#include <epan/emem.h> #include "packet-dcerpc.h" #include "packet-dcom.h" @@ -76,6 +77,11 @@ static guint16 ver_remunk2 = 0; static int proto_remunk2 = -1; +typedef struct remunk_remqueryinterface_call_s { + guint iid_count; + e_uuid_t *iids; +} remunk_remqueryinterface_call_t; + static int dissect_remunk_remqueryinterface_rqst(tvbuff_t *tvb, int offset, @@ -86,9 +92,12 @@ dissect_remunk_remqueryinterface_rqst(tvbuff_t *tvb, int offset, guint16 u16IIDs; guint32 u32ArraySize; guint32 u32ItemIdx; + e_uuid_t iid; + dcerpc_info *info = (dcerpc_info *) pinfo->private_data; + remunk_remqueryinterface_call_t *call; - offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); + offset = dissect_dcom_this(tvb, offset, pinfo, tree, drep); offset = dissect_dcom_UUID(tvb, offset, pinfo, tree, drep, hf_remunk_ipid, &ipid); @@ -102,10 +111,22 @@ dissect_remunk_remqueryinterface_rqst(tvbuff_t *tvb, int offset, offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep, &u32ArraySize); - u32ItemIdx = 1; - while (u32ArraySize--) { + /* limit the allocation to a reasonable size */ + if(u32ArraySize < 100) { + call = se_alloc(sizeof(remunk_remqueryinterface_call_t) + u32ArraySize * sizeof(e_uuid_t)); + call->iid_count = u32ArraySize; + call->iids = (e_uuid_t *) (call+1); + info->call_data->private_data = call; + } else { + call = NULL; + } + + for (u32ItemIdx = 0; u32ArraySize--; u32ItemIdx++) { offset = dissect_dcom_append_UUID(tvb, offset, pinfo, tree, drep, - hf_remunk_iid, "IID", u32ItemIdx++); + hf_remunk_iid, "IID", u32ItemIdx+1, &iid); + if(call != NULL) { + call->iids[u32ItemIdx] = iid; + } } return offset; @@ -123,9 +144,17 @@ dissect_remunk_remqueryinterface_resp(tvbuff_t *tvb, int offset, proto_tree *sub_tree; guint32 u32HResult; guint32 u32SubStart; + e_uuid_t iid; + e_uuid_t iid_null = DCERPC_UUID_NULL; + dcerpc_info *info = (dcerpc_info *) pinfo->private_data; + remunk_remqueryinterface_call_t *call = info->call_data->private_data; + guint64 oxid; + guint64 oid; + e_uuid_t ipid; + dcom_interface_t *dcom_if; - offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); + offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer); @@ -134,7 +163,7 @@ dissect_remunk_remqueryinterface_resp(tvbuff_t *tvb, int offset, u32ItemIdx = 1; while (u32ArraySize--) { - /* add subtree */ + /* add subtree */ sub_item = proto_tree_add_item(tree, hf_remunk_qiresult, tvb, offset, 0, FALSE); sub_tree = proto_item_add_subtree(sub_item, ett_remunk_rqi_result); @@ -144,10 +173,27 @@ dissect_remunk_remqueryinterface_resp(tvbuff_t *tvb, int offset, u32SubStart = offset - 4; offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer); - if (u32Pointer) { - offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, drep, 0 /* hfindex */); + + /* try to read the iid from the request */ + if(call != NULL && u32ItemIdx <= call->iid_count) { + iid = call->iids[u32ItemIdx-1]; + } else { + iid = iid_null; } + /* XXX - this doesn't seem to be dependent on the pointer above?!? */ + /*if (u32Pointer) {*/ + offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, drep, 0 /* hfindex */, + &oxid, &oid, &ipid); + /*}*/ + + /* add interface instance to database (we currently only handle IPv4) */ + if(pinfo->net_src.type == AT_IPv4) { + dcom_if = dcom_interface_new(pinfo, + pinfo->net_src.data, + &iid, oxid, oid, &ipid); + } + /* update subtree */ proto_item_append_text(sub_item, "[%u]: %s", u32ItemIdx, @@ -163,7 +209,7 @@ dissect_remunk_remqueryinterface_resp(tvbuff_t *tvb, int offset, u32ItemIdx++; } - + /* HRESULT of call */ offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, &u32HResult); diff --git a/epan/dissectors/packet-dcom-sysact.c b/epan/dissectors/packet-dcom-sysact.c index 6b278d06ea..43c0f119eb 100644 --- a/epan/dissectors/packet-dcom-sysact.c +++ b/epan/dissectors/packet-dcom-sysact.c @@ -58,7 +58,7 @@ dissect_remsysact_remotecreateinstance_rqst(tvbuff_t *tvb, int offset, 4); offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, - hf_sysact_unknown); + hf_sysact_unknown, NULL /* XXX */); return offset; } @@ -72,7 +72,7 @@ dissect_remsysact_remotecreateinstance_resp(tvbuff_t *tvb, int offset, offset = dissect_dcom_that(tvb, offset, pinfo, tree, drep); offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, drep, - hf_sysact_unknown); + hf_sysact_unknown, NULL /* XXX */); offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep, NULL /* pu32HResult */); diff --git a/epan/dissectors/packet-dcom.c b/epan/dissectors/packet-dcom.c index 8cabf32b95..116f147514 100644 --- a/epan/dissectors/packet-dcom.c +++ b/epan/dissectors/packet-dcom.c @@ -85,6 +85,8 @@ #include <glib.h> #include <epan/packet.h> #include <epan/emem.h> +#include <epan/addr_resolv.h> +#include <epan/inet_aton.h> #include "packet-dcerpc.h" #include "packet-dcom.h" #include "prefs.h" @@ -134,8 +136,8 @@ 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; +int hf_dcom_iid = -1; +int hf_dcom_clsid = -1; static int hf_dcom_objref_resolver_address = -1; static int hf_dcom_objref_cbextension = -1; static int hf_dcom_objref_size = -1; @@ -144,9 +146,9 @@ 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; +int hf_dcom_oxid = -1; +int hf_dcom_oid = -1; +int hf_dcom_ipid = -1; gint ett_dcom_dualstringarray = -1; gint ett_dcom_dualstringarray_binding = -1; @@ -214,6 +216,160 @@ static int hf_dcom_vt_byref = -1; static int hf_dcom_vt_dispatch = -1; +GList *dcom_machines; +GList *dcom_interfaces; + +void dcom_interface_dump(void) { + dcom_machine_t *machine; + dcom_object_t *object; + dcom_interface_t *interf; + GList *machines; + GList *objects; + GList *interfaces; + + + for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) { + machine = machines->data; + g_warning("Machine(#%4u): IP:%s", machine->first_packet, ip_to_str(machine->ip)); + + for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) { + object = objects->data; + g_warning(" Object(#%4u): OID:0x%x%x private:0x%x", object->first_packet, object->oid, object->private_data); + + for(interfaces = object->interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) { + interf = interfaces->data; + g_warning(" Interface(#%4u): iid:%s", + interf->first_packet, dcom_uuid_to_str(&interf->iid)); + g_warning(" ipid:%s", dcom_uuid_to_str(&interf->ipid)); + } + } + } +} + + +dcom_interface_t *dcom_interface_find(packet_info *pinfo, const guint8 *ip, e_uuid_t *ipid) +{ + dcom_interface_t *interf; + GList *interfaces; + static const e_uuid_t uuid_null = DCERPC_UUID_NULL; + + + if(memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0) + { + return NULL; + } + + for(interfaces = dcom_interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) { + interf = interfaces->data; + + if(memcmp(&interf->ipid, ipid, sizeof(e_uuid_t)) == 0) { + return interf; + } + } + + return NULL; +} + + +dcom_interface_t *dcom_interface_new(packet_info *pinfo, const guint8 *ip, e_uuid_t *iid, guint64 oxid, guint64 oid, e_uuid_t *ipid) +{ + static const e_uuid_t uuid_null = DCERPC_UUID_NULL; + GList *dcom_iter; + dcom_machine_t *machine; + dcom_object_t *object; + dcom_interface_t *interf; + + + if( memcmp(iid, &uuid_null, sizeof(uuid_null)) == 0 || + memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0) + { + return NULL; + } + + if(oxid == 0 || oid == 0) { + /*g_warning("interface_new#%u", pinfo->fd->num);*/ + + interf = se_alloc(sizeof(dcom_interface_t)); + interf->parent = NULL; //object; + interf->private_data = NULL; + interf->first_packet = pinfo->fd->num; + interf->iid = *iid; + interf->ipid = *ipid; + + dcom_interfaces = g_list_append(dcom_interfaces, interf); + //object->interfaces = g_list_append(object->interfaces, interf); + return interf; + } + + /* find machine */ + dcom_iter = dcom_machines; + while(dcom_iter != NULL) { + machine = dcom_iter->data; + if(memcmp(machine->ip, ip, 4) == 0) { + break; + } + dcom_iter = g_list_next(dcom_iter); + } + + /* create new machine if not found */ + if(dcom_iter == NULL) { + machine = se_alloc(sizeof(dcom_machine_t)); + memcpy( (void *) (machine->ip), ip, 4); + machine->objects = NULL; + machine->first_packet = pinfo->fd->num; + dcom_machines = g_list_append(dcom_machines, machine); + } + + /* find object */ + dcom_iter = machine->objects; + while(dcom_iter != NULL) { + object = dcom_iter->data; + if(object->oid == oid) { + break; + } + dcom_iter = g_list_next(dcom_iter); + } + + /* create new object if not found */ + if(dcom_iter == NULL) { + object = se_alloc(sizeof(dcom_object_t)); + object->parent = machine; + object->interfaces = NULL; + object->private_data = NULL; + object->first_packet = pinfo->fd->num; + object->oid = oid; + object->oxid = oxid; + + machine->objects = g_list_append(machine->objects, object); + } + + /* find interface */ + dcom_iter = object->interfaces; + while(dcom_iter != NULL) { + interf = dcom_iter->data; + if(memcmp(&interf->ipid, ipid, sizeof(e_uuid_t)) == 0) { + break; + } + dcom_iter = g_list_next(dcom_iter); + } + + /* create new interface if not found */ + if(dcom_iter == NULL) { + interf = se_alloc(sizeof(dcom_interface_t)); + interf->parent = object; + interf->private_data = NULL; + interf->first_packet = pinfo->fd->num; + interf->iid = *iid; + interf->ipid = *ipid; + + object->interfaces = g_list_append(object->interfaces, interf); + dcom_interfaces = g_list_append(dcom_interfaces, interf); + } + + return interf; +} + + /* * Flag bits in connection-oriented PDU header. */ @@ -586,6 +742,9 @@ dissect_dcom_this(tvbuff_t *tvb, int offset, proto_item *sub_item; proto_tree *sub_tree; guint32 u32SubStart; + proto_item *pi; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + e_uuid_t uuid_null = DCERPC_UUID_NULL; sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0, @@ -611,6 +770,11 @@ dissect_dcom_this(tvbuff_t *tvb, int offset, u16VersionMajor, u16VersionMinor, dcom_uuid_to_str(&uuidCausality)); proto_item_set_len(sub_item, offset - u32SubStart); + if(memcmp(&info->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) { + pi = proto_tree_add_guid(tree, hf_dcom_ipid, tvb, offset, GUID_LEN, (e_guid_t *) &info->call_data->object_uuid); + PROTO_ITEM_SET_GENERATED(pi); + } + return offset; } @@ -623,6 +787,9 @@ dissect_dcom_that(tvbuff_t *tvb, int offset, proto_item *sub_item; proto_tree *sub_tree; guint32 u32SubStart; + proto_item *pi; + dcerpc_info *info = (dcerpc_info *)pinfo->private_data; + e_uuid_t uuid_null = DCERPC_UUID_NULL; sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0, @@ -638,6 +805,11 @@ dissect_dcom_that(tvbuff_t *tvb, int offset, /* update subtree header */ proto_item_set_len(sub_item, offset - u32SubStart); + if(memcmp(&info->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) { + pi = proto_tree_add_guid(tree, hf_dcom_ipid, tvb, offset, GUID_LEN, (e_guid_t *) &info->call_data->object_uuid); + PROTO_ITEM_SET_GENERATED(pi); + } + return offset; } @@ -1177,7 +1349,7 @@ dissect_dcom_VARIANT(tvbuff_t *tvb, int offset, packet_info *pinfo, offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, drep, &u32Pointer); if (u32Pointer) { offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, sub_tree, drep, - hf_dcom_vt_dispatch); + hf_dcom_vt_dispatch, NULL); /* XXX - how to handle this? */ } break; case(WIRESHARK_VT_ARRAY): @@ -1217,21 +1389,20 @@ dissect_dcom_VARIANT(tvbuff_t *tvb, int offset, packet_info *pinfo, int dissect_dcom_append_UUID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, - int hfindex, const gchar *field_name, int field_index) + int hfindex, const gchar *field_name, int field_index, e_uuid_t *uuid) { - e_uuid_t uuid; const gchar *uuid_name; offset = dissect_dcom_UUID(tvb, offset, pinfo, tree, drep, - hfindex, &uuid); + 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); + uuid_name = dcerpc_get_uuid_name(uuid, 0); if (field_index != -1) { col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]=%s", @@ -1437,7 +1608,7 @@ dissect_dcom_BSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo, /* dissect an DUALSTRINGARRAY */ int dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, gint offset, packet_info *pinfo, - proto_tree *tree, guint8 *drep, int hfindex) + proto_tree *tree, guint8 *drep, int hfindex, gchar *ip) { guint16 u16NumEntries; guint16 u16SecurityOffset; @@ -1456,6 +1627,9 @@ dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *subsub_tree; guint32 u32SubSubStart; gboolean isPrintable; + guint32 first_ip = 0; + guint32 curr_ip = 0; + struct in_addr ipaddr; /* add subtree header */ @@ -1485,6 +1659,30 @@ dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_string_network_addr, tvb, u32Start, offset - u32Start, szStr); + /* convert ip address (if it is dotted decimal) */ + /* XXX - this conversion is ugly */ + if (inet_aton(szStr, &ipaddr)) { + if(get_host_ipaddr(szStr, &curr_ip)) { + curr_ip = ntohl(curr_ip); + + /*expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "DUALSTRINGARRAY: IP:%s", + ip_to_str( (gchar *) &curr_ip));*/ + + if(first_ip == 0) { + if(ip != NULL) { + memcpy(ip, &curr_ip, sizeof(curr_ip)); + } + first_ip = curr_ip; + } else { + if(first_ip != curr_ip) { + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_NOTE, + "DUALSTRINGARRAY: multiple IP's %s %s", + ip_to_str( (char *) &first_ip), ip_to_str( (char *) &curr_ip)); + } + } + } + } + proto_item_append_text(subsub_item, "[%u]: TowerId=%s, NetworkAddr=\"%s\"", u32StringBindings, val_to_str(u16TowerId, dcom_dualstringarray_tower_id_vals, "Unknown (0x%04x"), @@ -1532,11 +1730,11 @@ dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, gint offset, packet_info *pinfo, /* dissect an STDOBJREF */ int dissect_dcom_STDOBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, - proto_tree *tree, guint8 *drep, int hfindex _U_) + proto_tree *tree, guint8 *drep, int hfindex _U_, + guint64 *oxid, guint64 *oid, e_uuid_t *ipid) { guint32 u32Flags; guint32 u32PublicRefs; - e_uuid_t ipid; proto_item *sub_item; proto_tree *sub_tree; guint32 u32SubStart; @@ -1553,15 +1751,15 @@ dissect_dcom_STDOBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, 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, NULL); + hf_dcom_oxid, oxid); offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, drep, - hf_dcom_stdobjref_oid, NULL); + hf_dcom_oid, oid); offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep, - hf_dcom_stdobjref_ipid, &ipid); + hf_dcom_ipid, ipid); /* append info to subtree header */ proto_item_append_text(sub_item, ": PublicRefs=%u IPID=%s", - u32PublicRefs, dcom_uuid_to_str(&ipid)); + u32PublicRefs, dcom_uuid_to_str(ipid)); proto_item_set_len(sub_item, offset - u32SubStart); return offset; @@ -1571,7 +1769,7 @@ dissect_dcom_STDOBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, /* dissect an OBJREF */ int dissect_dcom_OBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, - proto_tree *tree, guint8 *drep, int hfindex) + proto_tree *tree, guint8 *drep, int hfindex, dcom_interface_t **interf) { guint32 u32Signature; guint32 u32Flags; @@ -1582,6 +1780,11 @@ dissect_dcom_OBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, guint32 u32SubStart; guint32 u32CBExtension; guint32 u32Size; + guint64 oxid; + guint64 oid; + e_uuid_t ipid; + dcom_interface_t *dcom_if = NULL; + gchar ip[4]; /* add subtree header */ @@ -1595,25 +1798,26 @@ dissect_dcom_OBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, 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); - + hf_dcom_iid, &iid); switch(u32Flags) { case(0x1): /* standard */ - offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex); + offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex, + &oxid, &oid, &ipid); offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, drep, - hf_dcom_objref_resolver_address); + hf_dcom_objref_resolver_address, ip); break; case(0x2): /* handler (untested) */ - offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex); + offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex, + &oxid, &oid, &iid); offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep, - hf_dcom_objref_clsid, &clsid); + hf_dcom_clsid, &clsid); offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, drep, - hf_dcom_objref_resolver_address); + hf_dcom_objref_resolver_address, ip); break; case(0x4): /* custom */ offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, drep, - hf_dcom_objref_clsid, &clsid); + hf_dcom_clsid, &clsid); offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, hf_dcom_objref_cbextension, &u32CBExtension); offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, drep, @@ -1623,6 +1827,19 @@ dissect_dcom_OBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, break; } + if(u32Flags == 0x1 || u32Flags == 0x2) { + /* add interface instance to database (we currently only handle IPv4) */ + if(pinfo->net_src.type == AT_IPv4) { + dcom_if = dcom_interface_new(pinfo, + ip, + &iid, oxid, oid, &ipid); + } + } + + if(interf != NULL) { + *interf = dcom_if; + } + /* append info to subtree header */ proto_item_set_len(sub_item, offset - u32SubStart); @@ -1634,7 +1851,7 @@ dissect_dcom_OBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, /* dissect an MInterfacePointer */ int dissect_dcom_MInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo, - proto_tree *tree, guint8 *drep, int hfindex) + proto_tree *tree, guint8 *drep, int hfindex, dcom_interface_t **interf) { guint32 u32CntData; guint32 u32ArraySize; @@ -1657,7 +1874,7 @@ dissect_dcom_MInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo, offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, drep, &u32ArraySize); - offset = dissect_dcom_OBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex); + offset = dissect_dcom_OBJREF(tvb, offset, pinfo, sub_tree, drep, hfindex, interf); /* append info to subtree header */ proto_item_set_len(sub_item, offset - u32SubStart); @@ -1669,7 +1886,7 @@ dissect_dcom_MInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo, /* 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) + proto_tree *tree, guint8 *drep, int hfindex, dcom_interface_t **interf) { guint32 u32Pointer; @@ -1677,8 +1894,12 @@ dissect_dcom_PMInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo, offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep, &u32Pointer); if (u32Pointer) { - offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, drep, hfindex); - } + offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, drep, hfindex, interf); + } else { + if(interf != NULL) { + *interf = NULL; + } + } return offset; } @@ -1695,6 +1916,12 @@ void dcom_register_server_coclass(int proto _U_, int ett _U_, e_uuid_t *uuid _U_ } +static void dcom_reinit( void) { + dcom_machines = NULL; + dcom_interfaces = NULL; +} + + void proto_register_dcom (void) { @@ -1709,7 +1936,7 @@ proto_register_dcom (void) { &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 }} + { "Causality ID", "dcom.this.uuid", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }} }; static hf_register_info hf_dcom_that_array[] = { @@ -1781,10 +2008,10 @@ proto_register_dcom (void) { "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_iid, + { "IID", "dcom.iid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_dcom_clsid, + { "CLSID", "dcom.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 }}, { &hf_dcom_objref_cbextension, @@ -1800,12 +2027,12 @@ proto_register_dcom (void) { "Flags", "dcom.stdobjref.flags", FT_UINT32, BASE_HEX, VALS(dcom_stdobjref_flag_vals), 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 }} + { &hf_dcom_oxid, + { "OXID", "dcom.oxid", FT_UINT64, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_oid, + { "OID", "dcom.oid", FT_UINT64, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcom_ipid, + { "IPID", "dcom.ipid", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }} }; static hf_register_info hf_dcom_dualstringarray_array[] = { @@ -1950,6 +2177,8 @@ proto_register_dcom (void) "Display some DCOM unmarshalled fields " "usually hidden", &dcom_prefs_display_unmarshalling_details); + + register_init_routine(dcom_reinit); } diff --git a/epan/dissectors/packet-dcom.h b/epan/dissectors/packet-dcom.h index c95d0228c2..4d9cabcf89 100644 --- a/epan/dissectors/packet-dcom.h +++ b/epan/dissectors/packet-dcom.h @@ -29,10 +29,48 @@ extern const value_string dcom_hresult_vals[]; extern const value_string dcom_variant_type_vals[]; +extern int hf_dcom_iid; +extern int hf_dcom_clsid; +extern int hf_dcom_oxid; +extern int hf_dcom_oid; +extern int hf_dcom_ipid; + /* preferences */ extern int dcom_prefs_display_unmarshalling_details; +typedef struct dcom_machine_s { + GList *objects; + gint first_packet; + + const guint8 ip[4]; +} dcom_machine_t; + +typedef struct dcom_object_s { + dcom_machine_t *parent; + GList *interfaces; + void *private_data; + gint first_packet; + + guint64 oid; + guint64 oxid; +} dcom_object_t; + +typedef struct dcom_interface_s { + dcom_object_t *parent; + void *private_data; + gint first_packet; + + e_uuid_t iid; + e_uuid_t ipid; /* the DCE/RPC Object UUID */ +} dcom_interface_t; + + +extern dcom_interface_t *dcom_interface_new(packet_info *pinfo, const guint8 *ip, e_uuid_t *iid, guint64 oxid, guint64 oid, e_uuid_t *ipid); +extern dcom_interface_t *dcom_interface_find(packet_info *pinfo, const guint8 *ip, e_uuid_t *ipid); +extern void dcom_interface_dump(void); + + /* the essential DCOM this and that, starting every call */ extern int dissect_dcom_this(tvbuff_t *tvb, int offset, @@ -59,7 +97,7 @@ dissect_dcom_that(tvbuff_t *tvb, int offset, extern int dissect_dcom_append_UUID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, - int hfindex, const gchar *field_name, int field_index); + int hfindex, const gchar *field_name, int field_index, e_uuid_t *uuid); extern const gchar* dcom_uuid_to_str(e_uuid_t *uuid); extern int @@ -103,22 +141,22 @@ dissect_dcom_BSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo, extern int dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, gint offset, packet_info *pinfo, - proto_tree *tree, guint8 *drep, int hfindex); + proto_tree *tree, guint8 *drep, int hfindex, gchar *ip); extern int dissect_dcom_STDOBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, - proto_tree *tree, guint8 *drep, int hfindex); - + proto_tree *tree, guint8 *drep, int hfindex, + guint64 *oxid, guint64 *oid, e_uuid_t *ipid); extern int dissect_dcom_OBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo, - proto_tree *tree, guint8 *drep, int hfindex); + proto_tree *tree, guint8 *drep, int hfindex, dcom_interface_t **interf); extern int dissect_dcom_MInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo, - proto_tree *tree, guint8 *drep, int hfindex); + proto_tree *tree, guint8 *drep, int hfindex, dcom_interface_t **interf); extern int dissect_dcom_PMInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo, - proto_tree *tree, guint8 *drep, int hfindex); + proto_tree *tree, guint8 *drep, int hfindex, dcom_interface_t **interf); extern int dissect_dcom_VARTYPE(tvbuff_t *tvb, int offset, |