Adds some Lua helper functions: some commonly used functions, and to help troubleshooting Lua scripts
There are some common things people need to do, such as convert to/from hex or get the raw binary string in a ByteArray/Tvb/TvbRange. These have been added, as well as some tests for them in the testsuites. Also, functions have been added to allow a script to get all the available tap types and filter fields, since they are not exactly what one can see in the Wireshark gui. Change-Id: I92e5e4eae713bb90d79b0c024eaa4e55b99cc96b Reviewed-on: https://code.wireshark.org/review/249 Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
This commit is contained in:
parent
907a825986
commit
860747e1e7
|
@ -2124,6 +2124,15 @@ dissector_handle_get_protocol_index(const dissector_handle_t handle)
|
|||
return proto_get_id(handle->protocol);
|
||||
}
|
||||
|
||||
/* Get a GList of all registered dissector names. The content of the list
|
||||
is owned by the hash table and should not be modified or freed.
|
||||
Use g_list_free() when done using the list. */
|
||||
GList*
|
||||
get_dissector_names()
|
||||
{
|
||||
return g_hash_table_get_keys(registered_dissectors);
|
||||
}
|
||||
|
||||
/* Find a registered dissector by name. */
|
||||
dissector_handle_t
|
||||
find_dissector(const char *name)
|
||||
|
|
|
@ -414,6 +414,9 @@ WS_DLL_PUBLIC const char *dissector_handle_get_short_name(const dissector_handle
|
|||
/* Get the index of the protocol for a dissector handle. */
|
||||
WS_DLL_PUBLIC int dissector_handle_get_protocol_index(const dissector_handle_t handle);
|
||||
|
||||
/* Get a GList of all registered dissector names. */
|
||||
GList* get_dissector_names();
|
||||
|
||||
/* Find a dissector by name. */
|
||||
WS_DLL_PUBLIC dissector_handle_t find_dissector(const char *name);
|
||||
|
||||
|
|
14
epan/tap.c
14
epan/tap.c
|
@ -421,7 +421,21 @@ draw_tap_listeners(gboolean draw_all)
|
|||
}
|
||||
}
|
||||
|
||||
/* Gets a GList of the tap names. The content of the list
|
||||
is owned by the tap table and should not be modified or freed.
|
||||
Use g_list_free() when done using the list. */
|
||||
GList*
|
||||
get_tap_names()
|
||||
{
|
||||
GList *list = NULL;
|
||||
tap_dissector_t *td;
|
||||
|
||||
for(td=tap_dissector_list; td; td=td->next) {
|
||||
list = g_list_prepend(list, td->name);
|
||||
}
|
||||
|
||||
return g_list_reverse(list);
|
||||
}
|
||||
|
||||
/* **********************************************************************
|
||||
* Functions used by tap to
|
||||
|
|
|
@ -78,6 +78,9 @@ extern void tap_init(void);
|
|||
*/
|
||||
WS_DLL_PUBLIC int register_tap(const char *name);
|
||||
|
||||
/* Gets a GList of the tap names */
|
||||
GList* get_tap_names();
|
||||
|
||||
/** This function will return the tap_id for the specific protocol tap
|
||||
* or 0 if no such tap was found.
|
||||
*/
|
||||
|
|
|
@ -572,4 +572,7 @@ extern int wslua_set_tap_enums(lua_State* L);
|
|||
|
||||
extern int wslua_is_field_available(lua_State* L, const char* field_abbr);
|
||||
|
||||
extern int wslua_bin2hex(lua_State* L, const guint8* data, const guint len, const gboolean lowercase, const gchar* sep);
|
||||
extern int wslua_hex2bin(lua_State* L, const char* data, const guint len, const gchar* sep);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -495,6 +495,34 @@ WSLUA_CONSTRUCTOR Field_new(lua_State *L) {
|
|||
WSLUA_RETURN(1); /* The field extractor */
|
||||
}
|
||||
|
||||
WSLUA_CONSTRUCTOR Field_list(lua_State *L) {
|
||||
/* Gets a Lua array table of all registered field filter names.
|
||||
NOTE: this is an expensive operation, and should only be used for troubleshooting. */
|
||||
void *cookie, *cookie2;
|
||||
int i = -1;
|
||||
int count = 0;
|
||||
header_field_info *hfinfo = NULL;
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
for (i = proto_get_first_protocol(&cookie); i != -1;
|
||||
i = proto_get_next_protocol(&cookie)) {
|
||||
|
||||
for (hfinfo = proto_get_first_protocol_field(i, &cookie2); hfinfo != NULL;
|
||||
hfinfo = proto_get_next_protocol_field(&cookie2)) {
|
||||
|
||||
if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
|
||||
continue;
|
||||
|
||||
count++;
|
||||
lua_pushstring(L,hfinfo->abbrev);
|
||||
lua_rawseti(L,1,count);
|
||||
}
|
||||
}
|
||||
|
||||
WSLUA_RETURN(1); /* The array table of field filter names */
|
||||
}
|
||||
|
||||
WSLUA_METAMETHOD Field__call (lua_State* L) {
|
||||
/* Obtain all values (see FieldInfo) for this field. */
|
||||
Field f = checkField(L,1);
|
||||
|
@ -549,6 +577,7 @@ static int Field__gc(lua_State* L _U_) {
|
|||
|
||||
WSLUA_METHODS Field_methods[] = {
|
||||
WSLUA_CLASS_FNREG(Field,new),
|
||||
WSLUA_CLASS_FNREG(Field,list),
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -230,6 +230,35 @@ WSLUA_CONSTRUCTOR Listener_new(lua_State* L) {
|
|||
WSLUA_RETURN(1); /* The newly created Listener listener object */
|
||||
}
|
||||
|
||||
/* Allow dissector key names to be sorted alphabetically */
|
||||
static gint
|
||||
compare_dissector_key_name(gconstpointer dissector_a, gconstpointer dissector_b)
|
||||
{
|
||||
return strcmp((const char*)dissector_a, (const char*)dissector_b);
|
||||
}
|
||||
|
||||
WSLUA_CONSTRUCTOR Listener_list (lua_State *L) {
|
||||
/* Gets a Lua array table of all registered Listener tap names.
|
||||
NOTE: this is an expensive operation, and should only be used for troubleshooting. */
|
||||
GList* list = get_tap_names();
|
||||
GList* elist = NULL;
|
||||
int i = 1;
|
||||
|
||||
if (!list) return luaL_error(L,"Cannot retrieve tap name list");
|
||||
|
||||
list = g_list_sort(list, (GCompareFunc)compare_dissector_key_name);
|
||||
elist = g_list_first(list);
|
||||
|
||||
lua_newtable(L);
|
||||
for (i=1; elist; i++, elist = g_list_next(elist)) {
|
||||
lua_pushstring(L,(const char *) elist->data);
|
||||
lua_rawseti(L,1,i);
|
||||
}
|
||||
|
||||
g_list_free(list);
|
||||
WSLUA_RETURN(1); /* The array table of registered tap names */
|
||||
}
|
||||
|
||||
WSLUA_METHOD Listener_remove(lua_State* L) {
|
||||
/* Removes a tap listener */
|
||||
Listener tap = checkListener(L,1);
|
||||
|
@ -292,6 +321,7 @@ WSLUA_ATTRIBUTES Listener_attributes[] = {
|
|||
WSLUA_METHODS Listener_methods[] = {
|
||||
WSLUA_CLASS_FNREG(Listener,new),
|
||||
WSLUA_CLASS_FNREG(Listener,remove),
|
||||
WSLUA_CLASS_FNREG(Listener,list),
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -1683,6 +1683,35 @@ WSLUA_CONSTRUCTOR Dissector_get (lua_State *L) {
|
|||
WSLUA_ARG_ERROR(Dissector_get,NAME,"No such dissector");
|
||||
}
|
||||
|
||||
/* Allow dissector key names to be sorted alphabetically */
|
||||
static gint
|
||||
compare_dissector_key_name(gconstpointer dissector_a, gconstpointer dissector_b)
|
||||
{
|
||||
return strcmp((const char*)dissector_a, (const char*)dissector_b);
|
||||
}
|
||||
|
||||
WSLUA_CONSTRUCTOR Dissector_list (lua_State *L) {
|
||||
/* Gets a Lua array table of all registered Dissector names.
|
||||
NOTE: this is an expensive operation, and should only be used for troubleshooting. */
|
||||
GList* list = get_dissector_names();
|
||||
GList* elist = NULL;
|
||||
int i = 1;
|
||||
|
||||
if (!list) return luaL_error(L,"Cannot retrieve Dissector name list");
|
||||
|
||||
list = g_list_sort(list, (GCompareFunc)compare_dissector_key_name);
|
||||
elist = g_list_first(list);
|
||||
|
||||
lua_newtable(L);
|
||||
for (i=1; elist; i++, elist = g_list_next(elist)) {
|
||||
lua_pushstring(L,(const char *) elist->data);
|
||||
lua_rawseti(L,1,i);
|
||||
}
|
||||
|
||||
g_list_free(list);
|
||||
WSLUA_RETURN(1); /* The array table of registered dissector names */
|
||||
}
|
||||
|
||||
WSLUA_METHOD Dissector_call(lua_State* L) {
|
||||
/* Calls a dissector against a given packet (or part of it) */
|
||||
#define WSLUA_ARG_Dissector_call_TVB 2 /* The buffer to dissect */
|
||||
|
@ -1727,6 +1756,7 @@ static int Dissector__gc(lua_State* L _U_) {
|
|||
WSLUA_METHODS Dissector_methods[] = {
|
||||
WSLUA_CLASS_FNREG(Dissector,get),
|
||||
WSLUA_CLASS_FNREG(Dissector,call),
|
||||
WSLUA_CLASS_FNREG(Dissector,list),
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -274,10 +274,10 @@ static void correctbytes (gchar *b, int size, int endian) {
|
|||
|
||||
WSLUA_CONSTRUCTOR Struct_pack (lua_State *L) {
|
||||
/* Returns a string containing the values arg1, arg2, etc. packed/encoded according to the format string. */
|
||||
#define WSLUA_ARG_Struct_unpack_FORMAT 1 /* The format string */
|
||||
#define WSLUA_ARG_Struct_unpack_STRUCT 2 /* One or more Lua value(s) to encode, based on the given format. */
|
||||
#define WSLUA_ARG_Struct_pack_FORMAT 1 /* The format string */
|
||||
#define WSLUA_ARG_Struct_pack_STRUCT 2 /* One or more Lua value(s) to encode, based on the given format. */
|
||||
luaL_Buffer b;
|
||||
const char *fmt = luaL_checkstring(L, WSLUA_ARG_Struct_unpack_FORMAT);
|
||||
const char *fmt = luaL_checkstring(L, WSLUA_ARG_Struct_pack_FORMAT);
|
||||
Header h;
|
||||
int poscnt = 0;
|
||||
int posBuf[10];
|
||||
|
@ -350,7 +350,7 @@ WSLUA_CONSTRUCTOR Struct_pack (lua_State *L) {
|
|||
luaL_pushresult(&b);
|
||||
for (arg = 0; arg < poscnt; arg++)
|
||||
lua_pushinteger(L, posBuf[arg]);
|
||||
return poscnt + 1;
|
||||
WSLUA_RETURN(poscnt + 1); /* The packed binary Lua string, plus any positions due to '=' being used in format. */
|
||||
}
|
||||
|
||||
/* Decodes an integer from a string struct into a Lua number, based on
|
||||
|
@ -476,14 +476,15 @@ WSLUA_CONSTRUCTOR Struct_unpack (lua_State *L) {
|
|||
pos += size;
|
||||
}
|
||||
lua_pushinteger(L, pos + 1);
|
||||
return lua_gettop(L) - 2;
|
||||
WSLUA_RETURN(lua_gettop(L) - 2); /* One or more values based on format, plus the posoition it stopped unpacking. */
|
||||
}
|
||||
|
||||
|
||||
WSLUA_CONSTRUCTOR Struct_size (lua_State *L) {
|
||||
/* Returns the length of the binary string struct that would be consumed/handled by the given format string. */
|
||||
#define WSLUA_ARG_Struct_size_FORMAT 1 /* The format string */
|
||||
Header h;
|
||||
const gchar *fmt = luaL_checkstring(L, 1);
|
||||
const gchar *fmt = luaL_checkstring(L, WSLUA_ARG_Struct_size_FORMAT);
|
||||
size_t pos = 0;
|
||||
defaultoptions(&h);
|
||||
while (*fmt) {
|
||||
|
@ -499,7 +500,48 @@ WSLUA_CONSTRUCTOR Struct_size (lua_State *L) {
|
|||
pos += size;
|
||||
}
|
||||
lua_pushinteger(L, pos);
|
||||
return 1;
|
||||
WSLUA_RETURN(1); /* The size number */
|
||||
}
|
||||
|
||||
WSLUA_CONSTRUCTOR Struct_tohex (lua_State *L) {
|
||||
/* Converts the passed-in binary string to a hex-ascii string. */
|
||||
#define WSLUA_ARG_Struct_tohex_BYTESTRING 1 /* A Lua string consisting of binary bytes */
|
||||
#define WSLUA_OPTARG_Struct_tohex_LOWERCASE 2 /* True to use lower-case hex characters (default=false). */
|
||||
#define WSLUA_OPTARG_Struct_tohex_SEPARATOR 3 /* A string separator to insert between hex bytes (default=nil). */
|
||||
const gchar* s = NULL;
|
||||
size_t len = 0;
|
||||
gboolean lowercase = FALSE;
|
||||
const gchar* sep = NULL;
|
||||
|
||||
s = luaL_checklstring(L,WSLUA_ARG_Struct_tohex_BYTESTRING,&len);
|
||||
|
||||
if (!s)
|
||||
WSLUA_ARG_ERROR(Struct_tohex,BYTESTRING,"must be a Lua string");
|
||||
|
||||
lowercase = wslua_optbool(L,WSLUA_OPTARG_Struct_tohex_LOWERCASE,FALSE);
|
||||
sep = luaL_optstring(L,WSLUA_OPTARG_Struct_tohex_SEPARATOR,NULL);
|
||||
|
||||
wslua_bin2hex(L, s, (guint)len, lowercase, sep);
|
||||
WSLUA_RETURN(1); /* The Lua hex-ascii string */
|
||||
}
|
||||
|
||||
WSLUA_CONSTRUCTOR Struct_fromhex (lua_State *L) {
|
||||
/* Converts the passed-in hex-ascii string to a binary string. */
|
||||
#define WSLUA_ARG_Struct_fromhex_HEXBYTES 1 /* A string consisting of hexadecimal bytes like "00 B1 A2" or "1a2b3c4d" */
|
||||
#define WSLUA_OPTARG_Struct_fromhex_SEPARATOR 2 /* A string separator between hex bytes/words (default=" "). */
|
||||
const gchar* s = NULL;
|
||||
size_t len = 0;
|
||||
const gchar* sep = NULL;
|
||||
|
||||
s = luaL_checklstring(L,WSLUA_ARG_Struct_fromhex_HEXBYTES,&len);
|
||||
|
||||
if (!s)
|
||||
WSLUA_ARG_ERROR(Struct_tohex,BYTESTRING,"must be a Lua string");
|
||||
|
||||
sep = luaL_optstring(L,WSLUA_OPTARG_Struct_fromhex_SEPARATOR,NULL);
|
||||
|
||||
wslua_hex2bin(L, s, (guint)len, sep);
|
||||
WSLUA_RETURN(1); /* The Lua binary string */
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
@ -510,9 +552,11 @@ static int Struct__gc(lua_State* L _U_) {
|
|||
}
|
||||
|
||||
WSLUA_METHODS Struct_methods[] = {
|
||||
{"pack", Struct_pack},
|
||||
{"unpack", Struct_unpack},
|
||||
{"size", Struct_size},
|
||||
WSLUA_CLASS_FNREG(Struct,pack),
|
||||
WSLUA_CLASS_FNREG(Struct,unpack),
|
||||
WSLUA_CLASS_FNREG(Struct,size),
|
||||
WSLUA_CLASS_FNREG(Struct,tohex),
|
||||
WSLUA_CLASS_FNREG(Struct,fromhex),
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -41,39 +41,34 @@ WSLUA_CLASS_DEFINE(ByteArray,FAIL_ON_NULL("ByteArray"),NOP);
|
|||
|
||||
WSLUA_CONSTRUCTOR ByteArray_new(lua_State* L) { /* Creates a ByteArray Object */
|
||||
#define WSLUA_OPTARG_ByteArray_new_HEXBYTES 1 /* A string consisting of hexadecimal bytes like "00 B1 A2" or "1a2b3c4d" */
|
||||
#define WSLUA_OPTARG_ByteArray_new_SEPARATOR 2 /* A string separator between hex bytes/words (default=" "); or if the boolean value 'true' is used, then the first arg is treated as raw binary data */
|
||||
GByteArray* ba = g_byte_array_new();
|
||||
const gchar* s;
|
||||
int nibble[2];
|
||||
int i = 0;
|
||||
gchar c;
|
||||
size_t len = 0;
|
||||
const gchar* sep = " ";
|
||||
gboolean ishex = TRUE;
|
||||
|
||||
if (lua_gettop(L) == 1) {
|
||||
s = luaL_checkstring(L,WSLUA_OPTARG_ByteArray_new_HEXBYTES);
|
||||
if (lua_gettop(L) >= 1) {
|
||||
s = luaL_checklstring(L,WSLUA_OPTARG_ByteArray_new_HEXBYTES,&len);
|
||||
|
||||
if (!s)
|
||||
WSLUA_OPTARG_ERROR(ByteArray_new,HEXBYTES,"must be a string");
|
||||
|
||||
/* XXX: slow! */
|
||||
for (; (c = *s); s++) {
|
||||
switch(c) {
|
||||
case '0': case '1': case '2': case '3': case '4': case '5' : case '6' : case '7': case '8' : case '9' :
|
||||
nibble[(i++)%2] = c - '0';
|
||||
break;
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f' :
|
||||
nibble[(i++)%2] = c - 'a' + 0xa;
|
||||
break;
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F' :
|
||||
nibble[(i++)%2] = c - 'A' + 0xa;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (lua_gettop(L) >= 2) {
|
||||
if (lua_type(L,2) == LUA_TBOOLEAN && lua_toboolean(L,2)) {
|
||||
ishex = FALSE;
|
||||
} else {
|
||||
sep = luaL_optstring(L,WSLUA_OPTARG_ByteArray_new_SEPARATOR," ");
|
||||
}
|
||||
}
|
||||
|
||||
if ( i == 2 ) {
|
||||
guint8 b = (guint8)(nibble[0] * 16 + nibble[1]);
|
||||
g_byte_array_append(ba,&b,1);
|
||||
i = 0;
|
||||
}
|
||||
if (ishex) {
|
||||
wslua_hex2bin(L, s, (guint)len, sep); /* this pushes a new string on top of stack */
|
||||
s = luaL_checklstring(L, -1, &len); /* get the new binary string */
|
||||
g_byte_array_append(ba,s,(guint)len); /* copy it into ByteArray */
|
||||
lua_pop(L,1); /* pop the newly created string */
|
||||
} else {
|
||||
g_byte_array_append(ba,s,(guint)len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,8 +206,8 @@ WSLUA_METHOD ByteArray_len(lua_State* L) {
|
|||
}
|
||||
|
||||
WSLUA_METHOD ByteArray_subset(lua_State* L) {
|
||||
/* Obtain a segment of a ByteArray */
|
||||
#define WSLUA_ARG_ByteArray_set_index_OFFSET 2 /* The position of the first byte */
|
||||
/* Obtain a segment of a ByteArray, as a new ByteArray. */
|
||||
#define WSLUA_ARG_ByteArray_set_index_OFFSET 2 /* The position of the first byte (0=first) */
|
||||
#define WSLUA_ARG_ByteArray_set_index_LENGTH 3 /* The length of the segment */
|
||||
ByteArray ba = checkByteArray(L,1);
|
||||
int offset = luaL_checkint(L,WSLUA_ARG_ByteArray_set_index_OFFSET);
|
||||
|
@ -252,42 +247,54 @@ WSLUA_METHOD ByteArray_base64_decode(lua_State* L) {
|
|||
WSLUA_RETURN(1); /* The created ByteArray. */
|
||||
}
|
||||
|
||||
WSLUA_METAMETHOD ByteArray__tostring(lua_State* L) {
|
||||
/* Obtain a string containing the bytes in a ByteArray so that it can be used in display filters (e.g. "01FE456789AB") */
|
||||
static const char byte_to_str[][3] = {
|
||||
"00","01","02","03","04","05","06","07","08","09","0A","0B","0C","0D","0E","0F",
|
||||
"10","11","12","13","14","15","16","17","18","19","1A","1B","1C","1D","1E","1F",
|
||||
"20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F",
|
||||
"30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3D","3E","3F",
|
||||
"40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F",
|
||||
"50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F",
|
||||
"60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F",
|
||||
"70","71","72","73","74","75","76","77","78","79","7A","7B","7C","7D","7E","7F",
|
||||
"80","81","82","83","84","85","86","87","88","89","8A","8B","8C","8D","8E","8F",
|
||||
"90","91","92","93","94","95","96","97","98","99","9A","9B","9C","9D","9E","9F",
|
||||
"A0","A1","A2","A3","A4","A5","A6","A7","A8","A9","AA","AB","AC","AD","AE","AF",
|
||||
"B0","B1","B2","B3","B4","B5","B6","B7","B8","B9","BA","BB","BC","BD","BE","BF",
|
||||
"C0","C1","C2","C3","C4","C5","C6","C7","C8","C9","CA","CB","CC","CD","CE","CF",
|
||||
"D0","D1","D2","D3","D4","D5","D6","D7","D8","D9","DA","DB","DC","DD","DE","DF",
|
||||
"E0","E1","E2","E3","E4","E5","E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
|
||||
"F0","F1","F2","F3","F4","F5","F6","F7","F8","F9","FA","FB","FC","FD","FE","FF"
|
||||
};
|
||||
WSLUA_METHOD ByteArray_raw(lua_State* L) {
|
||||
/* Obtain a Lua string of the binary bytes in a ByteArray. */
|
||||
#define WSLUA_OPTARG_ByteArray_raw_OFFSET 2 /* The position of the first byte (default=0/first). */
|
||||
#define WSLUA_OPTARG_ByteArray_raw_LENGTH 3 /* The length of the segment to get (default=all). */
|
||||
ByteArray ba = checkByteArray(L,1);
|
||||
int i;
|
||||
GString* s;
|
||||
guint offset = (guint) luaL_optint(L,WSLUA_OPTARG_ByteArray_raw_OFFSET,0);
|
||||
int len;
|
||||
|
||||
if (!ba) return 0;
|
||||
if (offset > ba->len)
|
||||
WSLUA_OPTARG_ERROR(ByteArray_raw,OFFSET,"offset beyond end of byte array");
|
||||
|
||||
len = luaL_optint(L,WSLUA_OPTARG_ByteArray_raw_LENGTH, ba->len - offset);
|
||||
if ((len < 0) || ((guint)len > (ba->len - offset)))
|
||||
len = ba->len - offset;
|
||||
|
||||
lua_pushlstring(L, &(ba->data[offset]), len);
|
||||
|
||||
WSLUA_RETURN(1); /* A Lua string of the binary bytes in the ByteArray. */
|
||||
}
|
||||
|
||||
WSLUA_METHOD ByteArray_tohex(lua_State* L) {
|
||||
/* Obtain a Lua string of the bytes in a ByteArray as hex-ascii, with given separator */
|
||||
#define WSLUA_OPTARG_ByteArray_tohex_LOWERCASE 2 /* True to use lower-case hex characters (default=false). */
|
||||
#define WSLUA_OPTARG_ByteArray_tohex_SEPARATOR 3 /* A string separator to insert between hex bytes (default=nil). */
|
||||
ByteArray ba = checkByteArray(L,1);
|
||||
gboolean lowercase = FALSE;
|
||||
const gchar* sep = NULL;
|
||||
|
||||
if (!ba) return 0;
|
||||
|
||||
s = g_string_new("");
|
||||
lowercase = wslua_optbool(L,WSLUA_OPTARG_ByteArray_tohex_LOWERCASE,FALSE);
|
||||
sep = luaL_optstring(L,WSLUA_OPTARG_ByteArray_tohex_SEPARATOR,NULL);
|
||||
|
||||
for (i = 0; i < (int)ba->len; i++) {
|
||||
g_string_append(s,byte_to_str[(ba->data)[i]]);
|
||||
}
|
||||
wslua_bin2hex(L, ba->data, ba->len, lowercase, sep);
|
||||
|
||||
lua_pushstring(L,s->str);
|
||||
g_string_free(s,TRUE);
|
||||
WSLUA_RETURN(1); /* A hex-ascii string representation of the ByteArray. */
|
||||
}
|
||||
|
||||
WSLUA_RETURN(1); /* A hex-ascii string containing a representation of the ByteArray. */
|
||||
WSLUA_METAMETHOD ByteArray__tostring(lua_State* L) {
|
||||
/* Obtain a Lua string containing the bytes in a ByteArray so that it can be used in display filters (e.g. "01FE456789AB") */
|
||||
ByteArray ba = checkByteArray(L,1);
|
||||
|
||||
if (!ba) return 0;
|
||||
|
||||
wslua_bin2hex(L, ba->data, ba->len, FALSE, NULL);
|
||||
|
||||
WSLUA_RETURN(1); /* A hex-ascii string representation of the ByteArray. */
|
||||
}
|
||||
|
||||
static int ByteArray_tvb (lua_State *L);
|
||||
|
@ -303,6 +310,8 @@ WSLUA_METHODS ByteArray_methods[] = {
|
|||
WSLUA_CLASS_FNREG(ByteArray,base64_decode),
|
||||
WSLUA_CLASS_FNREG(ByteArray,get_index),
|
||||
WSLUA_CLASS_FNREG(ByteArray,set_index),
|
||||
WSLUA_CLASS_FNREG(ByteArray,tohex),
|
||||
WSLUA_CLASS_FNREG(ByteArray,raw),
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -434,7 +443,7 @@ WSLUA_CONSTRUCTOR ByteArray_tvb (lua_State *L) {
|
|||
}
|
||||
|
||||
WSLUA_CONSTRUCTOR TvbRange_tvb (lua_State *L) {
|
||||
/* Creates a (sub)Tvb from using a TvbRange */
|
||||
/* Creates a (sub)Tvb from a TvbRange */
|
||||
#define WSLUA_ARG_Tvb_new_subset_RANGE 1 /* The TvbRange from which to create the new Tvb. */
|
||||
|
||||
TvbRange tvbr = checkTvbRange(L,WSLUA_ARG_Tvb_new_subset_RANGE);
|
||||
|
@ -579,12 +588,46 @@ WSLUA_METHOD Tvb_range(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
WSLUA_METHOD Tvb_raw(lua_State* L) {
|
||||
/* Obtain a Lua string of the binary bytes in a Tvb. */
|
||||
#define WSLUA_OPTARG_Tvb_raw_OFFSET 2 /* The position of the first byte (default=0/first). */
|
||||
#define WSLUA_OPTARG_Tvb_raw_LENGTH 3 /* The length of the segment to get (default=all). */
|
||||
Tvb tvb = checkTvb(L,1);
|
||||
int offset = luaL_optint(L,WSLUA_OPTARG_Tvb_raw_OFFSET,0);
|
||||
int len = luaL_optint(L,WSLUA_OPTARG_Tvb_raw_LENGTH,-1);
|
||||
|
||||
if (!tvb) return 0;
|
||||
if (tvb->expired) {
|
||||
luaL_error(L,"expired tvb");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((guint)offset > tvb_length(tvb->ws_tvb))
|
||||
WSLUA_OPTARG_ERROR(Tvb_raw,OFFSET,"offset beyond end of Tvb");
|
||||
|
||||
if (len == -1) {
|
||||
len = tvb_length_remaining(tvb->ws_tvb,offset);
|
||||
if (len < 0) {
|
||||
luaL_error(L,"out of bounds");
|
||||
return FALSE;
|
||||
}
|
||||
} else if ( (guint)(len + offset) > tvb_length(tvb->ws_tvb)) {
|
||||
luaL_error(L,"Range is out of bounds");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lua_pushlstring(L, tvb_get_ptr(tvb->ws_tvb, offset, len), len);
|
||||
|
||||
WSLUA_RETURN(1); /* A Lua string of the binary bytes in the Tvb. */
|
||||
}
|
||||
|
||||
WSLUA_METHODS Tvb_methods[] = {
|
||||
WSLUA_CLASS_FNREG(Tvb,range),
|
||||
WSLUA_CLASS_FNREG(Tvb,len),
|
||||
WSLUA_CLASS_FNREG(Tvb,offset),
|
||||
WSLUA_CLASS_FNREG(Tvb,reported_len),
|
||||
WSLUA_CLASS_FNREG(Tvb,reported_length_remaining),
|
||||
WSLUA_CLASS_FNREG(Tvb,raw),
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -1360,6 +1403,39 @@ WSLUA_METHOD TvbRange_offset(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
WSLUA_METHOD TvbRange_raw(lua_State* L) {
|
||||
/* Obtain a Lua string of the binary bytes in a TvbRange. */
|
||||
#define WSLUA_OPTARG_TvbRange_raw_OFFSET 2 /* The position of the first byte (default=0/first). */
|
||||
#define WSLUA_OPTARG_TvbRange_raw_LENGTH 3 /* The length of the segment to get (default=all). */
|
||||
TvbRange tvbr = checkTvbRange(L,1);
|
||||
int offset = luaL_optint(L,WSLUA_OPTARG_TvbRange_raw_OFFSET,0);
|
||||
int len = luaL_optint(L,WSLUA_OPTARG_TvbRange_raw_LENGTH,-1);
|
||||
|
||||
if (!tvbr || !tvbr->tvb) return 0;
|
||||
if (tvbr->tvb->expired) {
|
||||
luaL_error(L,"expired tvb");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((guint)offset > tvb_length(tvbr->tvb->ws_tvb))
|
||||
WSLUA_OPTARG_ERROR(Tvb_raw,OFFSET,"offset beyond end of Tvb");
|
||||
|
||||
if (len == -1) {
|
||||
len = tvb_length_remaining(tvbr->tvb->ws_tvb,offset);
|
||||
if (len < 0) {
|
||||
luaL_error(L,"out of bounds");
|
||||
return FALSE;
|
||||
}
|
||||
} else if ( (guint)(len + offset) > tvb_length(tvbr->tvb->ws_tvb)) {
|
||||
luaL_error(L,"Range is out of bounds");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lua_pushlstring(L, tvb_get_ptr(tvbr->tvb->ws_tvb, offset, len), len);
|
||||
|
||||
WSLUA_RETURN(1); /* A Lua string of the binary bytes in the TvbRange. */
|
||||
}
|
||||
|
||||
|
||||
WSLUA_METAMETHOD TvbRange__tostring(lua_State* L) {
|
||||
/* Converts the TvbRange into a string. As the string gets truncated
|
||||
|
@ -1407,6 +1483,7 @@ WSLUA_METHODS TvbRange_methods[] = {
|
|||
WSLUA_CLASS_FNREG(TvbRange,le_ustringz),
|
||||
WSLUA_CLASS_FNREG(TvbRange,ustringz),
|
||||
WSLUA_CLASS_FNREG(TvbRange,uncompress),
|
||||
WSLUA_CLASS_FNREG(TvbRange,raw),
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -432,6 +432,114 @@ WSLUA_FUNCTION wslua_register_stat_cmd_arg(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Pushes a hex string of the binary data argument. */
|
||||
int wslua_bin2hex(lua_State* L, const guint8* data, const guint len, const gboolean lowercase, const gchar* sep) {
|
||||
luaL_Buffer b;
|
||||
guint i = 0;
|
||||
static const char byte_to_str_upper[256][3] = {
|
||||
"00","01","02","03","04","05","06","07","08","09","0A","0B","0C","0D","0E","0F",
|
||||
"10","11","12","13","14","15","16","17","18","19","1A","1B","1C","1D","1E","1F",
|
||||
"20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F",
|
||||
"30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3D","3E","3F",
|
||||
"40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F",
|
||||
"50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F",
|
||||
"60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F",
|
||||
"70","71","72","73","74","75","76","77","78","79","7A","7B","7C","7D","7E","7F",
|
||||
"80","81","82","83","84","85","86","87","88","89","8A","8B","8C","8D","8E","8F",
|
||||
"90","91","92","93","94","95","96","97","98","99","9A","9B","9C","9D","9E","9F",
|
||||
"A0","A1","A2","A3","A4","A5","A6","A7","A8","A9","AA","AB","AC","AD","AE","AF",
|
||||
"B0","B1","B2","B3","B4","B5","B6","B7","B8","B9","BA","BB","BC","BD","BE","BF",
|
||||
"C0","C1","C2","C3","C4","C5","C6","C7","C8","C9","CA","CB","CC","CD","CE","CF",
|
||||
"D0","D1","D2","D3","D4","D5","D6","D7","D8","D9","DA","DB","DC","DD","DE","DF",
|
||||
"E0","E1","E2","E3","E4","E5","E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
|
||||
"F0","F1","F2","F3","F4","F5","F6","F7","F8","F9","FA","FB","FC","FD","FE","FF"
|
||||
};
|
||||
static const char byte_to_str_lower[256][3] = {
|
||||
"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
|
||||
"10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
|
||||
"20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f",
|
||||
"30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f",
|
||||
"40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f",
|
||||
"50","51","52","53","54","55","56","57","58","59","5a","5b","5c","5d","5e","5f",
|
||||
"60","61","62","63","64","65","66","67","68","69","6a","6b","6c","6d","6e","6f",
|
||||
"70","71","72","73","74","75","76","77","78","79","7a","7b","7c","7d","7e","7f",
|
||||
"80","81","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f",
|
||||
"90","91","92","93","94","95","96","97","98","99","9a","9b","9c","9d","9e","9f",
|
||||
"a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","aa","ab","ac","ad","ae","af",
|
||||
"b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","ba","bb","bc","bd","be","bf",
|
||||
"c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","ca","cb","cc","cd","ce","cf",
|
||||
"d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","da","db","dc","dd","de","df",
|
||||
"e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef",
|
||||
"f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff"
|
||||
};
|
||||
const char (*byte_to_str)[3] = byte_to_str_upper;
|
||||
const guint last = len - 1;
|
||||
|
||||
if (lowercase) byte_to_str = byte_to_str_lower;
|
||||
|
||||
luaL_buffinit(L, &b);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
luaL_addlstring(&b, &(*byte_to_str[data[i]]), 2);
|
||||
if (sep && i < last) luaL_addstring(&b, sep);
|
||||
}
|
||||
|
||||
luaL_pushresult(&b);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Pushes a binary string of the hex-ascii data argument. */
|
||||
int wslua_hex2bin(lua_State* L, const char* data, const guint len, const gchar* sep) {
|
||||
luaL_Buffer b;
|
||||
guint i = 0;
|
||||
guint seplen = 0;
|
||||
char c, d;
|
||||
|
||||
static const char str_to_nibble[256] = {
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
|
||||
-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
||||
};
|
||||
|
||||
if (sep) seplen = (guint) strlen(sep);
|
||||
|
||||
luaL_buffinit(L, &b);
|
||||
|
||||
for (i = 0; i < len;) {
|
||||
c = str_to_nibble[(int)data[i]];
|
||||
if (c < 0) {
|
||||
if (seplen && strncmp(&data[i], sep, seplen) == 0) {
|
||||
i += seplen;
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
d = str_to_nibble[(int)data[++i]];
|
||||
if (d < 0) break;
|
||||
luaL_addchar(&b, (c * 16) + d);
|
||||
i++;
|
||||
}
|
||||
|
||||
luaL_pushresult(&b);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
|
|
|
@ -167,7 +167,7 @@ local MYDNS_PROTO_UDP_PORT = 65333
|
|||
-- some forward "declarations" of helper functions we use in the dissector
|
||||
-- I don't usually use this trick, but it'll help reading/grok'ing this script I think
|
||||
-- if we don't focus on them.
|
||||
local byteArray2String, getQueryName
|
||||
local getQueryName
|
||||
|
||||
|
||||
----------------------------------------
|
||||
|
@ -326,19 +326,6 @@ udp_encap_table:add(MYDNS_PROTO_UDP_PORT, dns)
|
|||
-- our protocol (Proto) gets automatically registered after this script finishes loading
|
||||
----------------------------------------
|
||||
|
||||
----------------------------------------
|
||||
-- a helper function used later
|
||||
-- note that it doesn't use "local" because it's already been declared as a local
|
||||
-- variable way earlier in this script (as a form of forward declaration)
|
||||
byteArray2String = function (barray, begin, length)
|
||||
local word = {}
|
||||
for i = 1, length do
|
||||
word[i] = string.char(barray:get_index(begin))
|
||||
begin = begin + 1
|
||||
end
|
||||
return table.concat(word)
|
||||
end
|
||||
|
||||
----------------------------------------
|
||||
-- DNS query names are not just null-terminated strings; they're actually a sequence of
|
||||
-- 'labels', with a length octet before each one. So "foobar.com" is actually the
|
||||
|
@ -373,10 +360,8 @@ getQueryName = function (tvbr)
|
|||
return nil, "invalid label length of "..label_len
|
||||
end
|
||||
pos = pos + 1 -- move past label length octet
|
||||
-- sadly, there's no current way to get a raw Lua string from a ByteArray (nor from Tvb for that matter)
|
||||
-- so we need to do it one character at a a time
|
||||
-- append the label and a dot to name string
|
||||
name = name .. byteArray2String(barray, pos, label_len) .. "."
|
||||
name = name .. barray:raw(pos, label_len) .. "."
|
||||
len_remaining = len_remaining - (label_len + 1) -- subtract label and its length octet
|
||||
label_count = label_count + 1
|
||||
pos = pos + label_len -- move past label
|
||||
|
|
|
@ -23,10 +23,17 @@ end
|
|||
-- auxiliar function to print an hexadecimal `dump' of a given string
|
||||
-- (not used by the test)
|
||||
--
|
||||
local function bp (s)
|
||||
local function tohex(s, sep)
|
||||
local patt = "%02x" .. (sep or "")
|
||||
s = string.gsub(s, "(.)", function(c)
|
||||
return string.format("\\%02x", string.byte(c))
|
||||
return string.format(patt, string.byte(c))
|
||||
end)
|
||||
if sep then s = s:sub(1,-(sep:len()+1)) end
|
||||
return s
|
||||
end
|
||||
|
||||
local function bp (s)
|
||||
s = tohex(s)
|
||||
print(s)
|
||||
end
|
||||
|
||||
|
@ -64,6 +71,18 @@ test("basic_size2", lib.size(fmt1_le) == Struct.size(fmt1_be))
|
|||
test("basic_size3", lib.size(fmt1_le) == Struct.size(fmt1_64le))
|
||||
test("basic_size4", lib.size(fmt2_be) == Struct.size(fmt1_64le))
|
||||
|
||||
testing("tohex")
|
||||
local val1hex = "2A:00:00:00:00:00:00:01:00:00:00:02:00:00:00:03:00:00:00:04"
|
||||
test("tohex1", Struct.tohex(val1) == tohex(val1):upper())
|
||||
test("tohex2", Struct.tohex(val1,true) == tohex(val1))
|
||||
test("tohex3", Struct.tohex(val1,false,":") == val1hex)
|
||||
test("tohex4", Struct.tohex(val1,true,":") == val1hex:lower())
|
||||
|
||||
testing("fromhex")
|
||||
test("fromhex1", Struct.fromhex(val1hex,":") == val1)
|
||||
local val1hex2 = val1hex:gsub(":","")
|
||||
test("fromhex2", Struct.fromhex(val1hex2) == val1)
|
||||
test("fromhex3", Struct.fromhex(val1hex2:lower()) == val1)
|
||||
|
||||
testing("basic unpack")
|
||||
local ret1, ret2, ret3, ret4, ret5, pos = lib.unpack(fmt1_le, val1)
|
||||
|
|
Loading…
Reference in New Issue