aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/expert.c16
-rw-r--r--epan/expert.h18
-rw-r--r--epan/proto.h26
-rw-r--r--epan/wslua/init_wslua.c164
-rwxr-xr-xepan/wslua/make-init-lua.pl53
-rw-r--r--epan/wslua/template-init.lua5
-rw-r--r--epan/wslua/wslua.h13
-rw-r--r--epan/wslua/wslua_proto.c190
-rw-r--r--epan/wslua/wslua_tree.c103
-rw-r--r--test/captures/dns_port.pcapbin1318 -> 1318 bytes
-rw-r--r--test/lua/dissector.lua36
-rw-r--r--test/lua/proto.lua30
-rw-r--r--test/lua/verify_dissector.lua80
13 files changed, 671 insertions, 63 deletions
diff --git a/epan/expert.c b/epan/expert.c
index a59c5a60b8..46be838ac8 100644
--- a/epan/expert.c
+++ b/epan/expert.c
@@ -318,6 +318,7 @@ expert_set_info_vformat(packet_info *pinfo, proto_item *pi, int group, int sever
highest_severity = severity;
}
+ /* XXX: can we get rid of these checks and make them programming errors instead now? */
if (pi != NULL && PITEM_FINFO(pi) != NULL) {
expert_set_item_flags(pi, group, severity);
}
@@ -371,24 +372,15 @@ expert_set_info_vformat(packet_info *pinfo, proto_item *pi, int group, int sever
/* if we have a proto_item (not a faked item), set expert attributes to it */
if (pi != NULL && PITEM_FINFO(pi) != NULL) {
ei->pitem = pi;
- } else {
+ }
+ /* XXX: remove this because we don't have an internal-only function now? */
+ else {
ei->pitem = NULL;
}
tap_queue_packet(expert_tap, pinfo, ei);
}
-
-void
-expert_add_info_format_internal(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, -1, TRUE, format, ap);
- va_end(ap);
-}
-
void
expert_add_info(packet_info *pinfo, proto_item *pi, expert_field *expindex)
{
diff --git a/epan/expert.h b/epan/expert.h
index f8c00c2487..095b472deb 100644
--- a/epan/expert.h
+++ b/epan/expert.h
@@ -51,7 +51,9 @@ typedef struct expert_field
int hf;
} expert_field;
-#define EI_INIT {-1, -1}
+#define EI_INIT_EI -1
+#define EI_INIT_HF -1
+#define EI_INIT {EI_INIT_EI, EI_INIT_HF}
typedef struct expert_field_info {
/* ---------- set by dissector --------- */
@@ -112,20 +114,6 @@ expert_update_comment_count(guint64 count);
WS_DLL_PUBLIC void
expert_add_info(packet_info *pinfo, proto_item *pi, expert_field* eiindex);
-/** Add an expert info. FOR INTERNAL (NON-DISSECTOR) USE ONLY!!!
- Add an expert info tree to a protocol item, with classification and message.
- @param pinfo Packet info of the currently processed packet. May be NULL if
- pi is supplied
- @param pi Current protocol item (or NULL)
- @param group The expert group (like PI_CHECKSUM - see: proto.h)
- @param severity The expert severity (like PI_WARN - see: proto.h)
- @param format Printf-style format string for additional arguments
- */
-WS_DLL_PUBLIC void
-expert_add_info_format_internal(packet_info *pinfo, proto_item *pi, int group,
- int severity, const char *format, ...)
- G_GNUC_PRINTF(5, 6);
-
/** Add an expert info.
Add an expert info tree to a protocol item, using registered expert info item,
but with a formatted message.
diff --git a/epan/proto.h b/epan/proto.h
index 2ffa19793a..ab0f1b409b 100644
--- a/epan/proto.h
+++ b/epan/proto.h
@@ -533,40 +533,42 @@ typedef proto_node proto_item;
* the bottom up.
*/
+/* do not modify the PI_SEVERITY_MASK name - it's used by make-init-lua.pl */
/* expert severities */
#define PI_SEVERITY_MASK 0x00F00000 /**< mask usually for internal use only! */
-/** Packet is commented */
+/** Packet comment */
#define PI_COMMENT 0x00100000
/** Usual workflow, e.g. TCP connection establishing */
#define PI_CHAT 0x00200000
-/** Notable messages, e.g. an application returned an "usual" error code like HTTP 404 */
+/** Notable messages, e.g. an application returned an "unusual" error code like HTTP 404 */
#define PI_NOTE 0x00400000
/** Warning, e.g. application returned an "unusual" error code */
#define PI_WARN 0x00600000
-/** Serious problems, e.g. [Malformed Packet] */
+/** Serious problems, e.g. a malformed packet */
#define PI_ERROR 0x00800000
+/* do not modify the PI_GROUP_MASK name - it's used by make-init-lua.pl */
/* expert "event groups" */
#define PI_GROUP_MASK 0xFF000000 /**< mask usually for internal use only! */
-/** The protocol field has a bad checksum, usually PI_WARN */
+/** The protocol field has a bad checksum, usually uses PI_WARN severity */
#define PI_CHECKSUM 0x01000000
/** The protocol field indicates a sequence problem (e.g. TCP window is zero) */
#define PI_SEQUENCE 0x02000000
-/** The protocol field indicates a bad application response code (e.g. HTTP 404), usually PI_NOTE */
+/** The protocol field indicates a bad application response code (e.g. HTTP 404), usually PI_NOTE severity */
#define PI_RESPONSE_CODE 0x03000000
-/** The protocol field indicates an application request (e.g. File Handle == xxxx), usually PI_CHAT */
+/** The protocol field indicates an application request (e.g. File Handle == xxxx), usually PI_CHAT severity */
#define PI_REQUEST_CODE 0x04000000
-/** The data is undecoded, the protocol dissection is incomplete here, usually PI_WARN */
+/** The data is undecoded, the protocol dissection is incomplete here, usually PI_WARN severity */
#define PI_UNDECODED 0x05000000
-/** The protocol field indicates a reassemble (e.g. DCE/RPC defragmentation), usually PI_CHAT (or PI_ERROR) */
+/** The protocol field indicates a reassemble (e.g. DCE/RPC defragmentation), usually PI_CHAT severity (or PI_ERROR) */
#define PI_REASSEMBLE 0x06000000
-/** The packet data is malformed, the dissector has "given up", usually PI_ERROR */
+/** The packet data is malformed, the dissector has "given up", usually PI_ERROR severity */
#define PI_MALFORMED 0x07000000
-/** A generic debugging message (shouldn't remain in production code!), usually PI_ERROR */
+/** A generic debugging message (shouldn't remain in production code!), usually PI_ERROR severity */
#define PI_DEBUG 0x08000000
-/** The protocol field violates a protocol specification, usually PI_WARN */
+/** The protocol field violates a protocol specification, usually PI_WARN severity */
#define PI_PROTOCOL 0x09000000
-/** The protocol field indicates a security probem (e.g. unsecure implementation) */
+/** The protocol field indicates a security problem (e.g. insecure implementation) */
#define PI_SECURITY 0x0a000000
/** The protocol field indicates a packet comment */
#define PI_COMMENTS_GROUP 0x0b000000
diff --git a/epan/wslua/init_wslua.c b/epan/wslua/init_wslua.c
index c37602f82f..4ce2780520 100644
--- a/epan/wslua/init_wslua.c
+++ b/epan/wslua/init_wslua.c
@@ -58,6 +58,72 @@ int lua_heur_dissectors_table_ref = LUA_NOREF;
static int proto_lua = -1;
static expert_field ei_lua_error = EI_INIT;
+static expert_field ei_lua_proto_checksum_comment = EI_INIT;
+static expert_field ei_lua_proto_checksum_chat = EI_INIT;
+static expert_field ei_lua_proto_checksum_note = EI_INIT;
+static expert_field ei_lua_proto_checksum_warn = EI_INIT;
+static expert_field ei_lua_proto_checksum_error = EI_INIT;
+
+static expert_field ei_lua_proto_sequence_comment = EI_INIT;
+static expert_field ei_lua_proto_sequence_chat = EI_INIT;
+static expert_field ei_lua_proto_sequence_note = EI_INIT;
+static expert_field ei_lua_proto_sequence_warn = EI_INIT;
+static expert_field ei_lua_proto_sequence_error = EI_INIT;
+
+static expert_field ei_lua_proto_response_comment = EI_INIT;
+static expert_field ei_lua_proto_response_chat = EI_INIT;
+static expert_field ei_lua_proto_response_note = EI_INIT;
+static expert_field ei_lua_proto_response_warn = EI_INIT;
+static expert_field ei_lua_proto_response_error = EI_INIT;
+
+static expert_field ei_lua_proto_request_comment = EI_INIT;
+static expert_field ei_lua_proto_request_chat = EI_INIT;
+static expert_field ei_lua_proto_request_note = EI_INIT;
+static expert_field ei_lua_proto_request_warn = EI_INIT;
+static expert_field ei_lua_proto_request_error = EI_INIT;
+
+static expert_field ei_lua_proto_undecoded_comment = EI_INIT;
+static expert_field ei_lua_proto_undecoded_chat = EI_INIT;
+static expert_field ei_lua_proto_undecoded_note = EI_INIT;
+static expert_field ei_lua_proto_undecoded_warn = EI_INIT;
+static expert_field ei_lua_proto_undecoded_error = EI_INIT;
+
+static expert_field ei_lua_proto_reassemble_comment = EI_INIT;
+static expert_field ei_lua_proto_reassemble_chat = EI_INIT;
+static expert_field ei_lua_proto_reassemble_note = EI_INIT;
+static expert_field ei_lua_proto_reassemble_warn = EI_INIT;
+static expert_field ei_lua_proto_reassemble_error = EI_INIT;
+
+static expert_field ei_lua_proto_malformed_comment = EI_INIT;
+static expert_field ei_lua_proto_malformed_chat = EI_INIT;
+static expert_field ei_lua_proto_malformed_note = EI_INIT;
+static expert_field ei_lua_proto_malformed_warn = EI_INIT;
+static expert_field ei_lua_proto_malformed_error = EI_INIT;
+
+static expert_field ei_lua_proto_debug_comment = EI_INIT;
+static expert_field ei_lua_proto_debug_chat = EI_INIT;
+static expert_field ei_lua_proto_debug_note = EI_INIT;
+static expert_field ei_lua_proto_debug_warn = EI_INIT;
+static expert_field ei_lua_proto_debug_error = EI_INIT;
+
+static expert_field ei_lua_proto_protocol_comment = EI_INIT;
+static expert_field ei_lua_proto_protocol_chat = EI_INIT;
+static expert_field ei_lua_proto_protocol_note = EI_INIT;
+static expert_field ei_lua_proto_protocol_warn = EI_INIT;
+static expert_field ei_lua_proto_protocol_error = EI_INIT;
+
+static expert_field ei_lua_proto_security_comment = EI_INIT;
+static expert_field ei_lua_proto_security_chat = EI_INIT;
+static expert_field ei_lua_proto_security_note = EI_INIT;
+static expert_field ei_lua_proto_security_warn = EI_INIT;
+static expert_field ei_lua_proto_security_error = EI_INIT;
+
+static expert_field ei_lua_proto_comments_comment = EI_INIT;
+static expert_field ei_lua_proto_comments_chat = EI_INIT;
+static expert_field ei_lua_proto_comments_note = EI_INIT;
+static expert_field ei_lua_proto_comments_warn = EI_INIT;
+static expert_field ei_lua_proto_comments_error = EI_INIT;
+
dissector_handle_t lua_data_handle;
static void lua_frame_end(void)
@@ -506,6 +572,25 @@ wslua_plugins_dump_all(void)
wslua_plugins_get_descriptions(print_wslua_plugin_description, NULL);
}
+static ei_register_info* ws_lua_ei = NULL;
+static int ws_lua_ei_len = 0;
+
+expert_field*
+wslua_get_expert_field(const int group, const int severity)
+{
+ int i;
+ const ei_register_info *ei = ws_lua_ei;
+
+ g_assert(ei);
+
+ for (i=0; i < ws_lua_ei_len; i++, ei++) {
+ if (ei->eiinfo.group == group && ei->eiinfo.severity == severity)
+ return ei->ids;
+ }
+
+ return &ei_lua_error;
+}
+
int wslua_init(register_cb cb, gpointer client_data) {
gchar* filename;
const gchar *script_filename;
@@ -515,9 +600,88 @@ int wslua_init(register_cb cb, gpointer client_data) {
int file_count = 1;
static ei_register_info ei[] = {
+ /* the following are created so we can continue to support the TreeItem_add_expert_info()
+ function to Lua scripts. That function doesn't know what registered protocol to use,
+ so it uses the "_ws.lua" one. */
+ /* XXX: it seems to me we should not be offering PI_GROUP_MASK nor PI_SEVERITY_MASK since
+ they are not real settings, so I'm not adding them below (should they also not be exported
+ into Lua? they are right now.) */
+ /* NOTE: do not add expert entries at the top of this array - only at the bottom. This array
+ is not only used by expert.c, but also by wslua_get_expert_field() to find the appropriate
+ "dummy" entry. So this array's ordering matters. */
+ { &ei_lua_proto_checksum_comment, { "_ws.lua.proto.comment", PI_CHECKSUM, PI_COMMENT ,"Protocol Comment", EXPFILL }},
+ { &ei_lua_proto_checksum_chat, { "_ws.lua.proto.chat", PI_CHECKSUM, PI_CHAT ,"Protocol Chat", EXPFILL }},
+ { &ei_lua_proto_checksum_note, { "_ws.lua.proto.note", PI_CHECKSUM, PI_NOTE ,"Protocol Note", EXPFILL }},
+ { &ei_lua_proto_checksum_warn, { "_ws.lua.proto.warning", PI_CHECKSUM, PI_WARN ,"Protocol Warning", EXPFILL }},
+ { &ei_lua_proto_checksum_error, { "_ws.lua.proto.error", PI_CHECKSUM, PI_ERROR ,"Protocol Error", EXPFILL }},
+
+ { &ei_lua_proto_sequence_comment, { "_ws.lua.proto.comment", PI_SEQUENCE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
+ { &ei_lua_proto_sequence_chat, { "_ws.lua.proto.chat", PI_SEQUENCE, PI_CHAT ,"Protocol Chat", EXPFILL }},
+ { &ei_lua_proto_sequence_note, { "_ws.lua.proto.note", PI_SEQUENCE, PI_NOTE ,"Protocol Note", EXPFILL }},
+ { &ei_lua_proto_sequence_warn, { "_ws.lua.proto.warning", PI_SEQUENCE, PI_WARN ,"Protocol Warning", EXPFILL }},
+ { &ei_lua_proto_sequence_error, { "_ws.lua.proto.error", PI_SEQUENCE, PI_ERROR ,"Protocol Error", EXPFILL }},
+
+ { &ei_lua_proto_response_comment, { "_ws.lua.proto.comment", PI_RESPONSE_CODE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
+ { &ei_lua_proto_response_chat, { "_ws.lua.proto.chat", PI_RESPONSE_CODE, PI_CHAT ,"Protocol Chat", EXPFILL }},
+ { &ei_lua_proto_response_note, { "_ws.lua.proto.note", PI_RESPONSE_CODE, PI_NOTE ,"Protocol Note", EXPFILL }},
+ { &ei_lua_proto_response_warn, { "_ws.lua.proto.warning", PI_RESPONSE_CODE, PI_WARN ,"Protocol Warning", EXPFILL }},
+ { &ei_lua_proto_response_error, { "_ws.lua.proto.error", PI_RESPONSE_CODE, PI_ERROR ,"Protocol Error", EXPFILL }},
+
+ { &ei_lua_proto_request_comment, { "_ws.lua.proto.comment", PI_REQUEST_CODE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
+ { &ei_lua_proto_request_chat, { "_ws.lua.proto.chat", PI_REQUEST_CODE, PI_CHAT ,"Protocol Chat", EXPFILL }},
+ { &ei_lua_proto_request_note, { "_ws.lua.proto.note", PI_REQUEST_CODE, PI_NOTE ,"Protocol Note", EXPFILL }},
+ { &ei_lua_proto_request_warn, { "_ws.lua.proto.warning", PI_REQUEST_CODE, PI_WARN ,"Protocol Warning", EXPFILL }},
+ { &ei_lua_proto_request_error, { "_ws.lua.proto.error", PI_REQUEST_CODE, PI_ERROR ,"Protocol Error", EXPFILL }},
+
+ { &ei_lua_proto_undecoded_comment, { "_ws.lua.proto.comment", PI_UNDECODED, PI_COMMENT ,"Protocol Comment", EXPFILL }},
+ { &ei_lua_proto_undecoded_chat, { "_ws.lua.proto.chat", PI_UNDECODED, PI_CHAT ,"Protocol Chat", EXPFILL }},
+ { &ei_lua_proto_undecoded_note, { "_ws.lua.proto.note", PI_UNDECODED, PI_NOTE ,"Protocol Note", EXPFILL }},
+ { &ei_lua_proto_undecoded_warn, { "_ws.lua.proto.warning", PI_UNDECODED, PI_WARN ,"Protocol Warning", EXPFILL }},
+ { &ei_lua_proto_undecoded_error, { "_ws.lua.proto.error", PI_UNDECODED, PI_ERROR ,"Protocol Error", EXPFILL }},
+
+ { &ei_lua_proto_reassemble_comment, { "_ws.lua.proto.comment", PI_REASSEMBLE, PI_COMMENT ,"Protocol Comment", EXPFILL }},
+ { &ei_lua_proto_reassemble_chat, { "_ws.lua.proto.chat", PI_REASSEMBLE, PI_CHAT ,"Protocol Chat", EXPFILL }},
+ { &ei_lua_proto_reassemble_note, { "_ws.lua.proto.note", PI_REASSEMBLE, PI_NOTE ,"Protocol Note", EXPFILL }},
+ { &ei_lua_proto_reassemble_warn, { "_ws.lua.proto.warning", PI_REASSEMBLE, PI_WARN ,"Protocol Warning", EXPFILL }},
+ { &ei_lua_proto_reassemble_error, { "_ws.lua.proto.error", PI_REASSEMBLE, PI_ERROR ,"Protocol Error", EXPFILL }},
+
+ { &ei_lua_proto_malformed_comment, { "_ws.lua.proto.comment", PI_MALFORMED, PI_COMMENT ,"Protocol Comment", EXPFILL }},
+ { &ei_lua_proto_malformed_chat, { "_ws.lua.proto.chat", PI_MALFORMED, PI_CHAT ,"Protocol Chat", EXPFILL }},
+ { &ei_lua_proto_malformed_note, { "_ws.lua.proto.note", PI_MALFORMED, PI_NOTE ,"Protocol Note", EXPFILL }},
+ { &ei_lua_proto_malformed_warn, { "_ws.lua.proto.warning", PI_MALFORMED, PI_WARN ,"Protocol Warning", EXPFILL }},
+ { &ei_lua_proto_malformed_error, { "_ws.lua.proto.error", PI_MALFORMED, PI_ERROR ,"Protocol Error", EXPFILL }},
+
+ { &ei_lua_proto_debug_comment, { "_ws.lua.proto.comment", PI_DEBUG, PI_COMMENT ,"Protocol Comment", EXPFILL }},
+ { &ei_lua_proto_debug_chat, { "_ws.lua.proto.chat", PI_DEBUG, PI_CHAT ,"Protocol Chat", EXPFILL }},
+ { &ei_lua_proto_debug_note, { "_ws.lua.proto.note", PI_DEBUG, PI_NOTE ,"Protocol Note", EXPFILL }},
+ { &ei_lua_proto_debug_warn, { "_ws.lua.proto.warning", PI_DEBUG, PI_WARN ,"Protocol Warning", EXPFILL }},
+ { &ei_lua_proto_debug_error, { "_ws.lua.proto.error", PI_DEBUG, PI_ERROR ,"Protocol Error", EXPFILL }},
+
+ { &ei_lua_proto_protocol_comment, { "_ws.lua.proto.comment", PI_PROTOCOL, PI_COMMENT ,"Protocol Comment", EXPFILL }},
+ { &ei_lua_proto_protocol_chat, { "_ws.lua.proto.chat", PI_PROTOCOL, PI_CHAT ,"Protocol Chat", EXPFILL }},
+ { &ei_lua_proto_protocol_note, { "_ws.lua.proto.note", PI_PROTOCOL, PI_NOTE ,"Protocol Note", EXPFILL }},
+ { &ei_lua_proto_protocol_warn, { "_ws.lua.proto.warning", PI_PROTOCOL, PI_WARN ,"Protocol Warning", EXPFILL }},
+ { &ei_lua_proto_protocol_error, { "_ws.lua.proto.error", PI_PROTOCOL, PI_ERROR ,"Protocol Error", EXPFILL }},
+
+ { &ei_lua_proto_security_comment, { "_ws.lua.proto.comment", PI_SECURITY, PI_COMMENT ,"Protocol Comment", EXPFILL }},
+ { &ei_lua_proto_security_chat, { "_ws.lua.proto.chat", PI_SECURITY, PI_CHAT ,"Protocol Chat", EXPFILL }},
+ { &ei_lua_proto_security_note, { "_ws.lua.proto.note", PI_SECURITY, PI_NOTE ,"Protocol Note", EXPFILL }},
+ { &ei_lua_proto_security_warn, { "_ws.lua.proto.warning", PI_SECURITY, PI_WARN ,"Protocol Warning", EXPFILL }},
+ { &ei_lua_proto_security_error, { "_ws.lua.proto.error", PI_SECURITY, PI_ERROR ,"Protocol Error", EXPFILL }},
+
+ { &ei_lua_proto_comments_comment, { "_ws.lua.proto.comment", PI_COMMENTS_GROUP, PI_COMMENT ,"Protocol Comment", EXPFILL }},
+ { &ei_lua_proto_comments_chat, { "_ws.lua.proto.chat", PI_COMMENTS_GROUP, PI_CHAT ,"Protocol Chat", EXPFILL }},
+ { &ei_lua_proto_comments_note, { "_ws.lua.proto.note", PI_COMMENTS_GROUP, PI_NOTE ,"Protocol Note", EXPFILL }},
+ { &ei_lua_proto_comments_warn, { "_ws.lua.proto.warning", PI_COMMENTS_GROUP, PI_WARN ,"Protocol Warning", EXPFILL }},
+ { &ei_lua_proto_comments_error, { "_ws.lua.proto.error", PI_COMMENTS_GROUP, PI_ERROR ,"Protocol Error", EXPFILL }},
+
+ /* this one is for reporting errors executing Lua code */
{ &ei_lua_error, { "_ws.lua.error", PI_UNDECODED, PI_ERROR ,"Lua Error", EXPFILL }},
};
+ ws_lua_ei = ei;
+ ws_lua_ei_len = array_length(ei);
+
/* set up the logger */
g_log_set_handler(LOG_DOMAIN_LUA, (GLogLevelFlags)(G_LOG_LEVEL_CRITICAL|
G_LOG_LEVEL_WARNING|
diff --git a/epan/wslua/make-init-lua.pl b/epan/wslua/make-init-lua.pl
index 048f8097d2..47ffbf221f 100755
--- a/epan/wslua/make-init-lua.pl
+++ b/epan/wslua/make-init-lua.pl
@@ -40,6 +40,9 @@ my $wtap_presence_flags_table = '';
my $bases_table = '';
my $encodings = '';
my $expert_pi = '';
+my $expert_pi_tbl = '';
+my $expert_pi_severity = '';
+my $expert_pi_group = '';
my $menu_groups = '';
my %replacements = %{{
@@ -51,6 +54,7 @@ my %replacements = %{{
BASES => \$bases_table,
ENCODINGS => \$encodings,
EXPERT => \$expert_pi,
+ EXPERT_TABLE => \$expert_pi_tbl,
MENU_GROUPS => \$menu_groups,
}};
@@ -135,19 +139,53 @@ $ft_types_table =~ s/,\n$/\n}\n/msi;
# #defines for encodings and expert group and severity levels
#
-$bases_table = "-- Display Bases\n base = {\n";
-$encodings = "-- Encodings\n";
-$expert_pi = "-- Expert flags and facilities\n";
+$bases_table = "-- Display Bases\n base = {\n";
+$encodings = "-- Encodings\n";
+$expert_pi = "-- Expert flags and facilities (deprecated - see 'expert' table below)\n";
+$expert_pi_tbl = "-- Expert flags and facilities\nexpert = {\n";
+$expert_pi_severity = "\t-- Expert severity levels\n\tseverity = {\n";
+$expert_pi_group = "\t-- Expert event groups\n\tgroup = {\n";
open PROTO_H, "< $WSROOT/epan/proto.h" or die "cannot open '$WSROOT/epan/proto.h': $!";
+
+my $in_severity = 0;
+my $prev_comment;
+my $skip_this = 0;
+
while(<PROTO_H>) {
+ $skip_this = 0;
+
if (/^\s+BASE_([A-Z_]+)[ ]*=[ ]*([0-9]+),/ ) {
$bases_table .= "\t[\"$1\"] = $2,\n";
}
- if ( /^.define\s+(PI_[A-Z_]+)\s+((0x)?[0-9A-Fa-f]+)/ ) {
- my ($name, $value) = ($1, hex($2));
+ if (/^.define\s+PI_SEVERITY_MASK /) {
+ $in_severity = 1;
+ $skip_this = 1;
+ }
+
+ if (/^.define\s+PI_GROUP_MASK /) {
+ $in_severity = 2;
+ $skip_this = 1;
+ }
+
+ if ($in_severity && /\/\*\* (.*?) \*\//) {
+ $prev_comment = $1;
+ }
+
+ if ( /^.define\s+(PI_([A-Z_]+))\s+((0x)?[0-9A-Fa-f]+)/ ) {
+ my ($name, $abbr, $value) = ($1, $2, hex($3));
+ # I'm keeping this here for backwards-compatibility
$expert_pi .= "$name = $value\n";
+
+ if (!$skip_this && $in_severity == 1) {
+ $expert_pi_severity .= "\t\t-- $prev_comment\n";
+ $expert_pi_severity .= "\t\t\[\"$abbr\"\] = $value,\n";
+ }
+ elsif (!$skip_this && $in_severity == 2) {
+ $expert_pi_group .= "\t\t-- $prev_comment\n";
+ $expert_pi_group .= "\t\t\[\"$abbr\"\] = $value,\n";
+ }
}
if ( /^.define\s+(ENC_[A-Z0-9_]+)\s+((0x)?[0-9A-Fa-f]+)/ ) {
@@ -183,7 +221,10 @@ close STAT_MENU;
$bases_table .= "}\n\n";
$encodings .= "\n\n";
-$expert_pi .= "\n\n";
+$expert_pi .= "\n";
+$expert_pi_severity .= "\t},\n";
+$expert_pi_group .= "\t},\n";
+$expert_pi_tbl .= $expert_pi_group . $expert_pi_severity . "}\n\n";
for my $key (keys %replacements) {
$template =~ s/%$key%/${$replacements{$key}}/msig;
diff --git a/epan/wslua/template-init.lua b/epan/wslua/template-init.lua
index a80dc74023..0a9ad0d00d 100644
--- a/epan/wslua/template-init.lua
+++ b/epan/wslua/template-init.lua
@@ -64,6 +64,7 @@ function typeof(obj)
return mt and mt.__typeof or obj.__typeof or type(obj)
end
+-- the following function is since 1.11.3
function file_exists(name)
local f = io.open(name,"r")
if f ~= nil then io.close(f) return true else return false end
@@ -77,6 +78,7 @@ end
-- %FT_TYPES%
+-- the following table is since 1.11.3
-- %WTAP_PRESENCE_FLAGS%
-- %BASES%
@@ -85,6 +87,9 @@ end
-- %EXPERT%
+-- the following table is since 1.11.3
+-- %EXPERT_TABLE%
+
-- %MENU_GROUPS%
-- other useful constants
diff --git a/epan/wslua/wslua.h b/epan/wslua/wslua.h
index 0f627ef7f4..d8a2606239 100644
--- a/epan/wslua/wslua.h
+++ b/epan/wslua/wslua.h
@@ -56,6 +56,7 @@
#include <epan/funnel.h>
#include <epan/tvbparse.h>
#include <epan/epan.h>
+#include <epan/expert.h>
#include "declare_wslua.h"
@@ -126,6 +127,14 @@ typedef struct _wslua_field_t {
guint32 mask;
} wslua_field_t;
+typedef struct _wslua_expert_field_t {
+ expert_field ids;
+ const gchar *abbr;
+ const gchar *text;
+ int group;
+ int severity;
+} wslua_expert_field_t;
+
/**
* PREF_OBSOLETE is used for preferences that a module used to support
* but no longer supports; we give different error messages for them.
@@ -175,6 +184,8 @@ typedef struct _wslua_proto_t {
int ett;
wslua_pref_t prefs;
int fields;
+ int expert_info_table_ref;
+ expert_module_t *expert_module;
module_t *prefs_module;
dissector_handle_t handle;
gboolean is_postdissector;
@@ -297,6 +308,7 @@ typedef struct {const gchar* str; enum ftenum id; } wslua_ft_types_t;
typedef wslua_pref_t* Pref;
typedef wslua_pref_t* Prefs;
typedef struct _wslua_field_t* ProtoField;
+typedef struct _wslua_expert_field_t* ProtoExpert;
typedef struct _wslua_proto_t* Proto;
typedef struct _wslua_distbl_t* DissectorTable;
typedef dissector_handle_t Dissector;
@@ -662,6 +674,7 @@ extern gboolean wslua_get_field(lua_State *L, int idx, const gchar *name);
extern void wslua_assert_table_field_new(lua_State *L, int idx, const gchar *name);
extern int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data);
extern int heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data);
+extern expert_field* wslua_get_expert_field(const int group, const int severity);
extern void wslua_prefs_changed(void);
extern void proto_register_lua(void);
extern GString* lua_register_all_taps(void);
diff --git a/epan/wslua/wslua_proto.c b/epan/wslua/wslua_proto.c
index 6d08055df9..5ef77cddf2 100644
--- a/epan/wslua/wslua_proto.c
+++ b/epan/wslua/wslua_proto.c
@@ -893,7 +893,7 @@ WSLUA_CONSTRUCTOR ProtoField_new(lua_State* L) {
pushProtoField(L,f);
- WSLUA_RETURN(1); /* The newly created ProtoField object. */
+ WSLUA_RETURN(1); /* The newly created `ProtoField` object. */
}
static int ProtoField_integer(lua_State* L, enum ftenum type) {
@@ -1319,7 +1319,7 @@ WSLUA_METAMETHOD ProtoField__tostring(lua_State* L) {
}
static int ProtoField__gc(lua_State* L) {
- ProtoField f = checkProtoField(L,1);
+ ProtoField f = toProtoField(L,1);
/*
* A garbage collector for ProtoFields makes little sense.
@@ -1385,6 +1385,102 @@ int ProtoField_register(lua_State* L) {
return 0;
}
+WSLUA_CLASS_DEFINE(ProtoExpert,FAIL_ON_NULL("null ProtoExpert"),NOP);
+ /* A Protocol expert info field, to be used when adding items to the dissection tree.
+
+ @since 1.11.3
+ */
+
+WSLUA_CONSTRUCTOR ProtoExpert_new(lua_State* L) {
+ /* Creates a new `ProtoExpert` object to be used for a protocol's expert information notices.
+
+ @since 1.11.3
+ */
+#define WSLUA_ARG_ProtoExpert_new_ABBR 1 /* Filter name of the expert info field (the string that
+ is used in filters). */
+#define WSLUA_ARG_ProtoExpert_new_TEXT 2 /* The default text of the expert field. */
+#define WSLUA_ARG_ProtoExpert_new_GROUP 3 /* Expert group type: one of: `expert.group.CHECKSUM`,
+ `expert.group.SEQUENCE`, `expert.group.RESPONSE_CODE`,
+ `expert.group.REQUEST_CODE`, `expert.group.UNDECODED`,
+ `expert.group.REASSEMBLE`, `expert.group.MALFORMED`,
+ `expert.group.DEBUG`, `expert.group.PROTOCOL`,
+ `expert.group.SECURITY`, or `expert.group.COMMENTS_GROUP`. */
+#define WSLUA_ARG_ProtoExpert_new_SEVERITY 4 /* Expert severity type: one of:
+ `expert.severity.COMMENT`, `expert.severity.CHAT`,
+ `expert.severity.NOTE`, `expert.severity.WARN`,
+ or `expert.severity.ERROR`. */
+
+ ProtoExpert pe = NULL;
+ const gchar* abbr = wslua_checkstring_only(L,WSLUA_ARG_ProtoExpert_new_ABBR);
+ const gchar* text = wslua_checkstring_only(L,WSLUA_ARG_ProtoExpert_new_TEXT);
+ int group = luaL_checkint (L, WSLUA_ARG_ProtoExpert_new_GROUP);
+ int severity = luaL_checkint (L, WSLUA_ARG_ProtoExpert_new_SEVERITY);
+
+ pe = g_new(wslua_expert_field_t,1);
+
+ pe->ids.ei = EI_INIT_EI;
+ pe->ids.hf = EI_INIT_HF;
+ pe->abbr = g_strdup(abbr);
+ pe->text = g_strdup(text);
+ pe->group = group;
+ pe->severity = severity;
+
+ pushProtoExpert(L,pe);
+
+ WSLUA_RETURN(1); /* The newly created `ProtoExpert` object. */
+}
+
+WSLUA_METAMETHOD ProtoExpert__tostring(lua_State* L) {
+ /* Returns a string with debugging information about a `ProtoExpert` object.
+
+ @since 1.11.3
+ */
+ ProtoExpert pe = toProtoExpert(L,1);
+
+ if (!pe) {
+ lua_pushstring(L,"ProtoExpert pointer is NULL!");
+ } else {
+ lua_pushfstring(L, "ProtoExpert: ei=%d, hf=%d, abbr=%s, text=%s, group=%d, severity=%d",
+ pe->ids.ei, pe->ids.hf, pe->abbr, pe->text, pe->group, pe->severity);
+ }
+ return 1;
+}
+
+static int ProtoExpert__gc(lua_State* L) {
+ ProtoExpert pe = toProtoExpert(L,1);
+
+ /*
+ * A garbage collector for ProtoExpert makes little sense.
+ * Even if this cannot be used anymore because it has gone out of scope,
+ * we can destroy the ProtoExpert only if it is not part of a registered Proto,
+ * if it actually belongs to one we need to preserve it as it is pointed by
+ * a expert code causing a crash or memory corruption.
+ */
+
+ if (pe) {
+ luaL_argerror(L,1,"BUG: ProtoExpert_gc called for something not ProtoExpert");
+ /* g_assert() ?? */
+ }
+
+ return 0;
+}
+
+WSLUA_METHODS ProtoExpert_methods[] = {
+ WSLUA_CLASS_FNREG(ProtoExpert,new),
+ { NULL, NULL }
+};
+
+WSLUA_META ProtoExpert_meta[] = {
+ WSLUA_CLASS_MTREG(ProtoExpert,tostring),
+ { NULL, NULL }
+};
+
+int ProtoExpert_register(lua_State* L) {
+ WSLUA_REGISTER_CLASS(ProtoExpert);
+ return 0;
+}
+
+
WSLUA_CLASS_DEFINE(Proto,FAIL_ON_NULL("Proto"),NOP);
/*
A new protocol in Wireshark. Protocols have more uses, the main one is to dissect
@@ -1428,6 +1524,10 @@ WSLUA_CONSTRUCTOR Proto_new(lua_State* L) {
lua_newtable (L);
proto->fields = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_newtable (L);
+ proto->expert_info_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+ proto->expert_module = expert_register_protocol(proto->hfid);
+
proto->prefs.name = NULL;
proto->prefs.label = NULL;
proto->prefs.desc = NULL;
@@ -1712,6 +1812,46 @@ static int Proto_set_fields(lua_State* L) {
return 1;
}
+/* WSLUA_ATTRIBUTE Proto_experts RW The expert info Lua table of this `Proto`.
+
+ @since 1.11.3
+ */
+static int Proto_get_experts(lua_State* L) {
+ Proto proto = checkProto(L,1);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, proto->expert_info_table_ref);
+ return 1;
+}
+
+static int Proto_set_experts(lua_State* L) {
+ Proto proto = checkProto(L,1);
+#define EI_TABLE 2
+#define NEW_TABLE 3
+#define NEW_FIELD 3
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, proto->expert_info_table_ref);
+ lua_insert(L,EI_TABLE);
+
+ if( lua_istable(L,NEW_TABLE)) {
+ for (lua_pushnil(L); lua_next(L, NEW_TABLE); ) {
+ if (isProtoExpert(L,5)) {
+ luaL_ref(L,EI_TABLE);
+ } else if (! lua_isnil(L,5) ) {
+ return luaL_error(L,"only ProtoExperts should be in the table");
+ }
+ }
+ } else if (isProtoExpert(L,NEW_FIELD)){
+ lua_pushvalue(L, NEW_FIELD);
+ luaL_ref(L,EI_TABLE);
+
+ } else {
+ return luaL_error(L,"either a ProtoExpert or an array of ProtoExperts");
+ }
+
+ lua_pushvalue(L, 3);
+
+ return 1;
+}
+
/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
static int Proto__gc(lua_State* L _U_) {
/* do NOT free Proto, it's never free'd */
@@ -1725,6 +1865,7 @@ static int Proto__gc(lua_State* L _U_) {
WSLUA_ATTRIBUTES Proto_attributes[] = {
WSLUA_ATTRIBUTE_RWREG(Proto,dissector),
WSLUA_ATTRIBUTE_RWREG(Proto,fields),
+ WSLUA_ATTRIBUTE_RWREG(Proto,experts),
WSLUA_ATTRIBUTE_ROREG(Proto,prefs),
WSLUA_ATTRIBUTE_WOREG(Proto,prefs_changed),
WSLUA_ATTRIBUTE_WOREG(Proto,init),
@@ -1787,17 +1928,28 @@ int wslua_is_field_available(lua_State* L, const char* field_abbr) {
int Proto_commit(lua_State* L) {
lua_settop(L,0);
+ /* the following gets the table of registered Proto protocols and puts it on the stack (index=1) */
lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref);
+ /* for each registered Proto protocol do... */
for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 2)) {
- GArray* hfa = g_array_new(TRUE,TRUE,sizeof(hf_register_info));
+ /* lua_next() pop'ed the nil, pushed a table entry key at index=2, with value at index=3.
+ In our case, the key is the Proto's name, and the value is the Proto object.
+ At next iteration, the value (Proto object) and ProtoExperts table will be pop'ed due
+ to lua_pop(L, 2), and when lua_next() returns 0 (no more table entries), it will have
+ pop'ed the final key itself, leaving just the protocols_table_ref table on the stack.
+ */
+ GArray* hfa = g_array_new(TRUE,TRUE,sizeof(hf_register_info));
GArray* etta = g_array_new(TRUE,TRUE,sizeof(gint*));
+ GArray* eia = g_array_new(TRUE,TRUE,sizeof(ei_register_info));
Proto proto;
/* const gchar* proto_name = lua_tostring(L,2); */
proto = checkProto(L,3);
+ /* get the Lua table of ProtoFields, push it on the stack (index=3) */
lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields);
+ /* for each ProtoField in the Lua table do... */
for (lua_pushnil(L); lua_next(L, 4); lua_pop(L, 1)) {
ProtoField f = checkProtoField(L,6);
hf_register_info hfri = { NULL, { NULL, NULL, FT_NONE, 0, NULL, 0, NULL, HFILL } };
@@ -1821,11 +1973,43 @@ int Proto_commit(lua_State* L) {
g_array_append_val(etta,ettp);
}
+ /* register the proto fields */
proto_register_field_array(proto->hfid,(hf_register_info*)(void*)hfa->data,hfa->len);
proto_register_subtree_array((gint**)(void*)etta->data,etta->len);
+ lua_pop(L,1); /* pop the table of ProtoFields */
+
+ /* now do the same thing for expert fields */
+
+ /* get the Lua table of ProtoExperts, push it on the stack (index=2) */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, proto->expert_info_table_ref);
+
+ /* for each ProtoExpert in the Lua table do... */
+ for (lua_pushnil(L); lua_next(L, 4); lua_pop(L, 1)) {
+ ProtoExpert e = checkProtoExpert(L,6);
+ ei_register_info eiri = { NULL, { NULL, 0, 0, NULL, EXPFILL } };
+
+ eiri.ids = &(e->ids);
+ eiri.eiinfo.name = e->abbr;
+ eiri.eiinfo.group = e->group;
+ eiri.eiinfo.severity = e->severity;
+ eiri.eiinfo.summary = e->text;
+
+ if (e->ids.ei != EI_INIT_EI || e->ids.hf != EI_INIT_HF) {
+ return luaL_error(L,"expert fields can be registered only once");
+ }
+
+ g_array_append_val(eia,eiri);
+ }
+
+ expert_register_field_array(proto->expert_module, (ei_register_info*)(void*)eia->data, eia->len);
+
+ /* XXX: the registration routines say to use static arrays only, so is this safe? */
g_array_free(hfa,FALSE);
g_array_free(etta,FALSE);
+ g_array_free(eia,FALSE);
+
+ /* Proto object and ProtoFields table will be pop'ed by lua_pop(L, 2) in for statement */
}
lua_pop(L,1); /* pop the protocols_table_ref */
diff --git a/epan/wslua/wslua_tree.c b/epan/wslua/wslua_tree.c
index f73efa5879..f0c56106b0 100644
--- a/epan/wslua/wslua_tree.c
+++ b/epan/wslua/wslua_tree.c
@@ -32,7 +32,6 @@
/* WSLUA_MODULE Tree Adding information to the dissection tree */
#include "wslua.h"
-#include <epan/expert.h>
static gint wslua_ett = -1;
@@ -338,7 +337,15 @@ WSLUA_METHOD TreeItem_prepend_text(lua_State *L) {
}
WSLUA_METHOD TreeItem_add_expert_info(lua_State *L) {
- /* Sets the expert flags of the item and adds expert info to the packet. */
+ /* Sets the expert flags of the item and adds expert info to the packet.
+
+ This function does *not* create a truly filterable expert info for a protocol.
+ Instead you should use `TreeItem.add_proto_expert_info()`.
+
+ Note: This function is provided for backwards compatibility only, and should not
+ be used in new Lua code. It may be removed in the future. You should only
+ use `TreeItem.add_proto_expert_info()`.
+ */
#define WSLUA_OPTARG_TreeItem_add_expert_info_GROUP 2 /* One of `PI_CHECKSUM`, `PI_SEQUENCE`,
`PI_RESPONSE_CODE`, `PI_REQUEST_CODE`,
`PI_UNDECODED`, `PI_REASSEMBLE`,
@@ -346,12 +353,94 @@ WSLUA_METHOD TreeItem_add_expert_info(lua_State *L) {
#define WSLUA_OPTARG_TreeItem_add_expert_info_SEVERITY 3 /* One of `PI_CHAT`, `PI_NOTE`,
`PI_WARN`, or `PI_ERROR`. */
#define WSLUA_OPTARG_TreeItem_add_expert_info_TEXT 4 /* The text for the expert info display. */
+ TreeItem ti = checkTreeItem(L,1);
+ int group = luaL_optint(L,WSLUA_OPTARG_TreeItem_add_expert_info_GROUP,PI_DEBUG);
+ int severity = luaL_optint(L,WSLUA_OPTARG_TreeItem_add_expert_info_SEVERITY,PI_CHAT);
+ expert_field* ei_info = wslua_get_expert_field(group, severity);
+ const gchar* str;
+
+ if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_add_expert_info_TEXT) {
+ str = wslua_checkstring_only(L, WSLUA_OPTARG_TreeItem_add_expert_info_TEXT);
+ expert_add_info_format(lua_pinfo, ti->item, ei_info, "%s", str);
+ } else {
+ expert_add_info(lua_pinfo, ti->item, ei_info);
+ }
+
+ return 0;
+}
+
+WSLUA_METHOD TreeItem_add_proto_expert_info(lua_State *L) {
+ /* Sets the expert flags of the tree item and adds expert info to the packet.
+
+ @since 1.11.3
+ */
+#define WSLUA_ARG_TreeItem_add_proto_expert_info_EXPERT 2 /* The `ProtoExpert` object to add to the tree. */
+#define WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT 3 /* Text for the expert info display
+ (default is to use the registered
+ text). */
TreeItem ti = checkTreeItem(L,1);
- int group = luaL_optint(L,WSLUA_OPTARG_TreeItem_add_expert_info_GROUP,PI_DEBUG);
- int severity = luaL_optint(L,WSLUA_OPTARG_TreeItem_add_expert_info_SEVERITY,PI_CHAT);
- const gchar* str = luaL_optstring(L,WSLUA_OPTARG_TreeItem_add_expert_info_TEXT,"Expert Info");
+ ProtoExpert expert = checkProtoExpert(L,WSLUA_ARG_TreeItem_add_proto_expert_info_EXPERT);
+ const gchar* str;
+
+ if (expert->ids.ei == EI_INIT_EI || expert->ids.hf == EI_INIT_HF) {
+ luaL_error(L, "ProtoExpert is not registered");
+ return 0;
+ }
+
+ if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT) {
+ str = wslua_checkstring_only(L, WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT);
+ expert_add_info_format(lua_pinfo, ti->item, &expert->ids, "%s", str);
+ } else {
+ expert_add_info(lua_pinfo, ti->item, &expert->ids);
+ }
+
+ return 0;
+}
- expert_add_info_format_internal(lua_pinfo, ti->item, group, severity, "%s", str);
+WSLUA_METHOD TreeItem_add_tvb_expert_info(lua_State *L) {
+ /* Sets the expert flags of the tree item and adds expert info to the packet
+ associated with the `Tvb` or `TvbRange` bytes in the packet.
+
+ @since 1.11.3
+ */
+#define WSLUA_ARG_TreeItem_add_tvb_expert_info_EXPERT 2 /* The `ProtoExpert` object to add to the tree. */
+#define WSLUA_ARG_TreeItem_add_tvb_expert_info_TVB 3 /* The `Tvb` or `TvbRange` object bytes to associate
+ the expert info with. */
+#define WSLUA_OPTARG_TreeItem_add_tvb_expert_info_TEXT 4 /* Text for the expert info display
+ (default is to use the registered
+ text). */
+ TreeItem ti = checkTreeItem(L,1);
+ ProtoExpert expert = checkProtoExpert(L,WSLUA_ARG_TreeItem_add_proto_expert_info_EXPERT);
+ TvbRange tvbr;
+ const gchar* str;
+
+ if (expert->ids.ei == EI_INIT_EI || expert->ids.hf == EI_INIT_HF) {
+ luaL_error(L, "ProtoExpert is not registered");
+ return 0;
+ }
+
+ tvbr = shiftTvbRange(L,WSLUA_ARG_TreeItem_add_tvb_expert_info_TVB);
+
+ if (!tvbr) {
+ tvbr = ep_new(struct _wslua_tvbrange);
+ tvbr->tvb = shiftTvb(L,WSLUA_ARG_TreeItem_add_tvb_expert_info_TVB);
+ if (!tvbr->tvb) {
+ tvbr->tvb = ep_new(struct _wslua_tvb);
+ }
+ tvbr->tvb->ws_tvb = lua_tvb;
+ tvbr->offset = 0;
+ tvbr->len = 0;
+ }
+
+ if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT) {
+ str = wslua_checkstring_only(L, WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT);
+ proto_tree_add_expert_format(ti->tree, lua_pinfo, &expert->ids,
+ tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len,
+ "%s", str);
+ } else {
+ proto_tree_add_expert(ti->tree, lua_pinfo, &expert->ids,
+ tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len);
+ }
return 0;
}
@@ -405,6 +494,8 @@ WSLUA_METHODS TreeItem_methods[] = {
WSLUA_CLASS_FNREG(TreeItem,append_text),
WSLUA_CLASS_FNREG(TreeItem,prepend_text),
WSLUA_CLASS_FNREG(TreeItem,add_expert_info),
+ WSLUA_CLASS_FNREG(TreeItem,add_proto_expert_info),
+ WSLUA_CLASS_FNREG(TreeItem,add_tvb_expert_info),
WSLUA_CLASS_FNREG(TreeItem,set_generated),
WSLUA_CLASS_FNREG(TreeItem,set_hidden),
WSLUA_CLASS_FNREG(TreeItem,set_len),
diff --git a/test/captures/dns_port.pcap b/test/captures/dns_port.pcap
index c19a79c8c9..6974505abf 100644
--- a/test/captures/dns_port.pcap
+++ b/test/captures/dns_port.pcap
Binary files differ
diff --git a/test/lua/dissector.lua b/test/lua/dissector.lua
index 3fb835f289..2a68b9c5fe 100644
--- a/test/lua/dissector.lua
+++ b/test/lua/dissector.lua
@@ -132,6 +132,22 @@ dns.fields = { pf_trasaction_id, pf_flags,
pf_flag_z, pf_flag_authenticated, pf_flag_checking_disabled, pf_flag_rcode,
pf_query, pf_query_name, pf_query_name_len, pf_query_label_count, pf_query_type, pf_query_class }
+----------------------------------------
+-- create some expert info fields
+local ef_query = ProtoExpert.new("mydns.query.expert", "DNS query message",
+ expert.group.REQUEST_CODE, expert.severity.CHAT)
+local ef_response = ProtoExpert.new("mydns.response.expert", "DNS response message",
+ expert.group.RESPONSE_CODE, expert.severity.CHAT)
+local ef_ultimate = ProtoExpert.new("mydns.response.ultimate.expert", "DNS answer to life, the universe, and everything",
+ expert.group.COMMENTS_GROUP, expert.severity.NOTE)
+-- some error expert info's
+local ef_too_short = ProtoExpert.new("mydns.too_short.expert", "DNS message too short",
+ expert.group.MALFORMED, expert.severity.ERROR)
+local ef_bad_query = ProtoExpert.new("mydns.query.missing.expert", "DNS query missing or malformed",
+ expert.group.MALFORMED, expert.severity.WARN)
+
+-- register them
+dns.experts = { ef_query, ef_too_short, ef_bad_query, ef_response, ef_ultimate }
----------------------------------------
-- we don't just want to display our protocol's fields, we want to access the value of some of them too!
@@ -214,7 +230,9 @@ function dns.dissector(tvbuf,pktinfo,root)
if pktlen < DNS_HDR_LEN then
-- since we're going to add this protocol to a specific UDP port, we're going to
-- assume packets in this port are our protocol, so the packet being too short is an error
- tree:add_expert_info(PI_MALFORMED, PI_ERROR, "packet too short")
+ -- the old way: tree:add_expert_info(PI_MALFORMED, PI_ERROR, "packet too short")
+ -- the correct way now:
+ tree:add_proto_expert_info(ef_too_short)
dprint("packet length",pktlen,"too short")
return
end
@@ -238,8 +256,19 @@ function dns.dissector(tvbuf,pktinfo,root)
-- for our flags field, we want a sub-tree
local flag_tree = tree:add(pf_flags, flagrange)
-- I'm indenting this for clarity, because it's adding to the flag's child-tree
+
-- let's add the type of message (query vs. response)
- flag_tree:add(pf_flag_response, flagrange)
+ local query_flag_tree = flag_tree:add(pf_flag_response, flagrange)
+
+ -- let's also add an expert info about it
+ if isResponse() then
+ query_flag_tree:add_proto_expert_info(ef_response, "It's a response!")
+ if transid == 42 then
+ tree:add_tvb_expert_info(ef_ultimate, tvbuf:range(0,2))
+ end
+ else
+ query_flag_tree:add_proto_expert_info(ef_query)
+ end
-- we now know if it's a response or query, so let's put that in the
-- GUI packet row, in the INFO column cell
@@ -289,7 +318,8 @@ function dns.dissector(tvbuf,pktinfo,root)
while num_queries > 0 and pktlen_remaining > 0 do
if pktlen_remaining < MIN_QUERY_LEN then
- queries_tree:add_expert_info(PI_MALFORMED, PI_ERROR, "query field missing or too short")
+ -- old way: queries_tree:add_expert_info(PI_MALFORMED, PI_ERROR, "query field missing or too short")
+ queries_tree:add_proto_expert_info(ef_bad_query)
return
end
diff --git a/test/lua/proto.lua b/test/lua/proto.lua
index 9b159e65a3..157c4b2a9c 100644
--- a/test/lua/proto.lua
+++ b/test/lua/proto.lua
@@ -289,6 +289,24 @@ function dns.init()
end
----------------------------------------
+-- create some expert info fields
+local ef_query = ProtoExpert.new("mydns.query.expert", "DNS query message",
+ expert.group.REQUEST_CODE, expert.severity.CHAT)
+local ef_response = ProtoExpert.new("mydns.response.expert", "DNS response message",
+ expert.group.RESPONSE_CODE, expert.severity.CHAT)
+local ef_ultimate = ProtoExpert.new("mydns.response.ultimate.expert", "DNS answer to life, the universe, and everything",
+ expert.group.COMMENTS_GROUP, expert.severity.NOTE)
+-- some error expert info's
+local ef_too_short = ProtoExpert.new("mydns.too_short.expert", "DNS message too short",
+ expert.group.MALFORMED, expert.severity.ERROR)
+local ef_bad_query = ProtoExpert.new("mydns.query.missing.expert", "DNS query missing or malformed",
+ expert.group.MALFORMED, expert.severity.WARN)
+
+-- register them
+dns.experts = { ef_query, ef_too_short, ef_bad_query, ef_response, ef_ultimate }
+
+
+----------------------------------------
-- we don't just want to display our protocol's fields, we want to access the value of some of them too!
-- There are several ways to do that. One is to just parse the buffer contents in Lua code to find
-- the values. But since ProtoFields actually do the parsing for us, and can be retrieved using Field
@@ -391,7 +409,17 @@ function dns.dissector(tvbuf,pktinfo,root)
local flag_tree = tree:add(pf_flags, flagrange)
-- I'm indenting this for calarity, because it's adding to the flag's child-tree
-- let's add the type of message (query vs. response)
- flag_tree:add(pf_flag_response, flagrange)
+ local query_flag_tree = flag_tree:add(pf_flag_response, flagrange)
+
+ -- let's also add an expert info about it
+ if isResponse() then
+ query_flag_tree:add_proto_expert_info(ef_response, "It's a response!")
+ if transid == 42 then
+ tree:add_tvb_expert_info(ef_ultimate, tvbuf:range(0,2))
+ end
+ else
+ query_flag_tree:add_proto_expert_info(ef_query)
+ end
-- we now know if it's a response or query, so let's put that in the
-- GUI packet row, in the INFO column cell
diff --git a/test/lua/verify_dissector.lua b/test/lua/verify_dissector.lua
index f65d1ece72..46ec704e40 100644
--- a/test/lua/verify_dissector.lua
+++ b/test/lua/verify_dissector.lua
@@ -13,10 +13,76 @@ end
local lines = {
{
"MyDNS Protocol",
+ "Transaction ID: 42",
+ "Flags: 0x0100",
+ "0... .... .... .... = Response: this is a query",
+ "[Expert Info (Chat/Request): DNS query message]",
+ "[DNS query message]",
+ "[Severity level: Chat]",
+ "[Group: Request]",
+ ".000 0... .... .... = Opcode: 0",
+ ".... ..0. .... .... = Truncated: False",
+ ".... ...1 .... .... = Recursion desired: yes",
+ ".... .... .0.. .... = World War Z - Reserved for future use: 0x0000",
+ ".... .... ...0 .... = Checking disabled: False",
+ "Number of Questions: 1",
+ "Number of Answer RRs: 0",
+ "Number of Authority RRs: 0",
+ "Number of Additional RRs: 0",
+ "Queries",
+ "us.pool.ntp.org: type A (IPv4 host address) (1), class IN (Internet) (1)",
+ "Name: us.pool.ntp.org",
+ "[Name Length: 17]",
+ "[Label Count: 4]",
+ "Type: A (IPv4 host address) (1)",
+ "Class: IN (Internet) (1)",
+ },
+
+ {
+ "MyDNS Protocol",
+ "Transaction ID: 42",
+ "Flags: 0x8180",
+ "1... .... .... .... = Response: this is a response",
+ "[Expert Info (Chat/Response): It's a response!]",
+ "[It's a response!]",
+ "[Severity level: Chat]",
+ "[Group: Response]",
+ ".000 0... .... .... = Opcode: 0",
+ ".... .0.. .... .... = Authoritative: False",
+ ".... ..0. .... .... = Truncated: False",
+ ".... .... 1... .... = Recursion available: True",
+ ".... .... .0.. .... = World War Z - Reserved for future use: 0x0000",
+ ".... .... ..0. .... = Authenticated: no",
+ ".... .... .... 0000 = Response code: No Error (0)",
+ ".... .... ...0 .... = Checking disabled: False",
+ "DNS answer to life, the universe, and everything",
+ "[Expert Info (Note/Comment): DNS answer to life, the universe, and everything]",
+ "[DNS answer to life, the universe, and everything]",
+ "[Severity level: Note]",
+ "[Group: Comment]",
+ "Number of Questions: 1",
+ "Number of Answer RRs: 15",
+ "Number of Authority RRs: 6",
+ "Number of Additional RRs: 2",
+ "Queries",
+ "us.pool.ntp.org: type A (IPv4 host address) (1), class IN (Internet) (1)",
+ "Name: us.pool.ntp.org",
+ "[Name Length: 17]",
+ "[Label Count: 4]",
+ "Type: A (IPv4 host address) (1)",
+ "Class: IN (Internet) (1)",
+ },
+
+ {
+ "MyDNS Protocol",
"Transaction ID: 43",
"Flags: 0x0100",
"0... .... .... .... = Response: this is a query",
- ".000 0... .... .... = Opcode: 0",
+ "[Expert Info (Chat/Request): DNS query message]",
+ "[DNS query message]",
+ "[Severity level: Chat]",
+ "[Group: Request]",
+ ".000 0... .... .... = Opcode: 0",
".... ..0. .... .... = Truncated: False",
".... ...1 .... .... = Recursion desired: yes",
".... .... .0.. .... = World War Z - Reserved for future use: 0x0000",
@@ -39,7 +105,11 @@ local lines = {
"Transaction ID: 43",
"Flags: 0x8180",
"1... .... .... .... = Response: this is a response",
- ".000 0... .... .... = Opcode: 0",
+ "[Expert Info (Chat/Response): It's a response!]",
+ "[It's a response!]",
+ "[Severity level: Chat]",
+ "[Group: Response]",
+ ".000 0... .... .... = Opcode: 0",
".... .0.. .... .... = Authoritative: False",
".... ..0. .... .... = Truncated: False",
".... .... 1... .... = Recursion available: True",
@@ -58,13 +128,13 @@ local lines = {
"[Label Count: 4]",
"Type: A (IPv4 host address) (1)",
"Class: IN (Internet) (1)",
- }
+ },
}
-- we're going to see those two sets of output twice: both by the normal
-- dissector, then the first one by the heuristic, then the second one by
-- a conversation match
-local numtests = 1 + (2 * (#lines[1] + #lines[2]))
+local numtests = 1 + #lines[1] + #lines[2] + #lines[3] + #lines[4]
print("going to run "..numtests.." tests")
-- for an example of what we're reading through to verify, look at end of this file
@@ -83,7 +153,7 @@ while line do
pktidx = line:match("^Frame (%d+):")
testing("Frame "..pktidx)
pktidx = tonumber(pktidx)
- if pktidx > 2 then pktidx = pktidx - 2 end
+ if pktidx > 4 then pktidx = pktidx - 4 end
line = file:read()
elseif line:find("%[Heuristic dissector used%]") then
-- start again, because it now repeats