aboutsummaryrefslogtreecommitdiffstats
path: root/epan/wslua
diff options
context:
space:
mode:
authorHadriel Kaplan <hadrielk@yahoo.com>2014-04-12 00:32:20 -0400
committerAnders Broman <a.broman58@gmail.com>2014-04-14 11:47:39 +0000
commitdd002649c32a0f16720236b34fe5a7aefe04c457 (patch)
treed03bdc6f0f5ac36bb2d43a68f0cc8bcb72c27c3a /epan/wslua
parent92b501303bdeb163cec55825da8b683138517e4d (diff)
Add tvb_get and proto_tree_add for string-encoded timestamps
This commit adds tvb_get_string_time and proto_tree_add_time_item routines for getting nstime fields from the tvb when they are encoded in ASCII string form. The proto_tree_add_time_item routine is also usable for normal big/little-endian encoded time_t, and has the advantage of retrieving the value even if there's no proto tree. It also exposes the routines to Lua, both so that a Lua script can take advantage of this, but also so I can write a testsuite to test the functions. Change-Id: I955da10f68f2680e3da3a5be5ad8fdce7ed6808c Reviewed-on: https://code.wireshark.org/review/1084 Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/wslua')
-rw-r--r--epan/wslua/wslua_tree.c135
-rw-r--r--epan/wslua/wslua_tvb.c48
2 files changed, 164 insertions, 19 deletions
diff --git a/epan/wslua/wslua_tree.c b/epan/wslua/wslua_tree.c
index 5eee9e561e..356054f518 100644
--- a/epan/wslua/wslua_tree.c
+++ b/epan/wslua/wslua_tree.c
@@ -32,6 +32,8 @@
/* WSLUA_MODULE Tree Adding information to the dissection tree */
#include "wslua.h"
+#include <epan/exceptions.h>
+#include <epan/show_exception.h>
static gint wslua_ett = -1;
@@ -50,19 +52,113 @@ WSLUA_CLASS_DEFINE(TreeItem,FAIL_ON_NULL_OR_EXPIRED("TreeItem"),NOP);
/* `TreeItem`s represent information in the packet-details pane.
A root `TreeItem` is passed to dissectors as the third argument. */
+/* the following is used by TreeItem_add_packet_field() - this can THROW errors */
+static proto_item *
+try_add_packet_field(lua_State *L, TreeItem tree_item, TvbRange tvbr, const int hfid,
+ const ftenum_t type, const guint encoding, gint *ret_err)
+{
+ gint err = 0;
+ proto_item* item = NULL;
+ gint endoff = 0;
+
+ switch(type) {
+ case FT_ABSOLUTE_TIME:
+ case FT_RELATIVE_TIME:
+ {
+ /* nstime_t will be g_free'd by Lua */
+ nstime_t *nstime = (nstime_t *) g_malloc0(sizeof(nstime_t));
+ item = proto_tree_add_time_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
+ tvbr->offset, tvbr->len, encoding,
+ nstime, &endoff, &err);
+ if (err == 0) {
+ pushNSTime(L,nstime);
+ lua_pushinteger(L, endoff);
+ }
+ }
+ break;
+
+ /* anything else just needs to be done the old fashioned way */
+ default:
+ item = proto_tree_add_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, encoding);
+ lua_pushnil(L);
+ lua_pushnil(L);
+ break;
+ }
+
+ if (ret_err) *ret_err = err;
+
+ return item;
+}
+
WSLUA_METHOD TreeItem_add_packet_field(lua_State *L) {
/*
- Adds an child item to a given item, returning the child.
- tree_item:add_packet_field([proto_field], [tvbrange], [encoding], ...)
+ Adds a new child tree for the given `ProtoField` object to this tree item,
+ returning the new child `TreeItem`.
+
+ Unlike `TreeItem:add()` and `TreeItem:add_le()`, the `ProtoField` argument
+ is not optional, and cannot be a `Proto` object. Instead, this function always
+ uses the `ProtoField` to determine the type of field to extract from the
+ passed-in `TvbRange`, highlighting the relevant bytes in the Packet Bytes pane
+ of the GUI (if there is a GUI), etc. If no `TvbRange` is given, no bytes are
+ highlighted and the field's value cannot be determined; the `ProtoField` must
+ have been defined/created not to have a length in such a case, or an error will
+ occur. For backwards-compatibility reasons the `encoding` argument, however,
+ must still be given.
+
+ Unlike `TreeItem:add()` and `TreeItem:add_le()`, this function performs both
+ big-endian and little-endian decoding, by setting the `encoding` argument to
+ be `ENC_BIG_ENDIAN` or `ENC_LITTLE_ENDIAN`.
+
+ The signature of this function:
+ @code
+ tree_item:add_packet_field(proto_field [,tvbrange], encoding, ...)
+ @endcode
+
+ In Wireshark version 1.11.3, this function was changed to return more than
+ just the new child `TreeItem`. The child is the first return value, so that
+ function chaining will still work as before; but it now also returns the value
+ of the extracted field (i.e., a number, `UInt64`, `Address`, etc.). If the
+ value could not be extracted from the `TvbRange`, the child `TreeItem` is still
+ returned, but the second returned value is `nil`.
+
+ Another new feature added to this function in Wireshark version 1.11.3 is the
+ ability to extract native number `ProtoField`s from string encoding in the
+ `TvbRange`, for ASCII-based and similar string encodings. For example, a
+ `ProtoField` of as `ftypes.UINT32` type can be extracted from a `TvbRange`
+ containing the ASCII string "123", and it will correctly decode the ASCII to
+ the number `123`, both in the tree as well as for the second return value of
+ this function. To do so, you must set the `encoding` argument of this function
+ to the appropriate string `ENC_*` value, bitwise-or'd with the `ENC_STRING`
+ value (see `init.lua`). `ENC_STRING` is guaranteed to be a unique bit flag, and
+ thus it can added instead of bitwise-or'ed as well. Only single-byte ASCII digit
+ string encoding types can be used for this, such as `ENC_ASCII` and `ENC_UTF_8`.
+
+ For example, assuming the `Tvb` named "`tvb`" contains the string "123":
+ @code
+ -- this is done earlier in the script
+ local myfield = ProtoField.new("Transaction ID", "myproto.trans_id", ftypes.UINT16)
+
+ -- this is done inside a dissector, post-dissector, or heuristic function
+ -- child will be the created child tree, and value will be the number 123 or nil on failure
+ local child, value = tree:add_packet_field(myfield, tvb:range(0,3), ENC_UTF_8 + ENC_STRING)
+ @encode
+
*/
+#define WSLUA_ARG_TreeItem_add_packet_field_PROTOFIELD 2 /* The ProtoField field object to add to the tree. */
+#define WSLUA_OPTARG_TreeItem_add_packet_field_TVBRANGE 3 /* The `TvbRange` of bytes in the packet this tree item covers/represents. */
+#define WSLUA_ARG_TreeItem_add_packet_field_ENCODING 4 /* The field's encoding in the `TvbRange`. */
+#define WSLUA_OPTARG_TreeItem_add_packet_field_LABEL 5 /* One or more strings to append to the created `TreeItem`. */
TvbRange tvbr;
ProtoField field;
int hfid;
int ett;
ftenum_t type;
- TreeItem tree_item = shiftTreeItem(L,1);
+ TreeItem tree_item = shiftTreeItem(L,1);
guint encoding;
proto_item* item = NULL;
+ int nargs;
+ gint err = 0;
+ const char *volatile error = NULL;
if (!tree_item) {
return luaL_error(L,"not a TreeItem!");
@@ -92,6 +188,14 @@ WSLUA_METHOD TreeItem_add_packet_field(lua_State *L) {
encoding = wslua_checkguint(L,1);
lua_remove(L,1);
+
+ /* get the number of additional args before we add more to the stack */
+ nargs = lua_gettop(L);
+
+ /* XXX: why is this being done? If the length was -1, FT_STRINGZ figures out
+ * the right length in tvb_get_stringz_enc(); if it was 0, it should remain zero;
+ * if it was greater than zero, then it's the length the caller wanted.
+ */
if (type == FT_STRINGZ) {
switch (encoding & ENC_CHARENCODING_MASK) {
@@ -105,13 +209,29 @@ WSLUA_METHOD TreeItem_add_packet_field(lua_State *L) {
break;
}
}
- item = proto_tree_add_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, encoding);
- while(lua_gettop(L)) {
+ TRY {
+
+ item = try_add_packet_field(L, tree_item, tvbr, hfid, type, encoding, &err);
+
+ } CATCH_ALL {
+ show_exception(tvbr->tvb->ws_tvb, lua_pinfo, tree_item->tree, EXCEPT_CODE, GET_MESSAGE);
+ error = "Lua programming error";
+ } ENDTRY;
+
+ if (error) { WSLUA_ERROR(TreeItem_add_packet_field,error); }
+
+ if (err != 0) {
+ lua_pushnil(L);
+ lua_pushnil(L);
+ }
+
+ while(nargs) {
const gchar* s;
s = lua_tostring(L,1);
if (s) proto_item_append_text(item, " %s", s);
lua_remove(L,1);
+ nargs--;
}
tree_item = (TreeItem)g_malloc(sizeof(struct _wslua_treeitem));
@@ -121,7 +241,10 @@ WSLUA_METHOD TreeItem_add_packet_field(lua_State *L) {
PUSH_TREEITEM(L,tree_item);
- WSLUA_RETURN(1); /* The new child TreeItem. */
+ /* move the tree object before the field value */
+ lua_insert(L, 1);
+
+ WSLUA_RETURN(3); /* The new child `TreeItem`, the field's extracted value or nil, and offset or nil. */
}
static int TreeItem_add_item_any(lua_State *L, gboolean little_endian) {
diff --git a/epan/wslua/wslua_tvb.c b/epan/wslua/wslua_tvb.c
index bfad06c51e..9746ff77a4 100644
--- a/epan/wslua/wslua_tvb.c
+++ b/epan/wslua/wslua_tvb.c
@@ -1055,8 +1055,10 @@ WSLUA_METHOD TvbRange_ether(lua_State* L) {
WSLUA_METHOD TvbRange_nstime(lua_State* L) {
/* Obtain a time_t structure from a `TvbRange`, as an `NSTime` object. */
+#define WSLUA_OPTARG_TvbRange_nstime_ENCODING 2 /* An optional ENC_* encoding value to use */
TvbRange tvbr = checkTvbRange(L,1);
NSTime nstime;
+ const guint encoding = luaL_optint(L, WSLUA_OPTARG_TvbRange_nstime_ENCODING, 0);
if ( !(tvbr && tvbr->tvb)) return 0;
if (tvbr->tvb->expired) {
@@ -1066,21 +1068,41 @@ WSLUA_METHOD TvbRange_nstime(lua_State* L) {
nstime = g_new(nstime_t,1);
- if (tvbr->len == 4) {
- nstime->secs = tvb_get_ntohl(tvbr->tvb->ws_tvb, tvbr->offset);
- nstime->nsecs = 0;
- } else if (tvbr->len == 8) {
- nstime->secs = tvb_get_ntohl(tvbr->tvb->ws_tvb, tvbr->offset);
- nstime->nsecs = tvb_get_ntohl(tvbr->tvb->ws_tvb, tvbr->offset + 4);
- } else {
- g_free(nstime);
- WSLUA_ERROR(TvbRange_nstime,"The range must be 4 or 8 bytes long");
- return 0;
+ if (encoding == 0) {
+ if (tvbr->len == 4) {
+ nstime->secs = tvb_get_ntohl(tvbr->tvb->ws_tvb, tvbr->offset);
+ nstime->nsecs = 0;
+ } else if (tvbr->len == 8) {
+ nstime->secs = tvb_get_ntohl(tvbr->tvb->ws_tvb, tvbr->offset);
+ nstime->nsecs = tvb_get_ntohl(tvbr->tvb->ws_tvb, tvbr->offset + 4);
+ } else {
+ g_free(nstime);
+ WSLUA_ERROR(TvbRange_nstime,"The range must be 4 or 8 bytes long");
+ return 0;
+ }
+ pushNSTime(L, nstime);
+ lua_pushinteger(L, tvbr->len);
+ }
+ else if (encoding & ~ENC_STR_TIME_MASK) {
+ WSLUA_OPTARG_ERROR(TvbRange_nstime, ENCODING, "invalid encoding value");
+ }
+ else {
+ gint endoff = 0;
+ nstime_t *retval = tvb_get_string_time(tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len,
+ encoding, nstime, &endoff);
+ if (!retval || endoff == 0) {
+ g_free(nstime);
+ /* push nil nstime and offset */
+ lua_pushnil(L);
+ lua_pushnil(L);
+ }
+ else {
+ pushNSTime(L, nstime);
+ lua_pushinteger(L, endoff);
+ }
}
- pushNSTime(L, nstime);
-
- WSLUA_RETURN(1); /* The `NSTime` object. */
+ WSLUA_RETURN(2); /* The `NSTime` object and number of bytes used, or nil on failure. */
}
WSLUA_METHOD TvbRange_le_nstime(lua_State* L) {