Lua: add functions for more field information

Add Lua functions so a plugin can introspect field information, such
as the type of field, flags, tvb, etc. Also add a couple of Tvb and
ByteArray methods. And cleanup the TreeItem code a little.

Change-Id: I7b58ce589ace91cce14b8abccd01ceabb63e2653
Reviewed-on: https://code.wireshark.org/review/6500
Petri-Dish: Hadriel Kaplan <hadrielk@yahoo.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Hadriel Kaplan <hadrielk@yahoo.com>
Tested-by: Hadriel Kaplan <hadrielk@yahoo.com>
This commit is contained in:
Hadriel Kaplan 2015-07-08 15:20:50 -04:00
parent 7b85f62ba3
commit 281055af9c
9 changed files with 533 additions and 76 deletions

View File

@ -163,9 +163,6 @@ int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data
lua_pinfo = pinfo; lua_pinfo = pinfo;
lua_tvb = tvb; lua_tvb = tvb;
lua_tree = create_TreeItem(tree, proto_tree_add_item(tree, hf_wslua_fake, tvb, 0, 0, ENC_NA));
PROTO_ITEM_SET_HIDDEN(lua_tree->item);
/* /*
* almost equivalent to Lua: * almost equivalent to Lua:
* dissectors[current_proto](tvb,pinfo,tree) * dissectors[current_proto](tvb,pinfo,tree)
@ -185,7 +182,8 @@ int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data
push_Tvb(L,tvb); push_Tvb(L,tvb);
push_Pinfo(L,pinfo); push_Pinfo(L,pinfo);
push_TreeItem(L,lua_tree); lua_tree = push_TreeItem(L, tree, proto_tree_add_item(tree, hf_wslua_fake, tvb, 0, 0, ENC_NA));
PROTO_ITEM_SET_HIDDEN(lua_tree->item);
if ( lua_pcall(L,3,1,0) ) { if ( lua_pcall(L,3,1,0) ) {
proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, "Lua Error: %s", lua_tostring(L,-1)); proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, "Lua Error: %s", lua_tostring(L,-1));
@ -278,12 +276,10 @@ gboolean heur_dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, v
return FALSE; return FALSE;
} }
lua_tree = create_TreeItem(tree, proto_tree_add_item(tree, hf_wslua_fake, tvb, 0, 0, ENC_NA));
PROTO_ITEM_SET_HIDDEN(lua_tree->item);
push_Tvb(L,tvb); push_Tvb(L,tvb);
push_Pinfo(L,pinfo); push_Pinfo(L,pinfo);
push_TreeItem(L,lua_tree); lua_tree = push_TreeItem(L, tree, proto_tree_add_item(tree, hf_wslua_fake, tvb, 0, 0, ENC_NA));
PROTO_ITEM_SET_HIDDEN(lua_tree->item);
if ( lua_pcall(L,3,1,0) ) { if ( lua_pcall(L,3,1,0) ) {
proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0, proto_tree_add_expert_format(tree, pinfo, &ei_lua_error, tvb, 0, 0,

View File

@ -53,9 +53,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* public function declarations */ /* public function declarations */
REX_API int REX_OPENLIB (lua_State *L); REX_API int REX_OPENLIB (lua_State *L);
int Gregex_get_compile_flags (lua_State *L); extern int Gregex_get_compile_flags (lua_State *L);
int Gregex_get_match_flags (lua_State *L); extern int Gregex_get_match_flags (lua_State *L);
int Gregex_get_flags (lua_State *L); extern int Gregex_get_flags (lua_State *L);
/* Special values for maxmatch in gsub. They all must be negative. */ /* Special values for maxmatch in gsub. They all must be negative. */
#define GSUB_UNLIMITED -1 #define GSUB_UNLIMITED -1

View File

@ -54,9 +54,6 @@ THE SOFTWARE.
#include "lauxlib.h" #include "lauxlib.h"
#include "lrexlib.h" #include "lrexlib.h"
extern int Gregex_get_flags (lua_State *L);
extern int Gregex_get_compile_flags (lua_State *L);
extern int Gregex_get_match_flags (lua_State *L);
extern flag_pair gregex_error_flags[]; extern flag_pair gregex_error_flags[];
/* These 2 settings may be redefined from the command-line or the makefile. /* These 2 settings may be redefined from the command-line or the makefile.

View File

@ -118,7 +118,7 @@ typedef struct _wslua_field_t {
int hfid; int hfid;
int ett; int ett;
char* name; char* name;
char* abbr; char* abbrev;
char* blob; char* blob;
enum ftenum type; enum ftenum type;
unsigned base; unsigned base;
@ -128,7 +128,7 @@ typedef struct _wslua_field_t {
typedef struct _wslua_expert_field_t { typedef struct _wslua_expert_field_t {
expert_field ids; expert_field ids;
const gchar *abbr; const gchar *abbrev;
const gchar *text; const gchar *text;
int group; int group;
int severity; int severity;
@ -707,9 +707,10 @@ extern void clear_outstanding_Columns(void);
extern void clear_outstanding_PrivateTable(void); extern void clear_outstanding_PrivateTable(void);
extern int get_hf_wslua_text(void); extern int get_hf_wslua_text(void);
extern TreeItem* push_TreeItem(lua_State* L, TreeItem ti); extern TreeItem push_TreeItem(lua_State *L, proto_tree *tree, proto_item *item);
extern void clear_outstanding_TreeItem(void); extern void clear_outstanding_TreeItem(void);
extern FieldInfo* push_FieldInfo(lua_State *L, field_info* f);
extern void clear_outstanding_FieldInfo(void); extern void clear_outstanding_FieldInfo(void);
extern void wslua_print_stack(char* s, lua_State* L); extern void wslua_print_stack(char* s, lua_State* L);
@ -720,7 +721,7 @@ extern int wslua_cleanup(void);
extern tap_extractor_t wslua_get_tap_extractor(const gchar* name); extern tap_extractor_t wslua_get_tap_extractor(const gchar* name);
extern int wslua_set_tap_enums(lua_State* L); extern int wslua_set_tap_enums(lua_State* L);
extern int wslua_is_field_available(lua_State* L, const char* field_abbr); extern ProtoField wslua_is_field_available(lua_State* L, const char* field_abbr);
extern char* wslua_get_actual_filename(const char* fname); extern char* wslua_get_actual_filename(const char* fname);

View File

@ -45,7 +45,13 @@ WSLUA_CLASS_DEFINE(FieldInfo,FAIL_ON_NULL_OR_EXPIRED("FieldInfo"),NOP);
static GPtrArray* outstanding_FieldInfo = NULL; static GPtrArray* outstanding_FieldInfo = NULL;
#define PUSH_FIELDINFO(L,fi) {g_ptr_array_add(outstanding_FieldInfo,fi);pushFieldInfo(L,fi);} FieldInfo* push_FieldInfo(lua_State* L, field_info* f) {
FieldInfo fi = (FieldInfo) g_malloc(sizeof(struct _wslua_field_info));
fi->ws_fi = f;
fi->expired = FALSE;
g_ptr_array_add(outstanding_FieldInfo,fi);
return pushFieldInfo(L,fi);
}
CLEAR_OUTSTANDING(FieldInfo,expired,TRUE) CLEAR_OUTSTANDING(FieldInfo,expired,TRUE)
@ -210,7 +216,7 @@ WSLUA_METAMETHOD FieldInfo__call(lua_State* L) {
} }
} }
/* WSLUA_ATTRIBUTE FieldInfo_label RO The string representing this field */ /* WSLUA_ATTRIBUTE FieldInfo_label RO The string representing this field. */
WSLUA_METAMETHOD FieldInfo__tostring(lua_State* L) { WSLUA_METAMETHOD FieldInfo__tostring(lua_State* L) {
/* The string representation of the field. */ /* The string representation of the field. */
FieldInfo fi = checkFieldInfo(L,1); FieldInfo fi = checkFieldInfo(L,1);
@ -244,7 +250,7 @@ WSLUA_METAMETHOD FieldInfo__tostring(lua_State* L) {
return 1; return 1;
} }
/* WSLUA_ATTRIBUTE FieldInfo_display RO The string display of this field as seen in GUI */ /* WSLUA_ATTRIBUTE FieldInfo_display RO The string display of this field as seen in GUI. */
static int FieldInfo_get_display(lua_State* L) { static int FieldInfo_get_display(lua_State* L) {
/* The display string of this field as seen in GUI. */ /* The display string of this field as seen in GUI. */
FieldInfo fi = checkFieldInfo(L,1); FieldInfo fi = checkFieldInfo(L,1);
@ -272,7 +278,43 @@ static int FieldInfo_get_display(lua_State* L) {
return 1; return 1;
} }
/* WSLUA_ATTRIBUTE FieldInfo_range RO The `TvbRange` covering this field */ /* WSLUA_ATTRIBUTE FieldInfo_type RO The internal field type, a number which
matches one of the `ftype` values in `init.lua`.
@since 1.99.9
*/
static int FieldInfo_get_type(lua_State* L) {
FieldInfo fi = checkFieldInfo(L,1);
if (fi->ws_fi->hfinfo) {
lua_pushnumber(L, fi->ws_fi->hfinfo->type);
}
else {
lua_pushnil(L);
}
return 1;
}
/* WSLUA_ATTRIBUTE FieldInfo_source RO The source `Tvb` object the `FieldInfo` is derived
from, or nil if there is none.
@since 1.99.9
*/
static int FieldInfo_get_source(lua_State* L) {
FieldInfo fi = checkFieldInfo(L,1);
if (fi->ws_fi->ds_tvb) {
push_Tvb(L, fi->ws_fi->ds_tvb);
}
else {
lua_pushnil(L);
}
return 1;
}
/* WSLUA_ATTRIBUTE FieldInfo_range RO The `TvbRange` covering this field. */
static int FieldInfo_get_range(lua_State* L) { static int FieldInfo_get_range(lua_State* L) {
/* The `TvbRange` covering this field. */ /* The `TvbRange` covering this field. */
FieldInfo fi = checkFieldInfo(L,1); FieldInfo fi = checkFieldInfo(L,1);
@ -284,7 +326,7 @@ static int FieldInfo_get_range(lua_State* L) {
return 0; return 0;
} }
/* WSLUA_ATTRIBUTE FieldInfo_generated RO Whether this field was marked as generated (boolean) */ /* WSLUA_ATTRIBUTE FieldInfo_generated RO Whether this field was marked as generated (boolean). */
static int FieldInfo_get_generated(lua_State* L) { static int FieldInfo_get_generated(lua_State* L) {
/* Whether this field was marked as generated. */ /* Whether this field was marked as generated. */
FieldInfo fi = checkFieldInfo(L,1); FieldInfo fi = checkFieldInfo(L,1);
@ -293,7 +335,54 @@ static int FieldInfo_get_generated(lua_State* L) {
return 1; return 1;
} }
/* WSLUA_ATTRIBUTE FieldInfo_name RO The name of this field */ /* WSLUA_ATTRIBUTE FieldInfo_hidden RO Whether this field was marked as hidden (boolean).
@since 1.99.9
*/
static int FieldInfo_get_hidden(lua_State* L) {
FieldInfo fi = checkFieldInfo(L,1);
lua_pushboolean(L,FI_GET_FLAG(fi->ws_fi, FI_HIDDEN));
return 1;
}
/* WSLUA_ATTRIBUTE FieldInfo_is_url RO Whether this field was marked as being a URL (boolean).
@since 1.99.9
*/
static int FieldInfo_get_is_url(lua_State* L) {
FieldInfo fi = checkFieldInfo(L,1);
lua_pushboolean(L,FI_GET_FLAG(fi->ws_fi, FI_URL));
return 1;
}
/* WSLUA_ATTRIBUTE FieldInfo_little_endian RO Whether this field is little-endian encoded (boolean).
@since 1.99.9
*/
static int FieldInfo_get_little_endian(lua_State* L) {
FieldInfo fi = checkFieldInfo(L,1);
lua_pushboolean(L,FI_GET_FLAG(fi->ws_fi, FI_LITTLE_ENDIAN));
return 1;
}
/* WSLUA_ATTRIBUTE FieldInfo_big_endian RO Whether this field is big-endian encoded (boolean).
@since 1.99.9
*/
static int FieldInfo_get_big_endian(lua_State* L) {
FieldInfo fi = checkFieldInfo(L,1);
lua_pushboolean(L,FI_GET_FLAG(fi->ws_fi, FI_BIG_ENDIAN));
return 1;
}
/* WSLUA_ATTRIBUTE FieldInfo_name RO The filter name of this field.
@since 1.99.9
*/
static int FieldInfo_get_name(lua_State* L) { static int FieldInfo_get_name(lua_State* L) {
/* The filter name of this field. */ /* The filter name of this field. */
FieldInfo fi = checkFieldInfo(L,1); FieldInfo fi = checkFieldInfo(L,1);
@ -374,8 +463,14 @@ static int FieldInfo__gc(lua_State* L _U_) {
WSLUA_ATTRIBUTES FieldInfo_attributes[] = { WSLUA_ATTRIBUTES FieldInfo_attributes[] = {
WSLUA_ATTRIBUTE_ROREG(FieldInfo,range), WSLUA_ATTRIBUTE_ROREG(FieldInfo,range),
WSLUA_ATTRIBUTE_ROREG(FieldInfo,generated), WSLUA_ATTRIBUTE_ROREG(FieldInfo,generated),
WSLUA_ATTRIBUTE_ROREG(FieldInfo,hidden),
WSLUA_ATTRIBUTE_ROREG(FieldInfo,is_url),
WSLUA_ATTRIBUTE_ROREG(FieldInfo,little_endian),
WSLUA_ATTRIBUTE_ROREG(FieldInfo,big_endian),
WSLUA_ATTRIBUTE_ROREG(FieldInfo,name), WSLUA_ATTRIBUTE_ROREG(FieldInfo,name),
WSLUA_ATTRIBUTE_ROREG(FieldInfo,display), WSLUA_ATTRIBUTE_ROREG(FieldInfo,display),
WSLUA_ATTRIBUTE_ROREG(FieldInfo,type),
WSLUA_ATTRIBUTE_ROREG(FieldInfo,source),
{ "label", FieldInfo__tostring, NULL }, { "label", FieldInfo__tostring, NULL },
{ "value", FieldInfo__call, NULL }, { "value", FieldInfo__call, NULL },
{ "tvb", FieldInfo_get_range, NULL }, { "tvb", FieldInfo_get_range, NULL },
@ -422,11 +517,7 @@ WSLUA_FUNCTION wslua_all_field_infos(lua_State* L) {
if (found) { if (found) {
for (i=0; i<found->len; i++) { for (i=0; i<found->len; i++) {
FieldInfo fi = (FieldInfo)g_malloc(sizeof(struct _wslua_field_info)); push_FieldInfo(L, (field_info *)g_ptr_array_index(found,i));
fi->ws_fi = (field_info *)g_ptr_array_index(found,i);
fi->expired = FALSE;
PUSH_FIELDINFO(L,fi);
items_found++; items_found++;
} }
@ -583,6 +674,74 @@ WSLUA_CONSTRUCTOR Field_list(lua_State *L) {
WSLUA_RETURN(1); /* The array table of field filter names */ WSLUA_RETURN(1); /* The array table of field filter names */
} }
/* the following is used in Field_get_xxx functions later */
#define GET_HFINFO_MEMBER(luafunc, member) \
if (wanted_fields) { \
/* before registration, so it's a gchar** of the abbrev */ \
const gchar* name = (const gchar*) *fi; \
if (name) { \
hfinfo = proto_registrar_get_byname(name); \
if (!hfinfo) { \
/* could be a Lua-created field */ \
ProtoField pf = wslua_is_field_available(L, name); \
if (pf) { \
luafunc(L, pf->member); \
return 1; \
} \
} \
} else { \
luaL_error(L, "Field." #member ": unknown field"); \
return 0; \
} \
} else { \
hfinfo = *fi; \
} \
\
if (hfinfo) { \
luafunc(L,hfinfo->member); \
} else \
lua_pushnil(L)
/* WSLUA_ATTRIBUTE Field_name RO The filter name of this field, or nil.
@since 1.99.9
*/
static int Field_get_name(lua_State* L) {
Field fi = checkField(L,1);
header_field_info* hfinfo = NULL;
GET_HFINFO_MEMBER(lua_pushstring, abbrev);
return 1;
}
/* WSLUA_ATTRIBUTE Field_display RO The full display name of this field, or nil.
@since 1.99.9
*/
static int Field_get_display(lua_State* L) {
Field fi = checkField(L,1);
header_field_info* hfinfo = NULL;
GET_HFINFO_MEMBER(lua_pushstring, name);
return 1;
}
/* WSLUA_ATTRIBUTE Field_type RO The `ftype` of this field, or nil.
@since 1.99.9
*/
static int Field_get_type(lua_State* L) {
Field fi = checkField(L,1);
header_field_info* hfinfo = NULL;
GET_HFINFO_MEMBER(lua_pushnumber, type);
return 1;
}
WSLUA_METAMETHOD Field__call (lua_State* L) { WSLUA_METAMETHOD Field__call (lua_State* L) {
/* Obtain all values (see `FieldInfo`) for this field. */ /* Obtain all values (see `FieldInfo`) for this field. */
Field f = checkField(L,1); Field f = checkField(L,1);
@ -604,11 +763,7 @@ WSLUA_METAMETHOD Field__call (lua_State* L) {
guint i; guint i;
if (found) { if (found) {
for (i=0; i<found->len; i++) { for (i=0; i<found->len; i++) {
FieldInfo fi = (FieldInfo)g_malloc(sizeof(struct _wslua_field_info)); push_FieldInfo(L, (field_info *) g_ptr_array_index(found,i));
fi->ws_fi = (field_info *)g_ptr_array_index(found,i);
fi->expired = FALSE;
PUSH_FIELDINFO(L,fi);
items_found++; items_found++;
} }
} }
@ -619,7 +774,7 @@ WSLUA_METAMETHOD Field__call (lua_State* L) {
} }
WSLUA_METAMETHOD Field__tostring(lua_State* L) { WSLUA_METAMETHOD Field__tostring(lua_State* L) {
/* Obtain a string with the field name. */ /* Obtain a string with the field filter name. */
Field f = checkField(L,1); Field f = checkField(L,1);
if (wanted_fields) { if (wanted_fields) {
@ -636,6 +791,13 @@ static int Field__gc(lua_State* L _U_) {
return 0; return 0;
} }
WSLUA_ATTRIBUTES Field_attributes[] = {
WSLUA_ATTRIBUTE_ROREG(Field,name),
WSLUA_ATTRIBUTE_ROREG(Field,display),
WSLUA_ATTRIBUTE_ROREG(Field,type),
{ NULL, NULL, NULL }
};
WSLUA_METHODS Field_methods[] = { WSLUA_METHODS Field_methods[] = {
WSLUA_CLASS_FNREG(Field,new), WSLUA_CLASS_FNREG(Field,new),
WSLUA_CLASS_FNREG(Field,list), WSLUA_CLASS_FNREG(Field,list),
@ -653,6 +815,7 @@ int Field_register(lua_State* L) {
wanted_fields = g_ptr_array_new(); wanted_fields = g_ptr_array_new();
WSLUA_REGISTER_CLASS(Field); WSLUA_REGISTER_CLASS(Field);
WSLUA_REGISTER_ATTRIBUTES(Field);
outstanding_FieldInfo = g_ptr_array_new(); outstanding_FieldInfo = g_ptr_array_new();
return 0; return 0;

View File

@ -876,7 +876,7 @@ WSLUA_CONSTRUCTOR ProtoField_new(lua_State* L) {
f->hfid = -2; f->hfid = -2;
f->ett = -1; f->ett = -1;
f->name = g_strdup(name); f->name = g_strdup(name);
f->abbr = g_strdup(abbr); f->abbrev = g_strdup(abbr);
f->type = type; f->type = type;
f->base = base; f->base = base;
if (tfs) { if (tfs) {
@ -940,7 +940,7 @@ static int ProtoField_integer(lua_State* L, enum ftenum type) {
f->hfid = -2; f->hfid = -2;
f->ett = -1; f->ett = -1;
f->name = g_strdup(name); f->name = g_strdup(name);
f->abbr = g_strdup(abbr); f->abbrev = g_strdup(abbr);
f->type = type; f->type = type;
f->base = base; f->base = base;
if (vs64) { if (vs64) {
@ -1104,7 +1104,7 @@ static int ProtoField_boolean(lua_State* L, enum ftenum type) {
f->hfid = -2; f->hfid = -2;
f->ett = -1; f->ett = -1;
f->name = g_strdup(name); f->name = g_strdup(name);
f->abbr = g_strdup(abbr); f->abbrev = g_strdup(abbr);
f->type = type; f->type = type;
f->vs = TFS(tfs); f->vs = TFS(tfs);
f->base = base; f->base = base;
@ -1157,7 +1157,7 @@ static int ProtoField_time(lua_State* L,enum ftenum type) {
f->hfid = -2; f->hfid = -2;
f->ett = -1; f->ett = -1;
f->name = g_strdup(name); f->name = g_strdup(name);
f->abbr = g_strdup(abbr); f->abbrev = g_strdup(abbr);
f->type = type; f->type = type;
f->vs = NULL; f->vs = NULL;
f->base = base; f->base = base;
@ -1201,7 +1201,7 @@ static int ProtoField_other(lua_State* L,enum ftenum type) {
f->hfid = -2; f->hfid = -2;
f->ett = -1; f->ett = -1;
f->name = g_strdup(name); f->name = g_strdup(name);
f->abbr = g_strdup(abbr); f->abbrev = g_strdup(abbr);
f->type = type; f->type = type;
f->vs = NULL; f->vs = NULL;
f->base = BASE_NONE; f->base = BASE_NONE;
@ -1330,7 +1330,7 @@ WSLUA_METAMETHOD ProtoField__tostring(lua_State* L) {
/* Returns a string with info about a protofield (for debugging purposes). */ /* Returns a string with info about a protofield (for debugging purposes). */
ProtoField f = checkProtoField(L,1); ProtoField f = checkProtoField(L,1);
gchar* s = g_strdup_printf("ProtoField(%i): %s %s %s %s %p %.8x %s", gchar* s = g_strdup_printf("ProtoField(%i): %s %s %s %s %p %.8x %s",
f->hfid,f->name,f->abbr, f->hfid,f->name,f->abbrev,
ftenum_to_string(f->type), ftenum_to_string(f->type),
base_to_string(f->base), base_to_string(f->base),
f->vs,f->mask,f->blob); f->vs,f->mask,f->blob);
@ -1355,7 +1355,7 @@ static int ProtoField__gc(lua_State* L) {
/* g_assert() ?? */ /* g_assert() ?? */
} else if (f->hfid == -2) { } else if (f->hfid == -2) {
g_free(f->name); g_free(f->name);
g_free(f->abbr); g_free(f->abbrev);
g_free(f->blob); g_free(f->blob);
g_free(f); g_free(f);
} }
@ -1443,7 +1443,7 @@ WSLUA_CONSTRUCTOR ProtoExpert_new(lua_State* L) {
pe->ids.ei = EI_INIT_EI; pe->ids.ei = EI_INIT_EI;
pe->ids.hf = EI_INIT_HF; pe->ids.hf = EI_INIT_HF;
pe->abbr = g_strdup(abbr); pe->abbrev = g_strdup(abbr);
pe->text = g_strdup(text); pe->text = g_strdup(text);
pe->group = group; pe->group = group;
pe->severity = severity; pe->severity = severity;
@ -1464,7 +1464,7 @@ WSLUA_METAMETHOD ProtoExpert__tostring(lua_State* L) {
lua_pushstring(L,"ProtoExpert pointer is NULL!"); lua_pushstring(L,"ProtoExpert pointer is NULL!");
} else { } else {
lua_pushfstring(L, "ProtoExpert: ei=%d, hf=%d, abbr=%s, text=%s, group=%d, severity=%d", 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); pe->ids.ei, pe->ids.hf, pe->abbrev, pe->text, pe->group, pe->severity);
} }
return 1; return 1;
} }
@ -1953,7 +1953,7 @@ int Proto_register(lua_State* L) {
* Query field abbr that is defined and bound to a Proto in lua. * Query field abbr that is defined and bound to a Proto in lua.
* They are not registered until the end of the initialization. * They are not registered until the end of the initialization.
*/ */
int wslua_is_field_available(lua_State* L, const char* field_abbr) { ProtoField wslua_is_field_available(lua_State* L, const char* field_abbr) {
lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref);
lua_pushnil(L); lua_pushnil(L);
while (lua_next(L, -2)) { while (lua_next(L, -2)) {
@ -1965,10 +1965,10 @@ int wslua_is_field_available(lua_State* L, const char* field_abbr) {
lua_pushnil(L); lua_pushnil(L);
while (lua_next(L, -2)) { while (lua_next(L, -2)) {
ProtoField f = checkProtoField(L, -1); ProtoField f = checkProtoField(L, -1);
if (strcmp(field_abbr, f->abbr) == 0) { if (strcmp(field_abbr, f->abbrev) == 0) {
/* found! */ /* found! */
lua_pop(L, 6); lua_pop(L, 6);
return 1; return f;
} }
lua_pop(L, 1); /* table value */ lua_pop(L, 1); /* table value */
} }
@ -1976,7 +1976,7 @@ int wslua_is_field_available(lua_State* L, const char* field_abbr) {
} }
lua_pop(L, 1); /* protocols_table_ref */ lua_pop(L, 1); /* protocols_table_ref */
return 0; return NULL;
} }
int Proto_commit(lua_State* L) { int Proto_commit(lua_State* L) {
@ -2010,7 +2010,7 @@ int Proto_commit(lua_State* L) {
hfri.p_id = &(f->hfid); hfri.p_id = &(f->hfid);
hfri.hfinfo.name = f->name; hfri.hfinfo.name = f->name;
hfri.hfinfo.abbrev = f->abbr; hfri.hfinfo.abbrev = f->abbrev;
hfri.hfinfo.type = f->type; hfri.hfinfo.type = f->type;
hfri.hfinfo.display = f->base; hfri.hfinfo.display = f->base;
hfri.hfinfo.strings = VALS(f->vs); hfri.hfinfo.strings = VALS(f->vs);
@ -2043,7 +2043,7 @@ int Proto_commit(lua_State* L) {
ei_register_info eiri = { NULL, { NULL, 0, 0, NULL, EXPFILL } }; ei_register_info eiri = { NULL, { NULL, 0, 0, NULL, EXPFILL } };
eiri.ids = &(e->ids); eiri.ids = &(e->ids);
eiri.eiinfo.name = e->abbr; eiri.eiinfo.name = e->abbrev;
eiri.eiinfo.group = e->group; eiri.eiinfo.group = e->group;
eiri.eiinfo.severity = e->severity; eiri.eiinfo.severity = e->severity;
eiri.eiinfo.summary = e->text; eiri.eiinfo.summary = e->text;
@ -2143,12 +2143,11 @@ wslua_dissect_tcp_dissector(tvbuff_t *tvb, packet_info *pinfo,
lua_rawgeti(L, LUA_REGISTRYINDEX, fs->dissect_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, fs->dissect_ref);
if (lua_isfunction(L,1)) { if (lua_isfunction(L,1)) {
/* XXX: not sure if it's kosher to just use the tree as the item */
TreeItem ti = create_TreeItem(tree, (proto_item*)tree);
push_Tvb(L,tvb); push_Tvb(L,tvb);
push_Pinfo(L,pinfo); push_Pinfo(L,pinfo);
push_TreeItem(L,ti); /* XXX: not sure if it's kosher to just use the tree as the item */
push_TreeItem(L, tree, (proto_item*)tree);
if ( lua_pcall(L,3,1,0) ) { if ( lua_pcall(L,3,1,0) ) {
luaL_error(L, "Lua Error dissect_tcp_pdus dissect_func: %s", lua_tostring(L,-1)); luaL_error(L, "Lua Error dissect_tcp_pdus dissect_func: %s", lua_tostring(L,-1));

View File

@ -37,13 +37,21 @@ static gint wslua_ett = -1;
static GPtrArray* outstanding_TreeItem = NULL; static GPtrArray* outstanding_TreeItem = NULL;
#define PUSH_TREEITEM(L,i) {g_ptr_array_add(outstanding_TreeItem,i);pushTreeItem(L,i);}
TreeItem* push_TreeItem(lua_State*L, TreeItem t) { /* pushing a TreeItem with a NULL item or subtree is completely valid for this function */
g_ptr_array_add(outstanding_TreeItem,t); TreeItem push_TreeItem(lua_State *L, proto_tree *tree, proto_item *item) {
return pushTreeItem(L,t); TreeItem ti = (struct _wslua_treeitem *)g_malloc(sizeof(struct _wslua_treeitem));
ti->tree = tree;
ti->item = item;
ti->expired = FALSE;
g_ptr_array_add(outstanding_TreeItem, ti);
return *(pushTreeItem(L,ti));
} }
/* creates the TreeItem but does NOT push it into Lua */
TreeItem create_TreeItem(proto_tree* tree, proto_item* item) TreeItem create_TreeItem(proto_tree* tree, proto_item* item)
{ {
TreeItem tree_item = (TreeItem)g_malloc(sizeof(struct _wslua_treeitem)); TreeItem tree_item = (TreeItem)g_malloc(sizeof(struct _wslua_treeitem));
@ -57,8 +65,25 @@ TreeItem create_TreeItem(proto_tree* tree, proto_item* item)
CLEAR_OUTSTANDING(TreeItem, expired, TRUE) CLEAR_OUTSTANDING(TreeItem, expired, TRUE)
WSLUA_CLASS_DEFINE(TreeItem,FAIL_ON_NULL_OR_EXPIRED("TreeItem"),NOP); WSLUA_CLASS_DEFINE(TreeItem,FAIL_ON_NULL_OR_EXPIRED("TreeItem"),NOP);
/* ++TreeItem++s represent information in the packet-details pane. /* ++TreeItem++s represent information in the packet-details pane of
A root +TreeItem+ is passed to dissectors as the third argument. */ Wireshark, and the packet details view of Tshark. A `TreeItem` represents
a node in the tree, which might also be a subtree and have a list of
children. The children of a subtree have zero or more siblings: other children
of the same `TreeItem` subtree.
During dissection, heuristic-dissection, and post-dissection, a root
+TreeItem+ is passed to dissectors as the third argument of the function
callback (e.g., `myproto.dissector(tvbuf,pktinfo,root)`).
In some cases the tree is not truly added to, in order to improve performance.
For example for packets not currently displayed/selected in Wireshark's visible
window pane, or if Tshark isn't invoked with the `-V` switch. However the
"add" type `TreeItem` functions can still be called, and still return `TreeItem`
objects - but the info isn't really added to the tree. Therefore you do not
typically need to worry about whether there's a real tree or not. If, for some
reason, you need to know it, you can use the `tree.visible` attribute getter
to retrieve the state.
*/
/* the following is used by TreeItem_add_packet_field() - this can THROW errors */ /* the following is used by TreeItem_add_packet_field() - this can THROW errors */
static proto_item * static proto_item *
@ -264,9 +289,7 @@ WSLUA_METHOD TreeItem_add_packet_field(lua_State *L) {
nargs--; nargs--;
} }
tree_item = create_TreeItem(proto_item_add_subtree(item,ett > 0 ? ett : wslua_ett), item); tree_item = push_TreeItem(L, proto_item_add_subtree(item,ett > 0 ? ett : wslua_ett), item);
PUSH_TREEITEM(L,tree_item);
/* move the tree object before the field value */ /* move the tree object before the field value */
lua_insert(L, 1); lua_insert(L, 1);
@ -315,7 +338,11 @@ static int TreeItem_add_item_any(lua_State *L, gboolean little_endian) {
} }
if (hfid > 0 ) { if (hfid > 0 ) {
/* hfid is > 0 when the first arg was a ProtoField or Proto */
if (lua_gettop(L)) { if (lua_gettop(L)) {
/* if we got here, the (L,1) index is the value to add, instead of decoding from the Tvb */
switch(type) { switch(type) {
case FT_PROTOCOL: case FT_PROTOCOL:
item = proto_tree_add_item(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,ENC_NA); item = proto_tree_add_item(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,ENC_NA);
@ -388,17 +415,20 @@ static int TreeItem_add_item_any(lua_State *L, gboolean little_endian) {
lua_remove(L,1); lua_remove(L,1);
} else { } else {
/* the Lua stack is empty - no value was given - so decode the value from the tvb */
if (type == FT_STRINGZ) tvbr->len = tvb_strsize (tvbr->tvb->ws_tvb, tvbr->offset); if (type == FT_STRINGZ) tvbr->len = tvb_strsize (tvbr->tvb->ws_tvb, tvbr->offset);
item = proto_tree_add_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, little_endian ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN); item = proto_tree_add_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, little_endian ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN);
} }
if ( lua_gettop(L) ) { if ( lua_gettop(L) ) {
/* if there was a value, it was removed earlier, so what's left is the display string to set */
const gchar* s = lua_tostring(L,1); const gchar* s = lua_tostring(L,1);
if (s) proto_item_set_text(item,"%s",s); if (s) proto_item_set_text(item,"%s",s);
lua_remove(L,1); lua_remove(L,1);
} }
} else { } else {
/* no ProtoField or Proto was given */
if (lua_gettop(L)) { if (lua_gettop(L)) {
const gchar* s = lua_tostring(L,1); const gchar* s = lua_tostring(L,1);
const int hf = get_hf_wslua_text(); const int hf = get_hf_wslua_text();
@ -416,14 +446,13 @@ static int TreeItem_add_item_any(lua_State *L, gboolean little_endian) {
} }
while(lua_gettop(L)) { while(lua_gettop(L)) {
/* keep appending more text */
const gchar* s = lua_tostring(L,1); const gchar* s = lua_tostring(L,1);
if (s) proto_item_append_text(item, " %s", s); if (s) proto_item_append_text(item, " %s", s);
lua_remove(L,1); lua_remove(L,1);
} }
tree_item = create_TreeItem(proto_item_add_subtree(item,ett > 0 ? ett : wslua_ett), item); tree_item = push_TreeItem(L, proto_item_add_subtree(item,ett > 0 ? ett : wslua_ett), item);
PUSH_TREEITEM(L,tree_item);
return 1; return 1;
} }
@ -467,6 +496,38 @@ WSLUA_METHOD TreeItem_add_le(lua_State *L) {
WSLUA_RETURN(TreeItem_add_item_any(L,TRUE)); /* The new child TreeItem. */ WSLUA_RETURN(TreeItem_add_item_any(L,TRUE)); /* The new child TreeItem. */
} }
/* WSLUA_ATTRIBUTE TreeItem_text RW Set/get the `TreeItem`'s display string (string).
For the getter, if the TreeItem has no display string, then nil is returned.
@since 1.99.3
*/
static int TreeItem_get_text(lua_State* L) {
TreeItem ti = checkTreeItem(L,1);
gchar label_str[ITEM_LABEL_LENGTH+1];
gchar *label_ptr;
field_info *fi = PITEM_FINFO(ti->item);
if(fi) {
if (!fi->rep) {
label_ptr = label_str;
proto_item_fill_label(fi, label_str);
} else
label_ptr = fi->rep->representation;
if (label_ptr) {
lua_pushstring(L, label_ptr);
} else {
lua_pushnil(L);
}
} else {
lua_pushnil(L);
}
return 1;
}
/* the following is used as both a method and attribute */
WSLUA_METHOD TreeItem_set_text(lua_State *L) { WSLUA_METHOD TreeItem_set_text(lua_State *L) {
/* Sets the text of the label. /* Sets the text of the label.
@ -636,14 +697,55 @@ WSLUA_METHOD TreeItem_add_tvb_expert_info(lua_State *L) {
WSLUA_RETURN(1); /* The same TreeItem. */ WSLUA_RETURN(1); /* The same TreeItem. */
} }
/* WSLUA_ATTRIBUTE TreeItem_visible RO Get the `TreeItem`'s subtree visibility status (boolean).
@since 1.99.9
*/
static int TreeItem_get_visible(lua_State* L) {
TreeItem ti = checkTreeItem(L,1);
if (ti->tree) {
lua_pushboolean(L, PTREE_DATA(ti->tree)->visible);
}
else {
lua_pushboolean(L, FALSE);
}
return 1;
}
/* WSLUA_ATTRIBUTE TreeItem_generated RW Set/get the `TreeItem`'s generated state (boolean).
@since 1.99.9
*/
static int TreeItem_get_generated(lua_State* L) {
TreeItem ti = checkTreeItem(L,1);
lua_pushboolean(L, PROTO_ITEM_IS_GENERATED(ti->item));
return 1;
}
/* the following is used as both a method and attribute. As a method it defaults
to setting the value, because that's what it used to do before. */
WSLUA_METHOD TreeItem_set_generated(lua_State *L) { WSLUA_METHOD TreeItem_set_generated(lua_State *L) {
/* Marks the `TreeItem` as a generated field (with data inferred but not contained in the packet). /* Marks the `TreeItem` as a generated field (with data inferred but not contained in the packet).
This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls. This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
*/ */
#define WSLUA_OPTARG_TreeItem_set_generated_BOOL 2 /* A Lua boolean, which if `true` sets the `TreeItem`
generated flag, else clears it (default=true) */
TreeItem ti = checkTreeItem(L,1); TreeItem ti = checkTreeItem(L,1);
gboolean set = wslua_optbool(L, WSLUA_OPTARG_TreeItem_set_generated_BOOL, TRUE);
PROTO_ITEM_SET_GENERATED(ti->item); if (set) {
PROTO_ITEM_SET_GENERATED(ti->item);
} else {
if (ti->item)
FI_RESET_FLAG(PITEM_FINFO(ti->item), FI_GENERATED);
}
/* copy the TreeItem userdata so we give it back */ /* copy the TreeItem userdata so we give it back */
lua_pushvalue(L, 1); lua_pushvalue(L, 1);
@ -651,12 +753,35 @@ WSLUA_METHOD TreeItem_set_generated(lua_State *L) {
WSLUA_RETURN(1); /* The same TreeItem. */ WSLUA_RETURN(1); /* The same TreeItem. */
} }
/* WSLUA_ATTRIBUTE TreeItem_hidden RW Set/get `TreeItem`'s hidden state (boolean).
WSLUA_METHOD TreeItem_set_hidden(lua_State *L) { @since 1.99.9
/* This function should not be used, and is provided for backwards-compatibility only. */ */
static int TreeItem_get_hidden(lua_State* L) {
TreeItem ti = checkTreeItem(L,1); TreeItem ti = checkTreeItem(L,1);
PROTO_ITEM_SET_HIDDEN(ti->item); lua_pushboolean(L, PROTO_ITEM_IS_HIDDEN(ti->item));
return 1;
}
/* the following is used as both a method and attribute. As a method it defaults
to setting the value, because that's what it used to do before. */
WSLUA_METHOD TreeItem_set_hidden(lua_State *L) {
/* Marks the `TreeItem` as a hidden field (neither displayed nor used in filters).
This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
*/
#define WSLUA_OPTARG_TreeItem_set_hidden_BOOL 2 /* A Lua boolean, which if `true` sets the `TreeItem`
hidden flag, else clears it (default=true) */
TreeItem ti = checkTreeItem(L,1);
gboolean set = wslua_optbool(L, WSLUA_OPTARG_TreeItem_set_hidden_BOOL, TRUE);
if (set) {
PROTO_ITEM_SET_HIDDEN(ti->item);
} else {
PROTO_ITEM_SET_VISIBLE(ti->item);
}
/* copy the TreeItem userdata so we give it back */ /* copy the TreeItem userdata so we give it back */
lua_pushvalue(L, 1); lua_pushvalue(L, 1);
@ -664,6 +789,21 @@ WSLUA_METHOD TreeItem_set_hidden(lua_State *L) {
WSLUA_RETURN(1); /* The same TreeItem. */ WSLUA_RETURN(1); /* The same TreeItem. */
} }
/* WSLUA_ATTRIBUTE TreeItem_len RW Set/get `TreeItem`'s length inside tvb, after it has already been created.
@since 1.99.9
*/
static int TreeItem_get_len(lua_State* L) {
TreeItem ti = checkTreeItem(L,1);
int len = 0;
len = proto_item_get_len(ti->item);
lua_pushinteger(L, len > 0 ? len : 0);
return 1;
}
WSLUA_METHOD TreeItem_set_len(lua_State *L) { WSLUA_METHOD TreeItem_set_len(lua_State *L) {
/* Set `TreeItem`'s length inside tvb, after it has already been created. /* Set `TreeItem`'s length inside tvb, after it has already been created.
@ -681,6 +821,28 @@ WSLUA_METHOD TreeItem_set_len(lua_State *L) {
WSLUA_RETURN(1); /* The same TreeItem. */ WSLUA_RETURN(1); /* The same TreeItem. */
} }
WSLUA_METAMETHOD TreeItem__tostring(lua_State* L) {
/* Returns string debug information about the `TreeItem`.
@since 1.99.9
*/
TreeItem ti = toTreeItem(L,1);
if (ti) {
lua_pushfstring(L,
"TreeItem: expired=%s, has item=%s, has subtree=%s, they are %sthe same",
ti->expired ? "true" : "false",
ti->item ? "true" : "false",
ti->tree ? "true" : "false",
(ti->tree == ti->item) ? "" : "not ");
}
else {
lua_pushstring(L, "No TreeItem object!");
}
return 1;
}
/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
static int TreeItem__gc(lua_State* L) { static int TreeItem__gc(lua_State* L) {
TreeItem ti = toTreeItem(L,1); TreeItem ti = toTreeItem(L,1);
@ -692,6 +854,15 @@ static int TreeItem__gc(lua_State* L) {
return 0; return 0;
} }
WSLUA_ATTRIBUTES TreeItem_attributes[] = {
WSLUA_ATTRIBUTE_RWREG(TreeItem,generated),
WSLUA_ATTRIBUTE_RWREG(TreeItem,hidden),
WSLUA_ATTRIBUTE_RWREG(TreeItem,len),
WSLUA_ATTRIBUTE_RWREG(TreeItem,text),
WSLUA_ATTRIBUTE_ROREG(TreeItem,visible),
{ NULL, NULL, NULL }
};
WSLUA_METHODS TreeItem_methods[] = { WSLUA_METHODS TreeItem_methods[] = {
WSLUA_CLASS_FNREG(TreeItem,add_packet_field), WSLUA_CLASS_FNREG(TreeItem,add_packet_field),
WSLUA_CLASS_FNREG(TreeItem,add), WSLUA_CLASS_FNREG(TreeItem,add),
@ -709,12 +880,14 @@ WSLUA_METHODS TreeItem_methods[] = {
}; };
WSLUA_META TreeItem_meta[] = { WSLUA_META TreeItem_meta[] = {
WSLUA_CLASS_MTREG(TreeItem,tostring),
{ NULL, NULL } { NULL, NULL }
}; };
int TreeItem_register(lua_State *L) { int TreeItem_register(lua_State *L) {
gint* etts[] = { &wslua_ett }; gint* etts[] = { &wslua_ett };
WSLUA_REGISTER_CLASS(TreeItem); WSLUA_REGISTER_CLASS(TreeItem);
WSLUA_REGISTER_ATTRIBUTES(TreeItem);
outstanding_TreeItem = g_ptr_array_new(); outstanding_TreeItem = g_ptr_array_new();
proto_register_subtree_array(etts,1); proto_register_subtree_array(etts,1);
return 0; return 0;

View File

@ -563,6 +563,42 @@ WSLUA_METHOD Tvb_reported_length_remaining(lua_State* L) {
WSLUA_RETURN(1); /* The captured length of the `Tvb`. */ WSLUA_RETURN(1); /* The captured length of the `Tvb`. */
} }
WSLUA_METHOD Tvb_bytes(lua_State* L) {
/* Obtain a `ByteArray` from a `Tvb`.
@since 1.99.9
*/
#define WSLUA_OPTARG_Tvb_bytes_OFFSET 2 /* The offset (in octets) from the beginning of the `Tvb`. Defaults to 0. */
#define WSLUA_OPTARG_Tvb_bytes_LENGTH 3 /* The length (in octets) of the range. Defaults to until the end of the `Tvb`. */
Tvb tvb = checkTvb(L,1);
GByteArray* ba;
int offset = luaL_optint(L, WSLUA_OPTARG_Tvb_bytes_OFFSET, 0);
int len = luaL_optint(L,WSLUA_OPTARG_Tvb_bytes_LENGTH,-1);
if (tvb->expired) {
luaL_error(L,"expired tvb");
return 0;
}
ba = g_byte_array_new();
if (len < 0) {
len = tvb_captured_length_remaining(tvb->ws_tvb,offset);
if (len < 0) {
luaL_error(L,"out of bounds");
return 0;
}
} else if ( (guint)(len + offset) > tvb_captured_length(tvb->ws_tvb)) {
luaL_error(L,"Range is out of bounds");
return 0;
}
g_byte_array_append(ba, tvb_get_ptr(tvb->ws_tvb, offset, len), len);
pushByteArray(L,ba);
WSLUA_RETURN(1); /* The `ByteArray` object or nil. */
}
WSLUA_METHOD Tvb_offset(lua_State* L) { WSLUA_METHOD Tvb_offset(lua_State* L) {
/* Returns the raw offset (from the beginning of the source `Tvb`) of a sub `Tvb`. */ /* Returns the raw offset (from the beginning of the source `Tvb`) of a sub `Tvb`. */
Tvb tvb = checkTvb(L,1); Tvb tvb = checkTvb(L,1);
@ -674,7 +710,40 @@ WSLUA_METHOD Tvb_raw(lua_State* L) {
WSLUA_RETURN(1); /* A Lua string of the binary bytes in the `Tvb`. */ WSLUA_RETURN(1); /* A Lua string of the binary bytes in the `Tvb`. */
} }
WSLUA_METAMETHOD Tvb__eq(lua_State* L) {
/* Checks whether the two `Tvb` contents are equal.
@since 1.99.9
*/
Tvb tvb_l = checkTvb(L,1);
Tvb tvb_r = checkTvb(L,2);
int len_l = tvb_captured_length(tvb_l->ws_tvb);
int len_r = tvb_captured_length(tvb_r->ws_tvb);
/* it is not an error if their ds_tvb are different... they're just not equal */
if (len_l == len_r)
{
const gchar* lp = tvb_get_ptr(tvb_l->ws_tvb, 0, len_l);
const gchar* rp = tvb_get_ptr(tvb_r->ws_tvb, 0, len_r);
int i = 0;
for (; i < len_l; ++i) {
if (lp[i] != rp[i]) {
lua_pushboolean(L,0);
return 1;
}
}
lua_pushboolean(L,1);
} else {
lua_pushboolean(L,0);
}
return 1;
}
WSLUA_METHODS Tvb_methods[] = { WSLUA_METHODS Tvb_methods[] = {
WSLUA_CLASS_FNREG(Tvb,bytes),
WSLUA_CLASS_FNREG(Tvb,range), WSLUA_CLASS_FNREG(Tvb,range),
WSLUA_CLASS_FNREG(Tvb,len), WSLUA_CLASS_FNREG(Tvb,len),
WSLUA_CLASS_FNREG(Tvb,offset), WSLUA_CLASS_FNREG(Tvb,offset),
@ -685,6 +754,7 @@ WSLUA_METHODS Tvb_methods[] = {
}; };
WSLUA_META Tvb_meta[] = { WSLUA_META Tvb_meta[] = {
WSLUA_CLASS_MTREG(Tvb,eq),
WSLUA_CLASS_MTREG(Tvb,tostring), WSLUA_CLASS_MTREG(Tvb,tostring),
{"__call", Tvb_range}, {"__call", Tvb_range},
{ NULL, NULL } { NULL, NULL }
@ -722,13 +792,6 @@ WSLUA_METHOD TvbRange_uint(lua_State* L) {
case 4: case 4:
lua_pushnumber(L,tvb_get_ntohl(tvbr->tvb->ws_tvb,tvbr->offset)); lua_pushnumber(L,tvb_get_ntohl(tvbr->tvb->ws_tvb,tvbr->offset));
WSLUA_RETURN(1); /* The unsigned integer value. */ WSLUA_RETURN(1); /* The unsigned integer value. */
/*
* XXX:
* lua uses double so we have 52 bits to play with
* we are missing 5 and 6 byte integers within lua's range
* and 64 bit integers are not supported (there's a lib for
* lua that does).
*/
default: default:
luaL_error(L,"TvbRange:uint() does not handle %d byte integers",tvbr->len); luaL_error(L,"TvbRange:uint() does not handle %d byte integers",tvbr->len);
return 0; return 0;
@ -1576,6 +1639,36 @@ WSLUA_METHOD TvbRange_raw(lua_State* L) {
WSLUA_RETURN(1); /* A Lua string of the binary bytes in the `TvbRange`. */ WSLUA_RETURN(1); /* A Lua string of the binary bytes in the `TvbRange`. */
} }
WSLUA_METAMETHOD TvbRange__eq(lua_State* L) {
/* Checks whether the two `TvbRange` contents are equal.
@since 1.99.9
*/
TvbRange tvb_l = checkTvbRange(L,1);
TvbRange tvb_r = checkTvbRange(L,2);
/* it is not an error if their ds_tvb are different... they're just not equal */
if (tvb_l->len == tvb_r->len &&
tvb_l->len <= tvb_captured_length_remaining(tvb_l->tvb->ws_tvb, tvb_l->offset) &&
tvb_r->len <= tvb_captured_length_remaining(tvb_r->tvb->ws_tvb, tvb_r->offset))
{
const gchar* lp = tvb_get_ptr(tvb_l->tvb->ws_tvb, tvb_l->offset, tvb_l->len);
const gchar* rp = tvb_get_ptr(tvb_r->tvb->ws_tvb, tvb_r->offset, tvb_r->len);
int i = 0;
for (; i < tvb_r->len; ++i) {
if (lp[i] != rp[i]) {
lua_pushboolean(L,0);
return 1;
}
}
lua_pushboolean(L,1);
} else {
lua_pushboolean(L,0);
}
return 1;
}
WSLUA_METAMETHOD TvbRange__tostring(lua_State* L) { WSLUA_METAMETHOD TvbRange__tostring(lua_State* L) {
/* Converts the `TvbRange` into a string. Since the string gets truncated, /* Converts the `TvbRange` into a string. Since the string gets truncated,
@ -1635,6 +1728,7 @@ WSLUA_METHODS TvbRange_methods[] = {
WSLUA_META TvbRange_meta[] = { WSLUA_META TvbRange_meta[] = {
WSLUA_CLASS_MTREG(TvbRange,tostring), WSLUA_CLASS_MTREG(TvbRange,tostring),
WSLUA_CLASS_MTREG(wslua,concat), WSLUA_CLASS_MTREG(wslua,concat),
WSLUA_CLASS_MTREG(TvbRange,eq),
{"__call", TvbRange_range}, {"__call", TvbRange_range},
{ NULL, NULL } { NULL, NULL }
}; };

View File

@ -72,6 +72,18 @@ local f_bootp_opt = Field.new("bootp.option.type")
test("Field__tostring-1", tostring(f_frame_proto) == "frame.protocols") test("Field__tostring-1", tostring(f_frame_proto) == "frame.protocols")
test("Field.name-1", f_frame_proto.name == "frame.protocols")
test("Field.name-2", f_eth_src.name == "eth.src")
test("Field.display-1", f_frame_proto.display == "Protocols in frame")
test("Field.display-2", f_eth_src.display == "Source")
test("Field.type-1", f_frame_proto.type == ftypes.STRING)
test("Field.type-2", f_eth_src.type == ftypes.ETHER)
test("Field.type-3", f_ip_src.type == ftypes.IPv4)
test("Field.type-4", f_udp_srcport.type == ftypes.UINT16)
test("Field.type-5", f_bootp_opt.type == ftypes.UINT8)
-- make sure can't create a FieldInfo outside tap -- make sure can't create a FieldInfo outside tap
test("Field__call-1",not pcall(makeFieldInfo,f_eth_src)) test("Field__call-1",not pcall(makeFieldInfo,f_eth_src))
@ -90,11 +102,33 @@ function tap.packet(pinfo,tvb)
test("Field__call-2",pcall(makeFieldInfo,f_eth_src)) test("Field__call-2",pcall(makeFieldInfo,f_eth_src))
test("Field.name-3", f_frame_proto.name == "frame.protocols")
test("Field.name-4", f_eth_src.name == "eth.src")
test("Field.display-3", f_frame_proto.display == "Protocols in frame")
test("Field.display-4", f_eth_src.display == "Source")
test("Field.type-6", f_frame_proto.type == ftypes.STRING)
test("Field.type-7", f_eth_src.type == ftypes.ETHER)
test("Field.type-8", f_ip_src.type == ftypes.IPv4)
test("Field.type-9", f_udp_srcport.type == ftypes.UINT16)
test("Field.type-10", f_bootp_opt.type == ftypes.UINT8)
testing("FieldInfo") testing("FieldInfo")
local finfo_udp_srcport = f_udp_srcport()
test("FieldInfo.name-1", finfo_udp_srcport.name == "udp.srcport")
test("FieldInfo.type-1", finfo_udp_srcport.type == ftypes.UINT16)
test("FieldInfo.little_endian-1", finfo_udp_srcport.little_endian == false)
-- the following should be true, but UDP doesn't set it right?
-- test("FieldInfo.big_endian-1", finfo_udp_srcport.big_endian == true)
test("FieldInfo.is_url-1", finfo_udp_srcport.is_url == false)
test("FieldInfo.offset-1", finfo_udp_srcport.offset == 34)
test("FieldInfo.source-1", finfo_udp_srcport.source == tvb)
-- check ether addr -- check ether addr
local fi_eth_src = f_eth_src() local fi_eth_src = f_eth_src()
test("FieldInfo.type-2", fi_eth_src.type == ftypes.ETHER)
test("FieldInfo.range-0",pcall(getFieldInfo,fi_eth_src,"range")) test("FieldInfo.range-0",pcall(getFieldInfo,fi_eth_src,"range"))
local eth_macs = { f_eth_mac() } local eth_macs = { f_eth_mac() }
local eth_src1 = tostring(f_eth_src().range) local eth_src1 = tostring(f_eth_src().range)