summaryrefslogtreecommitdiff
path: root/epan
diff options
context:
space:
mode:
authorUlf Lamping <ulf.lamping@web.de>2005-09-11 16:55:34 +0000
committerUlf Lamping <ulf.lamping@web.de>2005-09-11 16:55:34 +0000
commit642467ad5ce08b28314cc2cb777b9d66a944d4ba (patch)
treefbc55d80c6f51c2fbac4a9350f4f14859eaf928f /epan
parent266e1a3491de1ff790c326bbffe0d4827af0f24b (diff)
downloadwireshark-642467ad5ce08b28314cc2cb777b9d66a944d4ba.tar.gz
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
Diffstat (limited to 'epan')
-rw-r--r--epan/Makefile.common2
-rw-r--r--epan/dissectors/packet-clnp.c30
-rw-r--r--epan/dissectors/packet-dcerpc.c70
-rw-r--r--epan/dissectors/packet-dcom.c42
-rw-r--r--epan/dissectors/packet-frame.c20
-rw-r--r--epan/dissectors/packet-http.c3
-rw-r--r--epan/dissectors/packet-tcp.c53
-rw-r--r--epan/epan.c3
-rw-r--r--epan/expert.c117
-rw-r--r--epan/expert.h60
-rw-r--r--epan/libethereal.def4
-rw-r--r--epan/proto.c26
-rw-r--r--epan/proto.h61
13 files changed, 446 insertions, 45 deletions
diff --git a/epan/Makefile.common b/epan/Makefile.common
index 150140a00a..339d516345 100644
--- a/epan/Makefile.common
+++ b/epan/Makefile.common
@@ -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 \
diff --git a/epan/dissectors/packet-clnp.c b/epan/dissectors/packet-clnp.c
index b7c734cf32..e7501d5c6c 100644
--- a/epan/dissectors/packet-clnp.c
+++ b/epan/dissectors/packet-clnp.c
@@ -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))
diff --git a/epan/dissectors/packet-dcerpc.c b/epan/dissectors/packet-dcerpc.c
index 9fad9ef11d..57fbbee4bf 100644
--- a/epan/dissectors/packet-dcerpc.c
+++ b/epan/dissectors/packet-dcerpc.c
@@ -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);
diff --git a/epan/dissectors/packet-dcom.c b/epan/dissectors/packet-dcom.c
index b64d1150c4..0a13d041c6 100644
--- a/epan/dissectors/packet-dcom.c
+++ b/epan/dissectors/packet-dcom.c
@@ -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;
diff --git a/epan/dissectors/packet-frame.c b/epan/dissectors/packet-frame.c
index 9b581d8913..b7d35cad25 100644
--- a/epan/dissectors/packet-frame.c
+++ b/epan/dissectors/packet-frame.c
@@ -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)");
}
}
diff --git a/epan/dissectors/packet-http.c b/epan/dissectors/packet-http.c
index 6fb851fa93..741ee5ffa7 100644
--- a/epan/dissectors/packet-http.c
+++ b/epan/dissectors/packet-http.c
@@ -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;
diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c
index 71f7351d26..6c59cb67d8 100644
--- a/epan/dissectors/packet-tcp.c
+++ b/epan/dissectors/packet-tcp.c
@@ -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",
diff --git a/epan/epan.c b/epan/epan.c
index 1a289e396e..895d3faa0d 100644
--- a/epan/epan.c
+++ b/epan/epan.c
@@ -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();
diff --git a/epan/expert.c b/epan/expert.c
new file mode 100644
index 0000000000..dfa585f7e2
--- /dev/null
+++ b/epan/expert.c
@@ -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);
+}
+
+
diff --git a/epan/expert.h b/epan/expert.h
new file mode 100644
index 0000000000..5860121fba
--- /dev/null
+++ b/epan/expert.h
@@ -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__ */
diff --git a/epan/libethereal.def b/epan/libethereal.def
index 91f676e935..019122a86f 100644
--- a/epan/libethereal.def
+++ b/epan/libethereal.def
@@ -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
diff --git a/epan/proto.c b/epan/proto.c
index 5deb8f1b18..a7996f4276 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -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)
{
diff --git a/epan/proto.h b/epan/proto.h
index 950687810f..50618acf98 100644
--- a/epan/proto.h
+++ b/epan/proto.h
@@ -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.