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):