Ethereal-dev: [Ethereal-dev] please checkin: packet-dcm.c
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: richard.coe@xxxxxxxxxx
Date: Tue, 09 Nov 2004 13:03:01 -0600
Please check-in.
* 9 Nov 2004
* - Fixed calculating the size of the complete dicom pdu in dcm_get_pdu_len
* - Fixed the heuristic code -- sometimes a conversation already exists
* - Fixed the dissect code to display all the tags in the pdu
--
Rich Coe richard.coe@xxxxxxxxxx
General Electric Medical Systems
*** ethereal-0.10.3-a/packet-dcm.c Sat May 8 13:52:38 2004
--- ethereal-0.10.4/packet-dcm.c Tue Nov 9 12:59:58 2004
***************
*** 9,17 ****
* (NOTE: you need to turn on 'Allow subdissector to desegment TCP streams'
* in Preferences/Protocols/TCP Option menu, in order to view
* DICOM packets correctly.
* This should probably be documented somewhere besides here.)
*
* $Id: packet-dcm.c,v 1.3 2004/05/08 21:31:52 obiot Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@xxxxxxxxxxxx>
--- 9,19 ----
* (NOTE: you need to turn on 'Allow subdissector to desegment TCP streams'
* in Preferences/Protocols/TCP Option menu, in order to view
* DICOM packets correctly.
+ * Also, you might have to turn off tcp.check_checksum if tcp
+ * detects that the checksum is bad.
* This should probably be documented somewhere besides here.)
*
* $Id: packet-dcm.c,v 1.3 2004/05/08 21:31:52 obiot Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@xxxxxxxxxxxx>
***************
*** 57,62 ****
--- 59,68 ----
*
* - The 'value to string' routines should probably be hash lookups.
*
+ * 9 Nov 2004
+ * - Fixed calculating the size of the complete dicom pdu in dcm_get_pdu_len
+ * - Fixed the heuristic code -- sometimes a conversation already exists
+ * - Fixed the dissect code to display all the tags in the pdu
*/
#include <stdio.h>
***************
*** 125,130 ****
--- 131,137 ----
};
struct dcmItem {
struct dcmItem *next, *prev;
+ int valid;
guint8 id; /* 0x20 Presentation Context */
guint8 *abs; /* 0x30 Abstract syntax */
guint8 *xfer; /* 0x40 Transfer syntax */
***************
*** 142,147 ****
--- 149,155 ----
guint32 tlen, clen, rlen; /* length: total, current, remaining */
int partial; /* is a partial packet */
int coff; /* current offset */
+ int valid; /* this conversation is a dicom conversation */
/* enum { DCM_NONE, DCM_ASSOC, DCM_ }; */
#define AEEND 16
guint8 orig[1+AEEND], targ[1+AEEND], resp[1+AEEND], source, result, reason;
***************
*** 268,273 ****
--- 276,282 ----
ds->pdu = 0;
ds->tlen = ds->rlen = 0;
ds->partial = 0;
+ ds->valid = TRUE;
memset(ds->orig, 0, sizeof(ds->orig));
memset(ds->targ, 0, sizeof(ds->targ));
memset(ds->resp, 0, sizeof(ds->resp));
***************
*** 440,446 ****
case 0xff00: s = "Pending: operations are continuing"; break;
default: break;
}
! if (0xC000 == (0xC000 & us)) s = "Failed: Unable to Process";
return s;
}
--- 449,455 ----
case 0xff00: s = "Pending: operations are continuing"; break;
default: break;
}
! if (0xC000 == (0xF000 & us)) s = "Failed: Unable to Process";
return s;
}
***************
*** 449,454 ****
--- 458,464 ----
{
if (NULL == di) return;
di->syntax = 0;
+ di->xfer = name;
if (0 == *name) return;
/* this would be faster to skip the common parts, and have a FSA to
* find the syntax.
***************
*** 478,483 ****
--- 488,494 ----
guint32 tag, val32;
guint16 val16;
dcmTag_t *dtag;
+ guint32 pl;
static dcmTag_t utag = { 0, 0, "(unknown)" };
*buf = 0;
***************
*** 493,505 ****
dtag = &utag;
strcpy(buf, dtag->desc);
p = buf + strlen(buf);
switch (dtag->dtype) {
case DCM_TSTR:
*p++ = ' ';
vval = tvb_get_ptr(tvb, offset, len);
! strncpy(p, vval, len);
p += len;
*p = 0;
break;
--- 504,517 ----
dtag = &utag;
strcpy(buf, dtag->desc);
+ pl = sizeof(buf) - strlen(buf);
p = buf + strlen(buf);
switch (dtag->dtype) {
case DCM_TSTR:
*p++ = ' ';
vval = tvb_get_ptr(tvb, offset, len);
! strncpy(p, vval, len > pl ? pl : len);
p += len;
*p = 0;
break;
***************
*** 549,555 ****
vval = tvb_get_ptr(tvb, offset, len);
i = 0;
*p++ = ' ';
! while (i < len && isprint(*(vval+i)))
*p++ = *(vval + i++);
*p = 0;
} break;
--- 561,567 ----
vval = tvb_get_ptr(tvb, offset, len);
i = 0;
*p++ = ' ';
! while (i < len && i < pl && isprint(*(vval+i)))
*p++ = *(vval + i++);
*p = 0;
} break;
***************
*** 560,584 ****
static guint
dcm_get_pdu_len(tvbuff_t *tvb, int offset)
{
! long len;
guint8 pdu_type;
len = tvb_get_ntohl(tvb, 2 + offset);
- #if 0
pdu_type = tvb_get_guint8(tvb, offset);
if (4 == pdu_type) {
guint8 frag;
! /* this is a total swamp. We only know how big this
! fragment is and that more are coming. We have to
! parse the entire packet to find a clue how much more is
! coming. this tries to guess .... */
frag = tvb_get_guint8(tvb, 11 + offset);
! if (0 == (0x2 & frag))
! /* len += tvb_ensure_length_remaining(tvb, offset) - 6; */
! /* there are more fragments */
! len++;
}
- #endif
return len + 6; /* add in fixed header part */
}
--- 572,600 ----
static guint
dcm_get_pdu_len(tvbuff_t *tvb, int offset)
{
! guint len;
guint8 pdu_type;
+ guint len_rem;
+ len_rem = tvb_ensure_length_remaining(tvb, offset);
len = tvb_get_ntohl(tvb, 2 + offset);
pdu_type = tvb_get_guint8(tvb, offset);
if (4 == pdu_type) {
guint8 frag;
! /* old swamp */
frag = tvb_get_guint8(tvb, 11 + offset);
! while (0 == (0x2 & frag)) { /* there are more fragments */
! int nlen;
! if (len_rem < len + 6 + 12) {
! len += 12; /* fixed part of next pdu */
! break;
! }
! len += 6;
! nlen = tvb_get_ntohl(tvb, 2 + offset + len);
! frag = tvb_get_guint8(tvb, 11 + offset + len);
! len += nlen;
! }
}
return len + 6; /* add in fixed header part */
}
***************
*** 587,596 ****
{
proto_tree *dcm_tree;
dcmItem_t *di = NULL;
dcm_tree = proto_item_add_subtree(ti, ett_assoc);
while (-1 < offset && offset < (int) dcm_data->clen) {
- guint8 id, *name, result;
short len;
long mlen;
id = tvb_get_guint8(tvb, offset);
--- 603,613 ----
{
proto_tree *dcm_tree;
dcmItem_t *di = NULL;
+ guint8 id, *name, result;
+ int reply = 0;
dcm_tree = proto_item_add_subtree(ti, ett_assoc);
while (-1 < offset && offset < (int) dcm_data->clen) {
short len;
long mlen;
id = tvb_get_guint8(tvb, offset);
***************
*** 615,633 ****
offset += len;
break;
case 0x40: /* Transfer syntax */
! dcm_data->last->xfer = name = g_malloc(1 + len);
tvb_memcpy(tvb, name, offset, len);
*(name + len) = 0;
proto_tree_add_string(dcm_tree, hf_dcm_pdi_syntax, tvb, offset, len, name);
! dcm_setSyntax(di, name);
offset += len;
break;
case 0x20: /* Presentation context */
id = tvb_get_guint8(tvb, offset);
di = lookupCtx(dcm_data, id);
! if (DCM_UNK == di->syntax) {
di = g_chunk_new(dcmItem_t, dcm_pdus);
di->id = id;
di->next = di->prev = NULL;
if (dcm_data->last) {
dcm_data->last->next = di;
--- 632,652 ----
offset += len;
break;
case 0x40: /* Transfer syntax */
! name = g_malloc(1 + len);
tvb_memcpy(tvb, name, offset, len);
*(name + len) = 0;
proto_tree_add_string(dcm_tree, hf_dcm_pdi_syntax, tvb, offset, len, name);
! if (reply && di && di->valid) dcm_setSyntax(di, name);
! reply = 0;
offset += len;
break;
case 0x20: /* Presentation context */
id = tvb_get_guint8(tvb, offset);
di = lookupCtx(dcm_data, id);
! if (!di->valid) {
di = g_chunk_new(dcmItem_t, dcm_pdus);
di->id = id;
+ di->valid = 1;
di->next = di->prev = NULL;
if (dcm_data->last) {
dcm_data->last->next = di;
***************
*** 644,652 ****
result = tvb_get_guint8(tvb, 2 + offset);
proto_tree_add_item(dcm_tree, hf_dcm_pctxt, tvb, offset, 1, FALSE);
proto_tree_add_uint_format(dcm_tree, hf_dcm_pcres, tvb,
! 2 + offset, 1,
! result, "Result 0x%x (%s)", result, dcm_PCresult2str(result));
! offset += len;
break;
case 0x50: /* User Info */
break;
--- 663,676 ----
result = tvb_get_guint8(tvb, 2 + offset);
proto_tree_add_item(dcm_tree, hf_dcm_pctxt, tvb, offset, 1, FALSE);
proto_tree_add_uint_format(dcm_tree, hf_dcm_pcres, tvb,
! 2 + offset, 1, result,
! "Result 0x%x (%s)", result, dcm_PCresult2str(result));
! if (0 == result) {
! reply = 1;
! di = lookupCtx(dcm_data, id);
! offset += 4;
! } else
! offset += len;
break;
case 0x50: /* User Info */
break;
***************
*** 682,688 ****
lookupCtx(dcmState_t *dd, guint8 ctx)
{
dcmItem_t *di = dd->first;
! static dcmItem_t dunk = { NULL, NULL, -1,
"not found - click on ASSOC Request",
"not found - click on ASSOC Request", DCM_UNK };
while (di) {
--- 706,712 ----
lookupCtx(dcmState_t *dd, guint8 ctx)
{
dcmItem_t *di = dd->first;
! static dcmItem_t dunk = { NULL, NULL, 0, -1,
"not found - click on ASSOC Request",
"not found - click on ASSOC Request", DCM_UNK };
while (di) {
***************
*** 732,738 ****
len = offset = toffset = 11;
state = D_HEADER;
nlen = 1;
! while (len + nlen < dcm_data->clen) {
switch (state) {
case D_HEADER: {
guint8 flags;
--- 756,762 ----
len = offset = toffset = 11;
state = D_HEADER;
nlen = 1;
! while (len + nlen <= dcm_data->clen) {
switch (state) {
case D_HEADER: {
guint8 flags;
***************
*** 860,904 ****
guint8 pdu;
guint16 vers;
guint32 len, tlen;
! dcmState_t *dcm_data;
conv = find_conversation(&pinfo->src, &pinfo->dst,
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
! if (NULL == conv) {
/* No conversation found.
* only look for the first packet of a DICOM conversation.
* if we don't get the first packet, we cannot decode the rest
* of the session.
*/
- if (10 > (tlen = tvb_reported_length(tvb)))
- return FALSE; /* not long enough */
- if (1 != (pdu = tvb_get_guint8(tvb, 0)))
- return FALSE; /* look for the start */
- if (1 != (vers = tvb_get_ntohs(tvb, 6)))
- return FALSE; /* not version 1 */
- len = 6 + tvb_get_ntohl(tvb, 2);
- if (len < tlen)
- return FALSE; /* packet is > decl len */
-
- conv = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
- pinfo->srcport, pinfo->destport, 0);
if (NULL == (dcm_data = mkds()))
return FALSE; /* internal error */
conversation_add_proto_data(conv, proto_dcm, dcm_data);
- } else {
- /*
- * conversation exists
- */
- dcm_data = conversation_get_proto_data(conv, proto_dcm);
- if (NULL == dcm_data) {
- /*
- * This is not a DICOM conversation
- */
- return FALSE;
- }
}
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_clear(pinfo->cinfo, COL_PROTOCOL);
--- 884,925 ----
guint8 pdu;
guint16 vers;
guint32 len, tlen;
! dcmState_t *dcm_data = NULL;
conv = find_conversation(&pinfo->src, &pinfo->dst,
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
! if (NULL != conv) /* conversation exists */
! /* do we have any data for this conversation ? */
! dcm_data = conversation_get_proto_data(conv, proto_dcm);
! else
! conv = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
! pinfo->srcport, pinfo->destport, 0);
!
! if (NULL == dcm_data) {
/* No conversation found.
* only look for the first packet of a DICOM conversation.
* if we don't get the first packet, we cannot decode the rest
* of the session.
*/
if (NULL == (dcm_data = mkds()))
return FALSE; /* internal error */
+ if (10 > (tlen = tvb_reported_length(tvb)) /* not long enough */
+ || 1 != (pdu = tvb_get_guint8(tvb, 0)) /* look for the start */
+ || 1 != (vers = tvb_get_ntohs(tvb, 6))) /* not version 1 */
+ dcm_data->valid = FALSE;
+ else {
+ len = 6 + tvb_get_ntohl(tvb, 2);
+ if (len < tlen)
+ dcm_data->valid = FALSE; /* packet is > decl len */
+ }
+
conversation_add_proto_data(conv, proto_dcm, dcm_data);
}
+ if (FALSE == dcm_data->valid)
+ return FALSE;
+
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_clear(pinfo->cinfo, COL_PROTOCOL);
***************
*** 1110,1116 ****
--- 1131,1141 ----
void
proto_reg_handoff_dcm(void)
{
+ dissector_handle_t dcm_handle;
+
heur_dissector_add("tcp", dissect_dcm, proto_dcm);
+ dcm_handle = new_create_dissector_handle(dissect_dcm, proto_dcm);
+ dissector_add("tcp.port", 104, dcm_handle);
}
/*
- Follow-Ups:
- Re: [Ethereal-dev] please checkin: packet-dcm.c
- From: Guy Harris
- Re: [Ethereal-dev] please checkin: packet-dcm.c
- Prev by Date: Re: [Ethereal-dev] Diff not working for anonsvn
- Next by Date: [Ethereal-dev] Update to NMAS dissector
- Previous by thread: [Ethereal-dev] patch for h225 decoded as h245 bug
- Next by thread: Re: [Ethereal-dev] please checkin: packet-dcm.c
- Index(es):





