I'm adding the "Expert Info" prototype now, as it seems to be in a state where others might have a look and probably already find it useful :-). Anyway, we can easily disable it at one or two places in the code if it get's in our way of a new release.

Please see: http://wiki.ethereal.com/Development/ExpertInfo for a complete overview of the intended feature and it's current state of implementation.

While I'm working on this, I've also added some more status result codes to the DCE/RPC and DCOM dissectors.

svn path=/trunk/; revision=15754
This commit is contained in:
Ulf Lamping 2005-09-11 16:55:34 +00:00
parent 266e1a3491
commit 642467ad5c
17 changed files with 1019 additions and 60 deletions

View File

@ -49,6 +49,7 @@ LIBETHEREAL_SRC = \
emem.c \
epan.c \
except.c \
expert.c \
filesystem.c \
follow.c \
frame_data.c \
@ -115,6 +116,7 @@ LIBETHEREAL_INCLUDES = \
epan_dissect.h \
except.h \
exceptions.h \
expert.h \
filesystem.h \
follow.h \
frame_data.h \

View File

@ -41,6 +41,7 @@
#include "packet-esis.h"
#include "nlpid.h"
#include <epan/ipproto.h>
#include <epan/expert.h>
/* protocols and fields */
@ -782,7 +783,7 @@ static int ositp_decode_DR(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
packet_info *pinfo, proto_tree *tree)
{
proto_tree *cotp_tree;
proto_item *ti;
proto_item *ti = NULL;
guint16 dst_ref, src_ref;
guchar reason;
const char *str;
@ -843,6 +844,9 @@ static int ositp_decode_DR(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
offset += li + 1;
expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_CHAT,
"Disconnect Request(DR): 0x%x -> 0x%x", src_ref, dst_ref);
/* User data */
call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
offset += tvb_length_remaining(tvb, offset);
@ -1176,6 +1180,7 @@ static int ositp_decode_RJ(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
{
proto_tree *cotp_tree;
proto_item *ti;
proto_item *item = NULL;
guint16 dst_ref;
guint tpdu_nr;
gushort credit = 0;
@ -1206,7 +1211,7 @@ static int ositp_decode_RJ(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
cotp_tree = proto_item_add_subtree(ti, ett_cotp);
proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu);
item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu);
if (li == LI_NORMAL_RJ)
proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
"Credit: %u", cdt);
@ -1224,6 +1229,9 @@ static int ositp_decode_RJ(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
offset += li + 1;
expert_add_info_format(pinfo, item, PI_SEQUENCE, PI_NOTE,
"Reject(RJ): -> 0x%x", dst_ref);
return offset;
} /* ositp_decode_RJ */
@ -1238,6 +1246,7 @@ static int ositp_decode_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
proto_tree *cotp_tree = NULL;
proto_item *ti;
proto_item *item = NULL;
guint16 dst_ref, src_ref;
guchar class_option;
tvbuff_t *next_tvb;
@ -1266,7 +1275,7 @@ static int ositp_decode_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
offset += 1;
if (tree) {
proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
}
offset += 1;
li -= 1;
@ -1281,6 +1290,14 @@ static int ositp_decode_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
offset += 2;
li -= 2;
/* expert info, but only if not encapsulated in TCP/SMB */
/* XXX - the best way to detect seems to be if we have a port set */
if (pinfo->destport == 0) {
expert_add_info_format(pinfo, item, PI_SEQUENCE, PI_CHAT,
tpdu == CR_TPDU ? "Connection Request(CR): 0x%x -> 0x%x" : "Connection Confirm(CC): 0x%x -> 0x%x",
src_ref, dst_ref);
}
if (tree) {
proto_tree_add_text(cotp_tree, tvb, offset, 1,
"Class option: 0x%02x", class_option);
@ -1315,6 +1332,7 @@ static int ositp_decode_DC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
{
proto_tree *cotp_tree = NULL;
proto_item *ti;
proto_item *item = NULL;
guint16 dst_ref, src_ref;
if (li > LI_MAX_DC)
@ -1339,7 +1357,7 @@ static int ositp_decode_DC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
offset += 1;
if (tree) {
proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
}
offset += 1;
li -= 1;
@ -1358,6 +1376,9 @@ static int ositp_decode_DC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
offset += li;
expert_add_info_format(pinfo, item, PI_SEQUENCE, PI_CHAT,
"Disconnect Confirm(DC): 0x%x -> 0x%x", src_ref, dst_ref);
return offset;
} /* ositp_decode_DC */
@ -1684,6 +1705,7 @@ static gboolean dissect_ositp_internal(tvbuff_t *tvb, packet_info *pinfo,
if (!first_tpdu) {
if (check_col(pinfo->cinfo, COL_INFO))
col_append_str(pinfo->cinfo, COL_INFO, ", ");
expert_add_info_format(pinfo, NULL, PI_SEQUENCE, PI_NOTE, "Multiple TDPUs in one packet");
}
if ((li = tvb_get_guint8(tvb, offset + P_LI)) == 0) {
if (check_col(pinfo->cinfo, COL_INFO))

View File

@ -45,6 +45,7 @@
#include <epan/emem.h>
#include <epan/dissectors/packet-frame.h>
#include <epan/dissectors/packet-dcerpc-nt.h>
#include <epan/expert.h>
static int dcerpc_tap = -1;
@ -284,6 +285,29 @@ static const value_string reject_status_vals[] = {
{ 0x1c010013, "nca_out_args_too_big" },
{ 0x1c010014, "nca_server_too_busy" },
{ 0x1c010017, "nca_unsupported_type" },
/* MS Windows specific values
* see: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes__1700-3999_.asp
* and: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/common_hresult_values.asp
* and: http://www.megos.ch/support/doserrors.txt
*
* XXX - we might need a way to dynamically add entries here, as higher layer protocols use these values too,
* at least MS protocols (like DCOM) do it that way ... */
{ 0x80004001, "E_NOTIMPL" },
{ 0x80004003, "E_POINTER" },
{ 0x80004004, "E_ABORT" },
{ 0x80010105, "RPC_E_SERVERFAULT" },
{ 0x80010108, "RPC_E_DISCONNECTED" },
{ 0x80010113, "RPC_E_INVALID_IPID" },
{ 0x80020006, "DISP_E_UNKNOWNNAME" },
{ 0x8004CB00, "CBA_E_MALFORMED" },
{ 0x8004CB01, "CBA_E_UNKNOWNOBJECT" },
{ 0x8004CB09, "CBA_E_INVALIDCOOKIE" },
{ 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" },
{ 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" },
{ 0x8004CB0F, "CBA_E_NOTAPPLICABLE" },
{ 0x8004CB12, "CBA_E_LIMITVIOLATION" },
{ 0x80070057, "E_INVALIDARG" },
{ 0x800706d1, "RPC_S_PROCNUM_OUT_OF_RANGE" },
{ 0, NULL }
};
@ -3040,6 +3064,8 @@ dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
col_append_fstr(pinfo->cinfo, COL_INFO,
" [DCE/RPC %s fragment]", fragment_type(hdr->flags));
}
expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
"%s fragment", fragment_type(hdr->flags));
pinfo->fragmented = save_fragmented;
return;
}
@ -3166,6 +3192,9 @@ end_cn_stub:
pinfo->fragmented = FALSE;
expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
"%s fragment, reassembled here in #%u", fragment_type(hdr->flags), fd_head->reassembled_in);
dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
next_tvb, hdr->drep, di, auth_info);
@ -3181,6 +3210,8 @@ end_cn_stub:
col_append_fstr(pinfo->cinfo, COL_INFO,
" [DCE/RPC %s fragment, reas: #%u]", fragment_type(hdr->flags), fd_head->reassembled_in);
}
expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
"%s fragment, reassembled in #%u", fragment_type(hdr->flags), fd_head->reassembled_in);
}
} else {
/* Reassembly not complete - some fragments
@ -3189,6 +3220,8 @@ end_cn_stub:
col_append_fstr(pinfo->cinfo, COL_INFO,
" [DCE/RPC %s fragment]", fragment_type(hdr->flags));
}
expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
"%s fragment", fragment_type(hdr->flags));
if(decrypted_tvb){
show_stub_data (decrypted_tvb, 0, tree, auth_info, FALSE);
@ -3560,7 +3593,7 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
guint32 status;
guint32 alloc_hint;
dcerpc_auth_info auth_info;
proto_item *pi;
proto_item *pi = NULL;
offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
hf_dcerpc_cn_alloc_hint, &alloc_hint);
@ -3573,8 +3606,19 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
/* padding */
offset++;
offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
hf_dcerpc_cn_status, &status);
/*offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
hf_dcerpc_cn_status, &status);*/
status = ((hdr->drep[0] & 0x10)
? tvb_get_letohl (tvb, offset)
: tvb_get_ntohl (tvb, offset));
if (dcerpc_tree) {
pi = proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_status, tvb, offset, 4, (hdr->drep[0] & 0x10));
}
offset+=4;
expert_add_info_format(pinfo, pi, PI_APPL_RESPONSE, PI_NOTE, "Fault: %s",
val_to_str(status, reject_status_vals, "Unknown (0x%08x)"));
/* save context ID for use with dcerpc_add_conv_to_bind_table() */
pinfo->dcectxid = ctx_id;
@ -3910,6 +3954,11 @@ dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
pckt_vals[hdr.ptype].strptr, hdr.call_id);
}
if(pinfo->dcectxid != 0) {
/* this is not the first DCE-RPC request/response in this (TCP?-)PDU */
expert_add_info_format(pinfo, NULL, PI_SEQUENCE, PI_NOTE, "Multiple DCE/RPC fragments/PDU's in one packet");
}
if (tree) {
offset = start_offset;
tvb_ensure_bytes_exist(tvb, offset, hdr.frag_len);
@ -3919,7 +3968,20 @@ dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
}
proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset++, 1, hdr.rpc_ver);
proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset++, 1, hdr.rpc_ver_minor);
proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, hdr.ptype);
tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, hdr.ptype);
} else {
tf = NULL;
}
/* XXX - too much "output noise", removed for now
if(hdr.ptype == PDU_BIND || hdr.ptype == PDU_ALTER ||
hdr.ptype == PDU_BIND_ACK || hdr.ptype == PDU_ALTER_ACK)
expert_add_info_format(pinfo, tf, PI_SEQUENCE, PI_CHAT, "Context change: %s",
val_to_str(hdr.ptype, pckt_vals, "(0x%x)"));*/
if(hdr.ptype == PDU_BIND_NAK)
expert_add_info_format(pinfo, tf, PI_SEQUENCE, PI_WARN, "Bind not acknowledged");
if (tree) {
proto_item_append_text(ti, " %s, Fragment:", val_to_str(hdr.ptype, pckt_vals, "Unknown (0x%02x)"));
tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_flags, tvb, offset, 1, hdr.flags);

View File

@ -87,6 +87,7 @@
#include "packet-dcerpc.h"
#include "packet-dcom.h"
#include "prefs.h"
#include "expert.h"
static int proto_dcom = -1;
@ -339,10 +340,12 @@ const value_string dcom_hresult_vals[] = {
{ 0x80070057, "E_INVALIDARG" },
{ 0x80010108, "RPC_E_DISCONNECTED" },
{ 0x80010113, "RPC_E_INVALID_IPID" },
{ 0x80020004, "DISP_E_PARAMNOTFOUND" },
{ 0x80040154, "REGDB_E_CLASSNOTREG" },
{ 0x80040201, "CO_E_FAILEDTOGETSECCTX" },
/* following are CBA application specific values */
{ 0x0004CA00, "CBA_S_PERSISTPENDING" },
@ -391,6 +394,9 @@ const value_string dcom_hresult_vals[] = {
{ 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" },
{ 0x8004CB24, "CBA_E_LINKFAILURE" },
{ 0x8004CB25, "CBA_E_MODECHANGE" },
{ 0x80080004, "CO_E_BAD_PATH" },
{ 0, NULL }
};
@ -730,11 +736,14 @@ extern int
dissect_dcom_tobedone_data(tvbuff_t *tvb, int offset,
packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, int length)
{
proto_item *item;
proto_tree_add_uint(tree, hf_dcom_tobedone_len, tvb, offset, length, length);
proto_tree_add_bytes(tree, hf_dcom_tobedone, tvb, offset, length,
item = proto_tree_add_bytes(tree, hf_dcom_tobedone, tvb, offset, length,
tvb_get_ptr(tvb, offset, length));
expert_add_info_format(pinfo, item, PI_UNDECODED, PI_WARN, "%u bytes still undecoded", length);
offset += length;
return offset;
@ -807,8 +816,26 @@ dissect_dcom_HRESULT(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint8 *drep,
guint32 * pu32HResult)
{
offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep,
hf_dcom_hresult, pu32HResult);
guint32 u32HResult;
proto_item *item = NULL;
/* dissect the DWORD, but don't add to tree */
offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, drep,
hf_dcom_hresult, &u32HResult);
if (tree) {
/* special formatted output of indexed value */
item = proto_tree_add_item (tree, hf_dcom_hresult, tvb, offset-4, 4, (drep[0] & 0x10));
}
/* expert info only if severity is set */
/* XXX - move this to the callers of this function, to provide a more detailed error output */
if(u32HResult & 0x80000000) {
expert_add_info_format(pinfo, item, PI_APPL_RESPONSE, PI_NOTE, "Hresult: %s",
val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
}
if (pu32HResult)
*pu32HResult = u32HResult;
return offset;
}
@ -821,6 +848,7 @@ dissect_dcom_indexed_HRESULT(tvbuff_t *tvb, int offset, packet_info *pinfo,
guint32 * pu32HResult, int field_index)
{
guint32 u32HResult;
proto_item *item = NULL;
/* dissect the DWORD, but don't add to tree */
@ -829,11 +857,17 @@ dissect_dcom_indexed_HRESULT(tvbuff_t *tvb, int offset, packet_info *pinfo,
if (tree) {
/* special formatted output of indexed value */
proto_tree_add_uint_format(tree, hf_dcom_hresult, tvb, offset-4, 4, (drep[0] & 0x10),
item = proto_tree_add_uint_format(tree, hf_dcom_hresult, tvb, offset-4, 4, (drep[0] & 0x10),
"HResult[%u]: %s (0x%08x)", field_index,
val_to_str(u32HResult, dcom_hresult_vals, "Unknown"),
u32HResult);
}
/* expert info only if severity flag is set */
/* XXX - move this to the callers of this function, to provide a more detailed error output */
if(u32HResult & 0x80000000) {
expert_add_info_format(pinfo, item, PI_APPL_RESPONSE, PI_NOTE, "Hresult: %s",
val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
}
if (pu32HResult)
*pu32HResult = u32HResult;

View File

@ -34,6 +34,7 @@
#include "packet-frame.h"
#include <epan/prefs.h>
#include <epan/tap.h>
#include <epan/expert.h>
int proto_frame = -1;
int hf_frame_arrival_time = -1;
@ -264,14 +265,18 @@ show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
{
static const char dissector_error_nomsg[] =
"Dissector writer didn't bother saying what the error was";
proto_item *item;
switch (exception) {
case BoundsError:
if (check_col(pinfo->cinfo, COL_INFO))
col_append_str(pinfo->cinfo, COL_INFO, "[Short Frame]");
proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0,
item = proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0,
"[Short Frame: %s]", pinfo->current_proto);
expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
"Short Frame");
break;
case ReportedBoundsError:
@ -285,7 +290,7 @@ show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
pinfo->current_proto,
exception_message == NULL ?
dissector_error_nomsg : exception_message);
proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0,
item = proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0,
"[Dissector bug, protocol %s: %s]",
pinfo->current_proto,
exception_message == NULL ?
@ -294,6 +299,9 @@ show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
pinfo->current_proto, pinfo->fd->num,
exception_message == NULL ?
dissector_error_nomsg : exception_message);
expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
exception_message == NULL ?
dissector_error_nomsg : exception_message);
if (exception_message != NULL)
g_free(exception_message);
break;
@ -307,6 +315,8 @@ show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
void
show_reported_bounds_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_item *item;
if (pinfo->fragmented) {
/*
* We were dissecting an unreassembled fragmented
@ -320,15 +330,17 @@ show_reported_bounds_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
col_append_fstr(pinfo->cinfo, COL_INFO,
"[Unreassembled Packet%s]",
pinfo->noreassembly_reason);
proto_tree_add_protocol_format(tree, proto_unreassembled,
item = proto_tree_add_protocol_format(tree, proto_unreassembled,
tvb, 0, 0, "[Unreassembled Packet%s: %s]",
pinfo->noreassembly_reason, pinfo->current_proto);
expert_add_info_format(pinfo, item, PI_REASSEMBLE, PI_WARN, "Unreassembled Packet (Exception occured)");
} else {
if (check_col(pinfo->cinfo, COL_INFO))
col_append_str(pinfo->cinfo, COL_INFO,
"[Malformed Packet]");
proto_tree_add_protocol_format(tree, proto_malformed,
item = proto_tree_add_protocol_format(tree, proto_malformed,
tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Malformed Packet (Exception occured)");
}
}

View File

@ -47,6 +47,7 @@
#include <epan/req_resp_hdrs.h>
#include "packet-http.h"
#include <epan/prefs.h>
#include <epan/expert.h>
typedef enum _http_type {
HTTP_REQUEST,
@ -755,6 +756,8 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
tvb_format_text(tvb, offset,
next_offset - offset));
}
expert_add_info_format(pinfo, hdr_item, PI_SEQUENCE, PI_CHAT,
tvb_format_text(tvb, offset, next_offset - offset));
if (reqresp_dissector) {
if (tree) req_tree = proto_item_add_subtree(hdr_item, ett_http_request);
else req_tree = NULL;

View File

@ -46,6 +46,7 @@
#include <epan/tap.h>
#include <epan/emem.h>
#include <epan/slab.h>
#include <epan/expert.h>
static int tcp_tap = -1;
@ -1306,13 +1307,14 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree
if( ta->flags&TCP_A_RETRANSMISSION ){
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_retransmission, tvb, 0, 0, "This frame is a (suspected) retransmission");
PROTO_ITEM_SET_GENERATED(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Retransmission (suspected)");
if(check_col(pinfo->cinfo, COL_INFO)){
col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] ");
}
if( ta->rto_ts.secs || ta->rto_ts.nsecs ){
item = proto_tree_add_time(flags_tree, hf_tcp_analysis_rto,
tvb, 0, 0, &ta->rto_ts);
PROTO_ITEM_SET_GENERATED(item);
PROTO_ITEM_SET_GENERATED(item);
item=proto_tree_add_uint(flags_tree, hf_tcp_analysis_rto_frame, tvb, 0, 0, ta->rto_frame);
PROTO_ITEM_SET_GENERATED(item);
}
@ -1320,6 +1322,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree
if( ta->flags&TCP_A_FAST_RETRANSMISSION ){
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_fast_retransmission, tvb, 0, 0, "This frame is a (suspected) fast retransmission");
PROTO_ITEM_SET_GENERATED(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN, "Fast retransmission (suspected)");
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_retransmission, tvb, 0, 0, "This frame is a (suspected) retransmission");
PROTO_ITEM_SET_GENERATED(flags_item);
if(check_col(pinfo->cinfo, COL_INFO)){
@ -1329,6 +1332,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree
if( ta->flags&TCP_A_OUT_OF_ORDER ){
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_out_of_order, tvb, 0, 0, "This frame is a (suspected) out-of-order segment");
PROTO_ITEM_SET_GENERATED(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN, "Out-Of-Order segment");
if(check_col(pinfo->cinfo, COL_INFO)){
col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] ");
}
@ -1336,6 +1340,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree
if( ta->flags&TCP_A_LOST_PACKET ){
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_lost_packet, tvb, 0, 0, "A segment before this frame was lost");
PROTO_ITEM_SET_GENERATED(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN, "Previous segment lost (common at capture start)");
if(check_col(pinfo->cinfo, COL_INFO)){
col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Previous segment lost] ");
}
@ -1343,6 +1348,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree
if( ta->flags&TCP_A_ACK_LOST_PACKET ){
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_ack_lost_packet, tvb, 0, 0, "This frame ACKs a segment we have not seen (lost?)");
PROTO_ITEM_SET_GENERATED(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN, "ACKed lost segment (common at capture start)");
if(check_col(pinfo->cinfo, COL_INFO)){
col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP ACKed lost segment] ");
}
@ -1350,6 +1356,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree
if( ta->flags&TCP_A_WINDOW_UPDATE ){
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_window_update, tvb, 0, 0, "This is a tcp window update");
PROTO_ITEM_SET_GENERATED(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Window update");
if(check_col(pinfo->cinfo, COL_INFO)){
col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] ");
}
@ -1357,6 +1364,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree
if( ta->flags&TCP_A_WINDOW_FULL ){
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_window_full, tvb, 0, 0, "The transmission window is now completely full");
PROTO_ITEM_SET_GENERATED(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Window is full");
if(check_col(pinfo->cinfo, COL_INFO)){
col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] ");
}
@ -1364,6 +1372,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree
if( ta->flags&TCP_A_KEEP_ALIVE ){
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_keep_alive, tvb, 0, 0, "This is a TCP keep-alive segment");
PROTO_ITEM_SET_GENERATED(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Keep-Alive");
if(check_col(pinfo->cinfo, COL_INFO)){
col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] ");
}
@ -1371,6 +1380,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree
if( ta->flags&TCP_A_KEEP_ALIVE_ACK ){
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_keep_alive_ack, tvb, 0, 0, "This is an ACK to a TCP keep-alive segment");
PROTO_ITEM_SET_GENERATED(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Keep-Alive ACK");
if(check_col(pinfo->cinfo, COL_INFO)){
col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] ");
}
@ -1389,10 +1399,13 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree
flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_frame,
tvb, 0, 0, ta->dupack_frame);
PROTO_ITEM_SET_GENERATED(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Duplicate ACK (#%u) to ACK in packet #%u",
ta->dupack_num, ta->dupack_frame);
}
if( ta->flags&TCP_A_ZERO_WINDOW_PROBE ){
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_zero_window_probe, tvb, 0, 0, "This is a TCP zero-window-probe");
PROTO_ITEM_SET_GENERATED(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Zero window probe");
if(check_col(pinfo->cinfo, COL_INFO)){
col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] ");
}
@ -1400,7 +1413,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree
if( ta->flags&TCP_A_ZERO_WINDOW ){
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_zero_window, tvb, 0, 0, "This is a ZeroWindow segment");
PROTO_ITEM_SET_GENERATED(flags_item);
PROTO_ITEM_SET_SEQUENCE_WARNING(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Zero window");
if(check_col(pinfo->cinfo, COL_INFO)){
col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] ");
}
@ -1408,6 +1421,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree
if( ta->flags&TCP_A_ZERO_WINDOW_VIOLATION ){
flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_zero_window_violation, tvb, 0, 0, "This is a ZeroWindow violation, attempts to write >1 byte of data to a zero-window");
PROTO_ITEM_SET_GENERATED(flags_item);
expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Zero window violation");
if(check_col(pinfo->cinfo, COL_INFO)){
col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowViolation] ");
}
@ -2679,6 +2693,7 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
struct tcpinfo tcpinfo;
static struct tcpheader tcphstruct[4], *tcph;
static int tcph_count=0;
proto_item *tf_syn = NULL, *tf_fin = NULL, *tf_rst = NULL;
tcph_count++;
if(tcph_count>=4){
@ -2866,9 +2881,9 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, tcph->th_flags);
proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, tcph->th_flags);
proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, tcph->th_flags);
proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags);
proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags);
proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags);
tf_rst = proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags);
tf_syn = proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags);
tf_fin = proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags);
if(tcp_relative_seq && (tcph->th_win!=real_window)){
proto_tree_add_uint_format(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, tcph->th_win, "Window size: %u (scaled)", tcph->th_win);
} else {
@ -2876,6 +2891,20 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
}
if(tcph->th_flags & TH_SYN)
if(tcph->th_flags & TH_ACK)
expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_CHAT, "Connection establish acknowledge (SYN+ACK): %s -> %s",
get_tcp_port(tcph->th_sport), get_tcp_port(tcph->th_dport));
else
expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_CHAT, "Connection establish request (SYN): %s -> %s",
get_tcp_port(tcph->th_sport), get_tcp_port(tcph->th_dport));
if(tcph->th_flags & TH_FIN)
expert_add_info_format(pinfo, tf_fin, PI_SEQUENCE, PI_CHAT, "Connection finish (FIN): %s -> %s",
get_tcp_port(tcph->th_sport), get_tcp_port(tcph->th_dport));
if(tcph->th_flags & TH_RST)
expert_add_info_format(pinfo, tf_rst, PI_SEQUENCE, PI_CHAT, "Connection reset (RST): %s -> %s",
get_tcp_port(tcph->th_sport), get_tcp_port(tcph->th_dport));
/* Supply the sequence number of the first byte and of the first byte
after the segment. */
tcpinfo.seq = tcph->th_seq;
@ -2937,13 +2966,15 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
} else {
proto_item *item;
proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
offset + 16, 2, th_sum,
"Checksum: 0x%04x [incorrect, should be 0x%04x]", th_sum,
in_cksum_shouldbe(th_sum, computed_cksum));
expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");
item = proto_tree_add_boolean(tcp_tree, hf_tcp_checksum_bad, tvb,
offset + 16, 2, TRUE);
PROTO_ITEM_SET_GENERATED(item);
/* XXX - don't use hidden fields for checksums */
PROTO_ITEM_SET_HIDDEN(item);
if (check_col(pinfo->cinfo, COL_INFO))
@ -2955,7 +2986,7 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
} else {
proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
offset + 16, 2, th_sum, "Checksum: 0x%04x", th_sum);
offset + 16, 2, th_sum, "Checksum: 0x%04x [validation disabled]", th_sum);
/* We didn't check the checksum, and don't care if it's valid,
so we're willing to desegment it. */
@ -2964,7 +2995,7 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
} else {
/* We don't have all the packet data, so we can't checksum it... */
proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
offset + 16, 2, th_sum, "Checksum: 0x%04x", th_sum);
offset + 16, 2, th_sum, "Checksum: 0x%04x [unchecked, not all data available]", th_sum);
/* ...and aren't willing to desegment it. */
desegment_ok = FALSE;
@ -3201,7 +3232,7 @@ proto_register_tcp(void)
{ &hf_tcp_analysis_window_full,
{ "Window full", "tcp.analysis.window_full", FT_NONE, BASE_NONE, NULL, 0x0,
"The this segment has caused the allowed window to become 100% full", HFILL }},
"This segment has caused the allowed window to become 100% full", HFILL }},
{ &hf_tcp_analysis_keep_alive,
{ "Keep Alive", "tcp.analysis.keep_alive", FT_NONE, BASE_NONE, NULL, 0x0,
@ -3397,8 +3428,8 @@ proto_register_tcp(void)
"Whether the TCP summary line should be shown in the protocol tree",
&tcp_summary_in_tree);
prefs_register_bool_preference(tcp_module, "check_checksum",
"Check the validity of the TCP checksum when possible",
"Whether to check the validity of the TCP checksum",
"Validate the TCP checksum if possible",
"Whether to validate the TCP checksum",
&tcp_check_checksum);
prefs_register_bool_preference(tcp_module, "desegment_tcp_streams",
"Allow subdissector to reassemble TCP streams",

View File

@ -22,6 +22,7 @@
#include "tap.h"
#include "addr_resolv.h"
#include "emem.h"
#include "expert.h"
static void (*report_failure_func)(const char *, va_list);
static void (*report_open_failure_func)(const char *, int, gboolean);
@ -66,11 +67,13 @@ epan_init(const char *plugin_dir, void (*register_all_protocols)(void),
dfilter_init();
final_registration_all_protocols();
host_name_lookup_init();
expert_init();
}
void
epan_cleanup(void)
{
expert_cleanup();
dfilter_cleanup();
proto_cleanup();
packet_cleanup();

117
epan/expert.c Normal file
View File

@ -0,0 +1,117 @@
/* expert.c
* Collecting Expert information.
*
* Implemented as a tap named "expert".
*
* $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "packet.h"
#include "expert.h"
#include "emem.h"
#include "tap.h"
static int expert_tap = -1;
void
expert_init(void)
{
if(expert_tap == -1) {
expert_tap = register_tap("expert");
}
}
void
expert_cleanup(void)
{
/* memory cleanup will be done by se_... */
}
/* set's the PI_ flags to a protocol item
* (and it's parent items till the toplevel) */
static void
expert_set_item_flags(proto_item *pi, int group, int severity)
{
if(proto_item_set_expert_flags(pi, group, severity)) {
/* propagate till toplevel item */
pi = proto_item_get_parent(pi);
expert_set_item_flags(pi, group, severity);
}
}
static void
expert_set_info_vformat(
packet_info *pinfo, proto_item *pi, int group, int severity, const char *format, va_list ap)
{
int ret; /*tmp return value */
char formatted[300];
expert_info_t *ei;
/* if this packet isn't loaded because of a read filter, don't output anything */
if(pinfo->fd->num == -1) {
return;
}
/* XXX - use currently nonexistant se_vsnprintf instead */
ret = g_vsnprintf(formatted, sizeof(formatted), format, ap);
if ((ret == -1) || (ret >= sizeof(formatted)))
formatted[sizeof(formatted) - 1] = '\0';
ei = se_alloc(sizeof(expert_info_t));
ei->packet_num = pinfo ? pinfo->fd->num : -1;
ei->group = group;
ei->severity = severity;
ei->protocol = se_strdup(pinfo->current_proto);
ei->summary = se_strdup(formatted);
/* if we have a proto_item (not a faked item), set expert attributes to it */
if(pi != NULL && pi->finfo != NULL) {
expert_set_item_flags(pi, group, severity);
}
tap_queue_packet(expert_tap, pinfo, ei);
}
void
expert_add_info_format(
packet_info *pinfo, proto_item *pi, int group, int severity, const char *format, ...)
{
va_list ap;
va_start(ap, format);
expert_set_info_vformat(pinfo, pi, group, severity, format, ap);
va_end(ap);
}

60
epan/expert.h Normal file
View File

@ -0,0 +1,60 @@
/* expert.h
* Collecting of Expert information.
*
* For further info, see: http://wiki.ethereal.com/Development/ExpertInfo
*
* $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __EXPERT_H__
#define __EXPERT_H__
/** only for internal and display use */
typedef struct expert_info_s {
int packet_num;
int group;
int severity;
gchar * protocol;
gchar * summary;
} expert_info_t;
extern void
expert_init(void);
extern void
expert_cleanup(void);
/** Add an expert info.
* XXX - add gcc format string check.
@param pinfo packet info of the currently processed packet
@param pi current protocol item (or NULL)
@param group the expert group (like PI_CHECKSUM)
@param severity the expert severity (like PI_WARN)
@param format printf like format string with further infos
*/
extern void
expert_add_info_format(
packet_info *pinfo, proto_item *pi, int group, int severity, const char *format, ...);
#endif /* __EXPERT_H__ */

View File

@ -191,7 +191,9 @@ ep_alloc
se_alloc
ep_alloc0
ep_strdup
se_strdup
ep_strdup_printf
se_strdup_printf
ep_strndup
ep_strsplit
ep_memdup
@ -217,6 +219,7 @@ except_throw
except_throwd
except_throwf
except_unhandled_catcher
expert_set_info_format
FacilityReason_vals DATA
fc_fc4_val DATA
file_open_error_message
@ -404,6 +407,7 @@ proto_item_get_parent
proto_item_get_parent_nth
proto_item_get_subtree
proto_item_set_end
proto_item_set_expert_flags
proto_item_set_len
proto_item_set_text
proto_register_field_array

View File

@ -2465,6 +2465,32 @@ proto_item_get_len(proto_item *pi)
return fi->length;
}
/** clear flags according to the mask and set new flag values */
#define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
(fi->flags = (fi)->flags & ~(mask)); \
(fi->flags = (fi)->flags | (flags_in)); \
}
gboolean
proto_item_set_expert_flags(proto_item *pi, int group, int severity)
{
if(pi == NULL || pi->finfo == NULL)
return FALSE;
/* only change things if severity is worse or at least equal than before */
if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
return TRUE;
}
return FALSE;
}
proto_tree*
proto_tree_create_root(void)
{

View File

@ -218,20 +218,13 @@ typedef struct field_info {
/** The protocol field should be displayed as "generated by Ethereal",
* used in field_info.flags. */
#define FI_GENERATED 0x0002
/** The protocol field has a bad checksum */
#define FI_CHECKSUM_ERROR 0x0004
/** The protocol field has an unusual sequence (e.g. TCP window is zero) */
#define FI_SEQUENCE_WARNING 0x0008
/** The protocol field has a bad sequence (e.g. TCP segment is lost) */
#define FI_SEQUENCE_ERROR 0x0010
/** convenience macro to get field_info.flags */
#define FI_GET_FLAG(fi, flag) (fi->flags & flag)
/** convenience macro to set field_info.flags */
#define FI_SET_FLAG(fi, flag) (fi->flags = fi->flags | flag)
/** One of these exists for the entire protocol tree. Each proto_node
* in the protocol tree points to the same copy. */
typedef struct {
@ -254,6 +247,38 @@ typedef proto_node proto_tree;
/** A protocol item element. */
typedef proto_node proto_item;
/* expert severities */
#define PI_SEVERITY_MASK 0x001C /* mask usually for internal use only! */
/** Usual workflow, e.g. TCP connection establishing */
#define PI_CHAT 0x0004
/** Notable messages, e.g. an application returned an "usual" error code like HTTP 404 */
#define PI_NOTE 0x0008
/** Warning, e.g. application returned an "unusual" error code */
#define PI_WARN 0x000C
/** Serious problems, e.g. [Malformed Packet] */
#define PI_ERROR 0x0010
/* expert "event groups" */
#define PI_GROUP_MASK 0xFF00 /* mask usually for internal use only! */
/** The protocol field has a bad checksum, usually PI_WARN */
#define PI_CHECKSUM 0x0100
/** The protocol field indicates a sequence problem (e.g. TCP window is zero) */
#define PI_SEQUENCE 0x0200
/** The protocol field indicates a bad application response code (e.g. HTTP 404), usually PI_NOTE */
#define PI_RESPONSE_CODE 0x0400
/** The data is undecoded, the protocol dissection is incomplete here, usually PI_WARN */
#define PI_UNDECODED 0x0800
/** The protocol field indicates a reassemble (e.g. DCE/RPC defragmentation), usually PI_CHAT (or PI_ERROR) */
#define PI_REASSEMBLE 0x1000
/** The packet data is malformed, the dissector has "given up", usually PI_ERROR */
#define PI_MALFORMED 0x2000
/** A generic debugging message (shouldn't remain in production code!), usually PI_ERROR */
#define PI_DEBUG 0x4000
/** The protocol field indicates a security probem (e.g. unsecure implementation) */
/*#define PI_SECURITY 0x8000*/
/* add more, see http://wiki.ethereal.com/Development/ExpertInfo */
/** is this protocol field hidden from the protocol tree display (used for filtering only)? */
/* HIDING PROTOCOL FIELDS IS DEPRECATED, IT'S CONSIDERED TO BE BAD GUI DESIGN! */
@ -269,16 +294,6 @@ typedef proto_node proto_item;
/** mark this protocol field as generated by Ethereal (and not read from the packet data) */
#define PROTO_ITEM_SET_GENERATED(proto_item) \
((proto_item) ? FI_SET_FLAG((proto_item)->finfo, FI_GENERATED) : 0)
/** mark this protocol field having a bad checksum */
#define PROTO_ITEM_SET_CHECKSUM_ERROR(proto_item) \
((proto_item) ? FI_SET_FLAG((proto_item)->finfo, FI_CHECKSUM_ERROR) : 0)
/** mark this protocol field having a sequence warning */
#define PROTO_ITEM_SET_SEQUENCE_WARNING(proto_item) \
((proto_item) ? FI_SET_FLAG((proto_item)->finfo, FI_SEQUENCE_WARNING) : 0)
/** mark this protocol field having a sequence error */
#define PROTO_ITEM_SET_SEQUENCE_ERROR(proto_item) \
((proto_item) ? FI_SET_FLAG((proto_item)->finfo, FI_SEQUENCE_ERROR) : 0)
typedef void (*proto_tree_foreach_func)(proto_node *, gpointer);
@ -376,6 +391,16 @@ extern void proto_item_set_end(proto_item *ti, tvbuff_t *tvb, gint end);
@return the current length */
extern int proto_item_get_len(proto_item *ti);
/**
* Sets an expert info to the proto_item.
@param ti the item to set the expert info
@param group the group of this info (e.g. FI_CHECKSUM)
@param severity of this info (e.g. FI_ERROR)
@return TRUE if value was written
*/
extern gboolean proto_item_set_expert_flags(proto_item *ti, int group, int severity);
/** Creates a new proto_tree root.

View File

@ -122,6 +122,7 @@ ETHEREAL_TAP_SRC = \
conversations_wlan.c \
conversations_rsvp.c \
dcerpc_stat.c \
expert_dlg.c \
fc_stat.c \
flow_graph.c \
gsm_a_stat.c \

511
gtk/expert_dlg.c Normal file
View File

@ -0,0 +1,511 @@
/* expert_dlg.c
* Display of Expert information.
*
* Implemented as a tap listener to the "expert" tap.
*
* $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <epan/packet.h>
#include <epan/expert.h>
#include <epan/emem.h>
#include <epan/tap.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <gtk/gtk.h>
#include "compat_macros.h"
#include "epan/packet_info.h"
#include "image/clist_ascend.xpm"
#include "image/clist_descend.xpm"
#include "simple_dialog.h"
#include "globals.h"
#include "gtk/find_dlg.h"
#include "color.h"
#include "gtk/color_dlg.h"
#include "main.h"
#include "gui_utils.h"
#include "gtkglobals.h"
#include "dlg_utils.h"
#include "../stat_menu.h"
#include "gui_stat_menu.h"
#include <../tap_dfilter_dlg.h>
#include <epan/stat_cmd_args.h>
#include <epan/prefs.h>
#include "colors.h"
#include "proto_draw.h"
#include <epan/emem.h>
static const value_string expert_severity_vals[] = {
{ PI_CHAT, "Chat" },
{ PI_NOTE, "Note" },
{ PI_WARN, "Warn" },
{ PI_ERROR, "Error" },
{ 0, NULL }
};
static const value_string expert_group_vals[] = {
{ PI_CHECKSUM, "Checksum" },
{ PI_SEQUENCE, "Sequence" },
{ PI_APPL_RESPONSE, "Response" },
{ PI_UNDECODED, "Undecoded" },
{ PI_MALFORMED, "Malformed" },
{ PI_REASSEMBLE, "Reassemble" },
{ PI_SECURITY, "Security" },
{ 0, NULL }
};
typedef struct expert_tapdata_s {
GtkWidget *win;
GtkWidget *scrolled_window;
GtkCList *table;
GtkWidget *label;
GList *displayed_events;
GList *new_events;
guint32 chat_events;
guint32 note_events;
guint32 warn_events;
guint32 error_events;
} expert_tapdata_t;
/* the current warning severity */
/* XXX - make this a preference setting / a setting in the dialog */
int severity_report_level = PI_CHAT;
//int severity_report_level = PI_NOTE;
void expert_dlg_reset(void *tapdata)
{
expert_tapdata_t * etd = tapdata;
gchar *title;
g_list_free(etd->displayed_events);
etd->displayed_events = NULL;
g_list_free(etd->new_events);
etd->new_events = NULL;
etd->chat_events = 0;
etd->note_events = 0;
etd->warn_events = 0;
etd->error_events = 0;
gtk_clist_clear(etd->table);
gtk_clist_columns_autosize(etd->table);
title = g_strdup_printf("Errors: %u Warnings: %u Notes: %u Chats: %u",
etd->error_events, etd->warn_events, etd->note_events, etd->chat_events);
gtk_label_set_text(GTK_LABEL(etd->label), "Please wait ...");
g_free(title);
title = g_strdup_printf("Ethereal: %u Expert Infos",
g_list_length(etd->displayed_events));
gtk_window_set_title(GTK_WINDOW(etd->win), title);
g_free(title);
}
int expert_dlg_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *pointer)
{
expert_info_t *ei = (expert_info_t *) pointer;
expert_tapdata_t * etd = tapdata;
switch(ei->severity) {
case(PI_CHAT):
etd->chat_events++;
break;
case(PI_NOTE):
etd->note_events++;
break;
case(PI_WARN):
etd->warn_events++;
break;
case(PI_ERROR):
etd->error_events++;
break;
default:
g_assert_not_reached();
}
if(ei->severity < severity_report_level) {
return 0; /* draw not required */
}
etd->new_events = g_list_append(etd->new_events, ei);
return 1; /* draw required */
}
void
expert_dlg_draw(expert_tapdata_t *etd)
{
int row;
char *strp;
expert_info_t *ei;
gchar *title;
char *entries[5] = { "", "", "", "", "" }; /**< column entries */
/*g_warning("draw start: displayed:%u new:%u",
g_list_length(etd->displayed_events), g_list_length(etd->new_events));*/
title = g_strdup_printf("Errors: %u Warnings: %u Notes: %u Chats: %u",
etd->error_events, etd->warn_events, etd->note_events, etd->chat_events);
gtk_label_set_text(GTK_LABEL(etd->label), title);
g_free(title);
gtk_clist_freeze(etd->table);
/* append new events (remove from new list, append to displayed list and clist) */
while(etd->new_events != NULL){
ei = etd->new_events->data;
etd->new_events = g_list_remove(etd->new_events, ei);
etd->displayed_events = g_list_append(etd->displayed_events, ei);
row=gtk_clist_append(etd->table, entries);
gtk_clist_set_row_data(etd->table, row, ei);
/* packet number */
strp=se_strdup_printf("%d", ei->packet_num);
gtk_clist_set_text(etd->table, row, 0, strp);
/* severity */
strp=se_strdup(val_to_str(ei->severity, expert_severity_vals, "Unknown severity (%u)"));
gtk_clist_set_text(etd->table, row, 1, strp);
/* group */
strp=se_strdup(val_to_str(ei->group, expert_group_vals, "Unknown group (%u)"));
gtk_clist_set_text(etd->table, row, 2, strp);
/* protocol */
if(ei->protocol) {
gtk_clist_set_text(etd->table, row, 3, ei->protocol);
} else {
gtk_clist_set_text(etd->table, row, 3, "-");
}
/* summary */
gtk_clist_set_text(etd->table, row, 4, ei->summary);
/*gtk_clist_set_pixmap(etd->table, row, 5, ascend_pm, ascend_bm);*/
/* set rows background color depending on severity */
switch(ei->severity) {
case(PI_CHAT):
gtk_clist_set_background(etd->table, row, &expert_color_chat);
break;
case(PI_NOTE):
gtk_clist_set_background(etd->table, row, &expert_color_note);
break;
case(PI_WARN):
gtk_clist_set_background(etd->table, row, &expert_color_warn);
break;
case(PI_ERROR):
gtk_clist_set_background(etd->table, row, &expert_color_error);
break;
default:
g_assert_not_reached();
}
}
gtk_clist_sort(etd->table);
gtk_clist_columns_autosize(etd->table);
gtk_clist_thaw(etd->table);
title = g_strdup_printf("Ethereal: %u Expert Infos",
g_list_length(etd->displayed_events));
gtk_window_set_title(GTK_WINDOW(etd->win), title);
g_free(title);
/*g_warning("draw end: displayed:%u", g_list_length(etd->displayed_events));*/
}
typedef struct column_arrows {
GtkWidget *table;
GtkWidget *ascend_pm;
GtkWidget *descend_pm;
} column_arrows;
static gint
srt_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
{
char *text1 = NULL;
char *text2 = NULL;
int i1, i2;
const GtkCListRow *row1 = ptr1;
const GtkCListRow *row2 = ptr2;
text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
switch(clist->sort_column){
case 0:
i1=atoi(text1);
i2=atoi(text2);
return i1-i2;
case 1:
case 2:
case 3:
case 4:
return strcmp (text1, text2);
}
g_assert_not_reached();
return 0;
}
static void
srt_click_column_cb(GtkCList *clist, gint column, gpointer data)
{
column_arrows *col_arrows = (column_arrows *) data;
int i;
gtk_clist_freeze(clist);
for (i = 0; i < 5; i++) {
gtk_widget_hide(col_arrows[i].ascend_pm);
gtk_widget_hide(col_arrows[i].descend_pm);
}
if (column == clist->sort_column) {
if (clist->sort_type == GTK_SORT_ASCENDING) {
clist->sort_type = GTK_SORT_DESCENDING;
gtk_widget_show(col_arrows[column].descend_pm);
} else {
clist->sort_type = GTK_SORT_ASCENDING;
gtk_widget_show(col_arrows[column].ascend_pm);
}
} else {
clist->sort_type = GTK_SORT_ASCENDING;
gtk_widget_show(col_arrows[column].ascend_pm);
gtk_clist_set_sort_column(clist, column);
}
gtk_clist_sort(clist);
gtk_clist_thaw(clist);
}
static void
select_row_cb(GtkCList *clist, gint row, gint column, GdkEventButton *event, gpointer user_data)
{
expert_info_t *ei;
ei = (expert_info_t *) gtk_clist_get_row_data(clist, row);
cf_goto_frame(&cfile, ei->packet_num);
}
void
expert_dlg_init_table(expert_tapdata_t * etd, GtkWidget *vbox)
{
int i;
column_arrows *col_arrows;
GtkStyle *win_style;
GtkWidget *column_lb;
GdkBitmap *ascend_bm, *descend_bm;
GdkPixmap *ascend_pm, *descend_pm;
const char *default_titles[] = { "No.", "Sever.", "Group", "Protocol", "Summary" };
etd->scrolled_window=scrolled_window_new(NULL, NULL);
gtk_box_pack_start(GTK_BOX(vbox), etd->scrolled_window, TRUE, TRUE, 0);
etd->table=(GtkCList *)gtk_clist_new(5);
SIGNAL_CONNECT(etd->table, "select-row", select_row_cb, etd);
gtk_widget_show(GTK_WIDGET(etd->table));
gtk_widget_show(etd->scrolled_window);
col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * 5);
win_style = gtk_widget_get_style(etd->scrolled_window);
ascend_pm = gdk_pixmap_create_from_xpm_d(etd->scrolled_window->window,
&ascend_bm,
&win_style->bg[GTK_STATE_NORMAL],
(gchar **)clist_ascend_xpm);
descend_pm = gdk_pixmap_create_from_xpm_d(etd->scrolled_window->window,
&descend_bm,
&win_style->bg[GTK_STATE_NORMAL],
(gchar **)clist_descend_xpm);
for (i = 0; i < 5; i++) {
col_arrows[i].table = gtk_table_new(2, 2, FALSE);
gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
column_lb = gtk_label_new(default_titles[i]);
gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
gtk_widget_show(column_lb);
col_arrows[i].ascend_pm = gtk_pixmap_new(ascend_pm, ascend_bm);
gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
col_arrows[i].descend_pm = gtk_pixmap_new(descend_pm, descend_bm);
gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
if (i == 0) {
gtk_widget_show(col_arrows[i].ascend_pm);
}
gtk_clist_set_column_widget(GTK_CLIST(etd->table), i, col_arrows[i].table);
gtk_widget_show(col_arrows[i].table);
}
gtk_clist_column_titles_show(GTK_CLIST(etd->table));
gtk_clist_set_compare_func(etd->table, srt_sort_column);
gtk_clist_set_sort_column(etd->table, 0);
gtk_clist_set_sort_type(etd->table, GTK_SORT_ASCENDING);
gtk_clist_set_column_justification(etd->table, 0, GTK_JUSTIFY_RIGHT);
gtk_clist_set_column_justification(etd->table, 3, GTK_JUSTIFY_RIGHT);
gtk_clist_set_shadow_type(etd->table, GTK_SHADOW_IN);
gtk_clist_column_titles_show(etd->table);
gtk_clist_columns_autosize(etd->table);
// gtk_clist_set_selection_mode(etd->table, GTK_SELECTION_SINGLE);
// gtk_list_set_selection_mode(GTK_LIST(etd->table), GTK_SELECTION_BROWSE);
// gtk_list_select_item(GTK_LIST(value_list), 0);
gtk_container_add(GTK_CONTAINER(etd->scrolled_window), (GtkWidget *)etd->table);
SIGNAL_CONNECT(etd->table, "click-column", srt_click_column_cb, col_arrows);
gtk_widget_show(GTK_WIDGET(etd->table));
gtk_widget_show(etd->scrolled_window);
/* create popup menu for this table */
/*if(etd->filter_string){
srt_create_popup_menu(etd);
}*/
}
void protect_thread_critical_region(void);
void unprotect_thread_critical_region(void);
static void
expert_dlg_destroy_cb(GtkWindow *win _U_, gpointer data)
{
expert_tapdata_t *etd=(expert_tapdata_t *)data;
protect_thread_critical_region();
remove_tap_listener(etd);
unprotect_thread_critical_region();
//free_srt_table_data(&etd->afp_srt_table);
g_free(etd);
}
static void
expert_dlg_init(const char *optarg)
{
expert_tapdata_t * etd;
const char *filter=NULL;
GString *error_string;
GtkWidget *vbox;
GtkWidget *bbox;
GtkWidget *close_bt;
if(!strncmp(optarg,"afp,srt,",8)){
filter=optarg+8;
} else {
filter=NULL;
}
proto_draw_colors_init();
etd=g_malloc(sizeof(expert_tapdata_t));
etd->displayed_events = NULL;
etd->new_events = NULL;
etd->chat_events = 0;
etd->note_events = 0;
etd->warn_events = 0;
etd->error_events = 0;
etd->win=window_new(GTK_WINDOW_TOPLEVEL, "Ethereal: Expert Info");
gtk_window_set_default_size(GTK_WINDOW(etd->win), 650, 600);
vbox=gtk_vbox_new(FALSE, 3);
gtk_container_add(GTK_CONTAINER(etd->win), vbox);
gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
etd->label=gtk_label_new("Please wait ...");
gtk_box_pack_start(GTK_BOX(vbox), etd->label, FALSE, FALSE, 0);
/* We must display TOP LEVEL Widget before calling init_srt_table() */
gtk_widget_show_all(etd->win);
expert_dlg_init_table(etd, vbox);
/*for(i=0;i<256;i++){
init_srt_table_row(&etd->afp_srt_table, i, val_to_str(i, CommandCode_vals, "Unknown(%u)"));
}*/
error_string=register_tap_listener("expert", etd, NULL /* fstring */,
expert_dlg_reset,
expert_dlg_packet,
expert_dlg_draw);
if(error_string){
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
g_string_free(error_string, TRUE);
g_free(etd);
return;
}
/* Button row. */
bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
window_set_cancel_button(etd->win, close_bt, window_cancel_button_cb);
SIGNAL_CONNECT(etd->win, "delete_event", window_delete_event_cb, NULL);
SIGNAL_CONNECT(etd->win, "destroy", expert_dlg_destroy_cb, etd);
gtk_widget_show_all(etd->win);
window_present(etd->win);
cf_retap_packets(&cfile);
}
static void
expert_dlg_cb(GtkWidget *w _U_, gpointer d _U_)
{
expert_dlg_init("");
}
void
register_tap_listener_expert(void)
{
register_stat_cmd_arg("expert", expert_dlg_init);
register_stat_menu_item("_Expert Info", REGISTER_STAT_GROUP_GENERIC,
expert_dlg_cb, NULL, NULL, NULL);
}

View File

@ -1602,6 +1602,27 @@ set_ptree_font_all(FONT_TYPE *font)
}
gboolean colors_ok = FALSE;
GdkColor expert_color_chat = { 0, 0xcc00, 0xcc00, 0xe000 }; /* a pale bluegrey */
GdkColor expert_color_note = { 0, 0xa000, 0xff00, 0xff00 }; /* a bright turquoise */
GdkColor expert_color_warn = { 0, 0xff00, 0xff00, 0 }; /* yellow */
GdkColor expert_color_error = { 0, 0xff00, 0x5c00, 0x5c00 }; /* pale red */
void proto_draw_colors_init(void)
{
if(colors_ok) {
return;
}
get_color(&expert_color_chat);
get_color(&expert_color_note);
get_color(&expert_color_warn);
get_color(&expert_color_error);
colors_ok = TRUE;
}
#if GTK_MAJOR_VERSION >= 2
static void tree_cell_renderer(GtkTreeViewColumn *tree_column _U_,
GtkCellRenderer *cell,
@ -1613,11 +1634,16 @@ static void tree_cell_renderer(GtkTreeViewColumn *tree_column _U_,
gtk_tree_model_get(tree_model, iter, 1, &fi, -1);
if(!colors_ok) {
proto_draw_colors_init();
}
/* for the various possible attributes, see:
* http://developer.gnome.org/doc/API/2.0/gtk/GtkCellRendererText.html
*
* color definitions can be found at:
* http://cvs.gnome.org/viewcvs/gtk+/gdk-pixbuf/io-xpm.c?rev=1.42
* (a good color overview: http://www.computerhope.com/htmcolor.htm)
*
* some experiences:
* background-gdk: doesn't seem to work (probably the GdkColor must be allocated)
@ -1639,22 +1665,9 @@ static void tree_cell_renderer(GtkTreeViewColumn *tree_column _U_,
/*g_object_set (cell, "weight", PANGO_WEIGHT_NORMAL, NULL);
g_object_set (cell, "weight-set", FALSE, NULL);*/
if(FI_GET_FLAG(fi, FI_CHECKSUM_ERROR)) {
g_object_set (cell, "background", "red", NULL);
g_object_set (cell, "background-set", TRUE, NULL);
}
if(FI_GET_FLAG(fi, FI_SEQUENCE_WARNING)) {
g_object_set (cell, "background", "yellow", NULL);
g_object_set (cell, "background-set", TRUE, NULL);
}
if(FI_GET_FLAG(fi, FI_SEQUENCE_ERROR)) {
g_object_set (cell, "background", "red", NULL);
g_object_set (cell, "background-set", TRUE, NULL);
}
if(FI_GET_FLAG(fi, FI_GENERATED)) {
/* we use "[...]" to mark generated items, no need to change things here */
/* as some fonts don't support italic, don't use this */
/*g_object_set (cell, "style", PANGO_STYLE_ITALIC, NULL);
g_object_set (cell, "style-set", TRUE, NULL);
@ -1677,6 +1690,29 @@ static void tree_cell_renderer(GtkTreeViewColumn *tree_column _U_,
g_object_set (cell, "underline", PANGO_UNDERLINE_SINGLE, NULL);
g_object_set (cell, "underline-set", TRUE, NULL);
}
if(FI_GET_FLAG(fi, PI_SEVERITY_MASK)) {
switch(FI_GET_FLAG(fi, PI_SEVERITY_MASK)) {
case(PI_CHAT):
g_object_set (cell, "background-gdk", &expert_color_chat, NULL);
g_object_set (cell, "background-set", TRUE, NULL);
break;
case(PI_NOTE):
g_object_set (cell, "background-gdk", &expert_color_note, NULL);
g_object_set (cell, "background-set", TRUE, NULL);
break;
case(PI_WARN):
g_object_set (cell, "background-gdk", &expert_color_warn, NULL);
g_object_set (cell, "background-set", TRUE, NULL);
break;
case(PI_ERROR):
g_object_set (cell, "background-gdk", &expert_color_error, NULL);
g_object_set (cell, "background-set", TRUE, NULL);
break;
default:
g_assert_not_reached();
}
}
}
#endif

View File

@ -206,4 +206,14 @@ extern gboolean tree_view_select(GtkWidget *widget, GdkEventButton *event);
*/
extern void set_ptree_sel_browse_all(gboolean val);
/** init the expert colors */
extern void proto_draw_colors_init(void);
/** the expert colors */
extern GdkColor expert_color_chat;
extern GdkColor expert_color_note;
extern GdkColor expert_color_warn;
extern GdkColor expert_color_error;
#endif