diff options
-rw-r--r-- | epan/expert.c | 16 | ||||
-rw-r--r-- | epan/expert.h | 18 | ||||
-rw-r--r-- | epan/proto.h | 26 | ||||
-rw-r--r-- | epan/wslua/init_wslua.c | 164 | ||||
-rwxr-xr-x | epan/wslua/make-init-lua.pl | 53 | ||||
-rw-r--r-- | epan/wslua/template-init.lua | 5 | ||||
-rw-r--r-- | epan/wslua/wslua.h | 13 | ||||
-rw-r--r-- | epan/wslua/wslua_proto.c | 190 | ||||
-rw-r--r-- | epan/wslua/wslua_tree.c | 103 | ||||
-rw-r--r-- | test/captures/dns_port.pcap | bin | 1318 -> 1318 bytes | |||
-rw-r--r-- | test/lua/dissector.lua | 36 | ||||
-rw-r--r-- | test/lua/proto.lua | 30 | ||||
-rw-r--r-- | test/lua/verify_dissector.lua | 80 |
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 Binary files differindex c19a79c8c9..6974505abf 100644 --- a/test/captures/dns_port.pcap +++ b/test/captures/dns_port.pcap 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 |