Add filterable expert info for Lua

This adds the ability for a Lua script to register expert info fields,
similar to C-code dissectors. This change also removes the need for
the expert_add_info_format_internal() function. Existing Lua scripts
do not have to change, because the existing expert info function
uses the internal "_ws.lua" protocol instead of nothing; but using
the new functionality provides more benefits since it correctly
registers the expert info fields to the dissector's protocol.

The test suite was amended to generate both old and new forms.

Change-Id: Ib5ae74e927cfa81312baf7b04ff4104b0b4f936e
Reviewed-on: https://code.wireshark.org/review/830
Reviewed-by: Evan Huus <eapache@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Hadriel Kaplan 2014-03-25 18:11:05 -04:00 committed by Anders Broman
parent b981173669
commit da1af6e549
13 changed files with 672 additions and 64 deletions

View File

@ -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)
{

View File

@ -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.

View File

@ -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

View File

@ -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|

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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);
const gchar* str = luaL_optstring(L,WSLUA_OPTARG_TreeItem_add_expert_info_TEXT,"Expert Info");
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;
expert_add_info_format_internal(lua_pinfo, ti->item, group, severity, "%s", 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);
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;
}
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),

Binary file not shown.

View File

@ -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

View File

@ -288,6 +288,24 @@ function dns.init()
end
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
@ -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

View File

@ -11,12 +11,78 @@ local function testing(...)
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