forked from osmocom/wireshark
407b7034e3
The format of the API chapter was a bit screwed up, as was the indentation level of attributes. Also, some functions introduced in 1.11.3 were not documented as being since that version. Change-Id: I7912488c6da5b5ae72933e4c5ce49f8fbf0b0e34 Reviewed-on: https://code.wireshark.org/review/6753 Reviewed-by: Hadriel Kaplan <hadrielk@yahoo.com> Petri-Dish: Hadriel Kaplan <hadrielk@yahoo.com> Reviewed-by: Anders Broman <a.broman58@gmail.com>
1649 lines
52 KiB
C
1649 lines
52 KiB
C
/*
|
|
* wslua_tvb.c
|
|
*
|
|
* Wireshark's interface to the Lua Programming Language
|
|
*
|
|
* (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
|
|
* (c) 2008, Balint Reczey <balint.reczey@ericsson.com>
|
|
* (c) 2009, Stig Bjorlykke <stig@bjorlykke.org>
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <epan/wmem/wmem.h>
|
|
|
|
/* WSLUA_MODULE Tvb Functions for handling packet data */
|
|
|
|
#include "wslua.h"
|
|
#include "wsutil/base64.h"
|
|
|
|
WSLUA_CLASS_DEFINE(ByteArray,FAIL_ON_NULL("ByteArray"),NOP);
|
|
|
|
WSLUA_CONSTRUCTOR ByteArray_new(lua_State* L) {
|
|
/* Creates a `ByteArray` object.
|
|
|
|
Starting in version 1.11.3, if the second argument is a boolean `true`,
|
|
then the first argyument is treated as a raw Lua string of bytes to use,
|
|
instead of a hexadecimal string.
|
|
*/
|
|
#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 argument
|
|
is treated as raw binary data */
|
|
GByteArray* ba = g_byte_array_new();
|
|
const gchar* s;
|
|
size_t len = 0;
|
|
const gchar* sep = " ";
|
|
gboolean ishex = TRUE;
|
|
|
|
if (lua_gettop(L) >= 1) {
|
|
s = luaL_checklstring(L,WSLUA_OPTARG_ByteArray_new_HEXBYTES,&len);
|
|
|
|
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 (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);
|
|
}
|
|
}
|
|
|
|
pushByteArray(L,ba);
|
|
|
|
WSLUA_RETURN(1); /* The new ByteArray object. */
|
|
}
|
|
|
|
/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
|
|
static int ByteArray__gc(lua_State* L) {
|
|
ByteArray ba = toByteArray(L,1);
|
|
|
|
if (!ba) return 0;
|
|
|
|
g_byte_array_free(ba,TRUE);
|
|
return 0;
|
|
}
|
|
|
|
WSLUA_METAMETHOD ByteArray__concat(lua_State* L) {
|
|
/* Concatenate two `ByteArrays`. */
|
|
#define WSLUA_ARG_ByteArray__cat_FIRST 1 /* First array. */
|
|
#define WSLUA_ARG_ByteArray__cat_SECOND 2 /* Second array. */
|
|
|
|
ByteArray ba1 = checkByteArray(L,WSLUA_ARG_ByteArray__cat_FIRST);
|
|
ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray__cat_SECOND);
|
|
ByteArray ba;
|
|
|
|
ba = g_byte_array_new();
|
|
g_byte_array_append(ba,ba1->data,ba1->len);
|
|
g_byte_array_append(ba,ba2->data,ba2->len);
|
|
|
|
pushByteArray(L,ba);
|
|
WSLUA_RETURN(1); /* The new composite `ByteArray`. */
|
|
}
|
|
|
|
WSLUA_METAMETHOD ByteArray__eq(lua_State* L) {
|
|
/* Compares two ByteArray values.
|
|
|
|
@since 1.11.4
|
|
*/
|
|
#define WSLUA_ARG_ByteArray__eq_FIRST 1 /* First array. */
|
|
#define WSLUA_ARG_ByteArray__eq_SECOND 2 /* Second array. */
|
|
ByteArray ba1 = checkByteArray(L,WSLUA_ARG_ByteArray__eq_FIRST);
|
|
ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray__eq_SECOND);
|
|
gboolean result = FALSE;
|
|
|
|
if (ba1->len == ba2->len) {
|
|
if (memcmp(ba1->data, ba2->data, ba1->len) == 0)
|
|
result = TRUE;
|
|
}
|
|
|
|
lua_pushboolean(L,result);
|
|
|
|
return 1;
|
|
}
|
|
|
|
WSLUA_METHOD ByteArray_prepend(lua_State* L) {
|
|
/* Prepend a `ByteArray` to this `ByteArray`. */
|
|
#define WSLUA_ARG_ByteArray_prepend_PREPENDED 2 /* `ByteArray` to be prepended. */
|
|
ByteArray ba = checkByteArray(L,1);
|
|
ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray_prepend_PREPENDED);
|
|
|
|
g_byte_array_prepend(ba,ba2->data,ba2->len);
|
|
|
|
return 0;
|
|
}
|
|
|
|
WSLUA_METHOD ByteArray_append(lua_State* L) {
|
|
/* Append a `ByteArray` to this `ByteArray`. */
|
|
#define WSLUA_ARG_ByteArray_append_APPENDED 2 /* `ByteArray` to be appended. */
|
|
ByteArray ba = checkByteArray(L,1);
|
|
ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray_append_APPENDED);
|
|
|
|
g_byte_array_append(ba,ba2->data,ba2->len);
|
|
|
|
return 0;
|
|
}
|
|
|
|
WSLUA_METHOD ByteArray_set_size(lua_State* L) {
|
|
/* Sets the size of a `ByteArray`, either truncating it or filling it with zeros. */
|
|
#define WSLUA_ARG_ByteArray_set_size_SIZE 2 /* New size of the array. */
|
|
|
|
ByteArray ba = checkByteArray(L,1);
|
|
int siz = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_size_SIZE);
|
|
guint8* padding;
|
|
|
|
if (siz < 0) {
|
|
WSLUA_ERROR(ByteArray_set_size,"ByteArray size must be non-negative");
|
|
return 0;
|
|
}
|
|
|
|
if (ba->len >= (guint)siz) { /* truncate */
|
|
g_byte_array_set_size(ba,siz);
|
|
} else { /* fill */
|
|
padding = (guint8 *)g_malloc0(sizeof(guint8)*(siz - ba->len));
|
|
g_byte_array_append(ba,padding,siz - ba->len);
|
|
g_free(padding);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
WSLUA_METHOD ByteArray_set_index(lua_State* L) {
|
|
/* Sets the value of an index of a `ByteArray`. */
|
|
#define WSLUA_ARG_ByteArray_set_index_INDEX 2 /* The position of the byte to be set. */
|
|
#define WSLUA_ARG_ByteArray_set_index_VALUE 3 /* The char value to set [0-255]. */
|
|
ByteArray ba = checkByteArray(L,1);
|
|
int idx = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_index_INDEX);
|
|
int v = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_index_VALUE);
|
|
|
|
if (idx == 0 && ! g_str_equal(luaL_optstring(L,2,""),"0") ) {
|
|
luaL_argerror(L,2,"bad index");
|
|
return 0;
|
|
}
|
|
|
|
if (idx < 0 || (guint)idx >= ba->len) {
|
|
luaL_argerror(L,2,"index out of range");
|
|
return 0;
|
|
}
|
|
|
|
if (v < 0 || v > 255) {
|
|
luaL_argerror(L,3,"Byte out of range");
|
|
return 0;
|
|
}
|
|
|
|
ba->data[idx] = (guint8)v;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
WSLUA_METHOD ByteArray_get_index(lua_State* L) {
|
|
/* Get the value of a byte in a `ByteArray`. */
|
|
#define WSLUA_ARG_ByteArray_get_index_INDEX 2 /* The position of the byte to get. */
|
|
ByteArray ba = checkByteArray(L,1);
|
|
int idx = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_get_index_INDEX);
|
|
|
|
if (idx == 0 && ! g_str_equal(luaL_optstring(L,2,""),"0") ) {
|
|
luaL_argerror(L,2,"bad index");
|
|
return 0;
|
|
}
|
|
|
|
if (idx < 0 || (guint)idx >= ba->len) {
|
|
luaL_argerror(L,2,"index out of range");
|
|
return 0;
|
|
}
|
|
lua_pushnumber(L,ba->data[idx]);
|
|
|
|
WSLUA_RETURN(1); /* The value [0-255] of the byte. */
|
|
}
|
|
|
|
WSLUA_METHOD ByteArray_len(lua_State* L) {
|
|
/* Obtain the length of a `ByteArray`. */
|
|
ByteArray ba = checkByteArray(L,1);
|
|
|
|
lua_pushnumber(L,(lua_Number)ba->len);
|
|
|
|
WSLUA_RETURN(1); /* The length of the `ByteArray`. */
|
|
}
|
|
|
|
WSLUA_METHOD ByteArray_subset(lua_State* L) {
|
|
/* 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 = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_index_OFFSET);
|
|
int len = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_index_LENGTH);
|
|
ByteArray sub;
|
|
|
|
if ((offset + len) > (int)ba->len || offset < 0 || len < 1) {
|
|
luaL_error(L,"Out Of Bounds");
|
|
return 0;
|
|
}
|
|
|
|
sub = g_byte_array_new();
|
|
g_byte_array_append(sub,ba->data + offset,len);
|
|
|
|
pushByteArray(L,sub);
|
|
|
|
WSLUA_RETURN(1); /* A `ByteArray` containing the requested segment. */
|
|
}
|
|
|
|
WSLUA_METHOD ByteArray_base64_decode(lua_State* L) {
|
|
/* Obtain a base64 decoded `ByteArray`.
|
|
|
|
@since 1.11.3
|
|
*/
|
|
ByteArray ba = checkByteArray(L,1);
|
|
ByteArray ba2;
|
|
gchar *data;
|
|
size_t len;
|
|
|
|
ba2 = g_byte_array_new();
|
|
data = (gchar*)g_malloc (ba->len + 1);
|
|
memcpy(data, ba->data, ba->len);
|
|
data[ba->len] = '\0';
|
|
|
|
len = ws_base64_decode_inplace(data);
|
|
g_byte_array_append(ba2,data,(int)len);
|
|
g_free(data);
|
|
|
|
pushByteArray(L,ba2);
|
|
WSLUA_RETURN(1); /* The created `ByteArray`. */
|
|
}
|
|
|
|
WSLUA_METHOD ByteArray_raw(lua_State* L) {
|
|
/* Obtain a Lua string of the binary bytes in a `ByteArray`.
|
|
|
|
@since 1.11.3
|
|
*/
|
|
#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);
|
|
guint offset = (guint) luaL_optinteger(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");
|
|
return 0;
|
|
}
|
|
|
|
len = (int) luaL_optinteger(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
|
|
|
|
@since 1.11.3
|
|
*/
|
|
#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;
|
|
|
|
lowercase = wslua_optbool(L,WSLUA_OPTARG_ByteArray_tohex_LOWERCASE,FALSE);
|
|
sep = luaL_optstring(L,WSLUA_OPTARG_ByteArray_tohex_SEPARATOR,NULL);
|
|
|
|
wslua_bin2hex(L, ba->data, ba->len, lowercase, sep);
|
|
|
|
WSLUA_RETURN(1); /* A hex-ascii string 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);
|
|
|
|
WSLUA_METHODS ByteArray_methods[] = {
|
|
WSLUA_CLASS_FNREG(ByteArray,new),
|
|
WSLUA_CLASS_FNREG(ByteArray,len),
|
|
WSLUA_CLASS_FNREG(ByteArray,prepend),
|
|
WSLUA_CLASS_FNREG(ByteArray,append),
|
|
WSLUA_CLASS_FNREG(ByteArray,subset),
|
|
WSLUA_CLASS_FNREG(ByteArray,set_size),
|
|
WSLUA_CLASS_FNREG(ByteArray,tvb),
|
|
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 }
|
|
};
|
|
|
|
WSLUA_META ByteArray_meta[] = {
|
|
WSLUA_CLASS_MTREG(ByteArray,tostring),
|
|
WSLUA_CLASS_MTREG(ByteArray,concat),
|
|
WSLUA_CLASS_MTREG(ByteArray,eq),
|
|
{"__call",ByteArray_subset},
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
int ByteArray_register(lua_State* L) {
|
|
WSLUA_REGISTER_CLASS(ByteArray);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Tvb & TvbRange
|
|
*
|
|
* a Tvb represents a tvbuff_t in Lua.
|
|
* a TvbRange represents a range in a tvb (tvb,offset,length) its main purpose is to do bounds checking,
|
|
* It helps, too, simplifying argument passing to Tree. In wireshark terms this is worthless nothing
|
|
* not already done by the TVB itself. In lua's terms it's necessary to avoid abusing TRY{}CATCH(){}
|
|
* via preemptive bounds checking.
|
|
*
|
|
* These lua objects refer to structures in wireshark that are freed independently from Lua's garbage collector.
|
|
* To avoid using pointers from Lua to Wireshark structures that are already freed, we maintain a list of the
|
|
* pointers each with a marker that tracks its expiry.
|
|
*
|
|
* All pointers are marked as expired when the dissection of the current frame is finished or when the garbage
|
|
* collector tries to free the object referring to the pointer, whichever comes first.
|
|
*
|
|
* All allocated memory chunks used for tracking the pointers' state are freed after marking the pointer as expired
|
|
* by the garbage collector or by the end of the dissection of the current frame, whichever comes second.
|
|
*
|
|
* We check the expiry state of the pointer before each access.
|
|
*
|
|
*/
|
|
|
|
WSLUA_CLASS_DEFINE(Tvb,FAIL_ON_NULL_OR_EXPIRED("Tvb"),NOP);
|
|
/* A `Tvb` represents the packet's buffer. It is passed as an argument to listeners and dissectors,
|
|
and can be used to extract information (via `TvbRange`) from the packet's data.
|
|
|
|
To create a `TvbRange` the `Tvb` must be called with offset and length as optional arguments;
|
|
the offset defaults to 0 and the length to `tvb:len()`.
|
|
|
|
@warning Tvbs are usable only by the current listener or dissector call and are destroyed
|
|
as soon as the listener/dissector returns, so references to them are unusable once the function
|
|
has returned.
|
|
*/
|
|
|
|
static GPtrArray* outstanding_Tvb = NULL;
|
|
static GPtrArray* outstanding_TvbRange = NULL;
|
|
|
|
#define PUSH_TVB(L,t) {g_ptr_array_add(outstanding_Tvb,t);pushTvb(L,t);}
|
|
#define PUSH_TVBRANGE(L,t) {g_ptr_array_add(outstanding_TvbRange,t);pushTvbRange(L,t);}
|
|
|
|
static void free_Tvb(Tvb tvb) {
|
|
if (!tvb) return;
|
|
|
|
if (!tvb->expired) {
|
|
tvb->expired = TRUE;
|
|
} else {
|
|
if (tvb->need_free)
|
|
tvb_free(tvb->ws_tvb);
|
|
g_free(tvb);
|
|
}
|
|
}
|
|
|
|
void clear_outstanding_Tvb(void) {
|
|
while (outstanding_Tvb->len) {
|
|
Tvb tvb = (Tvb)g_ptr_array_remove_index_fast(outstanding_Tvb,0);
|
|
free_Tvb(tvb);
|
|
}
|
|
}
|
|
|
|
static void free_TvbRange(TvbRange tvbr) {
|
|
if (!(tvbr && tvbr->tvb)) return;
|
|
|
|
if (!tvbr->tvb->expired) {
|
|
tvbr->tvb->expired = TRUE;
|
|
} else {
|
|
free_Tvb(tvbr->tvb);
|
|
g_free(tvbr);
|
|
}
|
|
}
|
|
|
|
void clear_outstanding_TvbRange(void) {
|
|
while (outstanding_TvbRange->len) {
|
|
TvbRange tvbr = (TvbRange)g_ptr_array_remove_index_fast(outstanding_TvbRange,0);
|
|
free_TvbRange(tvbr);
|
|
}
|
|
}
|
|
|
|
|
|
Tvb* push_Tvb(lua_State* L, tvbuff_t* ws_tvb) {
|
|
Tvb tvb = (Tvb)g_malloc(sizeof(struct _wslua_tvb));
|
|
tvb->ws_tvb = ws_tvb;
|
|
tvb->expired = FALSE;
|
|
tvb->need_free = FALSE;
|
|
g_ptr_array_add(outstanding_Tvb,tvb);
|
|
return pushTvb(L,tvb);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* ByteArray_tvb(name)
|
|
*/
|
|
WSLUA_CONSTRUCTOR ByteArray_tvb (lua_State *L) {
|
|
/* Creates a new `Tvb` from a `ByteArray` (it gets added to the current frame too). */
|
|
#define WSLUA_ARG_ByteArray_tvb_NAME 2 /* The name to be given to the new data-source. */
|
|
ByteArray ba = checkByteArray(L,1);
|
|
const gchar* name = luaL_optstring(L,WSLUA_ARG_ByteArray_tvb_NAME,"Unnamed") ;
|
|
guint8* data;
|
|
Tvb tvb;
|
|
|
|
if (!lua_tvb) {
|
|
luaL_error(L,"Tvbs can only be created and used in dissectors");
|
|
return 0;
|
|
}
|
|
|
|
data = (guint8 *)g_memdup(ba->data, ba->len);
|
|
|
|
tvb = (Tvb)g_malloc(sizeof(struct _wslua_tvb));
|
|
tvb->ws_tvb = tvb_new_real_data(data, ba->len,ba->len);
|
|
tvb->expired = FALSE;
|
|
tvb->need_free = TRUE;
|
|
tvb_set_free_cb(tvb->ws_tvb, g_free);
|
|
|
|
add_new_data_source(lua_pinfo, tvb->ws_tvb, name);
|
|
PUSH_TVB(L,tvb);
|
|
WSLUA_RETURN(1); /* The created `Tvb`. */
|
|
}
|
|
|
|
WSLUA_CONSTRUCTOR TvbRange_tvb (lua_State *L) {
|
|
/* 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);
|
|
Tvb tvb;
|
|
|
|
if (! (tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
if (tvb_offset_exists(tvbr->tvb->ws_tvb, tvbr->offset + tvbr->len -1 )) {
|
|
tvb = (Tvb)g_malloc(sizeof(struct _wslua_tvb));
|
|
tvb->expired = FALSE;
|
|
tvb->need_free = FALSE;
|
|
tvb->ws_tvb = tvb_new_subset(tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len, tvbr->len);
|
|
PUSH_TVB(L, tvb);
|
|
return 1;
|
|
} else {
|
|
luaL_error(L,"Out Of Bounds");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
WSLUA_METAMETHOD Tvb__tostring(lua_State* L) {
|
|
/* Convert the bytes of a `Tvb` into a string, to be used for debugging purposes, as '...'
|
|
will be appended if the string is too long. */
|
|
Tvb tvb = checkTvb(L,1);
|
|
int len = tvb_captured_length(tvb->ws_tvb);
|
|
char* str = tvb_bytes_to_str(NULL,tvb->ws_tvb,0,len);
|
|
|
|
lua_pushfstring(L, "TVB(%d) : %s", len, str);
|
|
|
|
wmem_free(NULL, str);
|
|
|
|
WSLUA_RETURN(1); /* The string. */
|
|
}
|
|
|
|
/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
|
|
static int Tvb__gc(lua_State* L) {
|
|
Tvb tvb = toTvb(L,1);
|
|
|
|
free_Tvb(tvb);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
WSLUA_METHOD Tvb_reported_len(lua_State* L) {
|
|
/* Obtain the reported (not captured) length of a `Tvb`. */
|
|
Tvb tvb = checkTvb(L,1);
|
|
|
|
lua_pushnumber(L,tvb_reported_length(tvb->ws_tvb));
|
|
WSLUA_RETURN(1); /* The reported length of the `Tvb`. */
|
|
}
|
|
|
|
WSLUA_METHOD Tvb_len(lua_State* L) {
|
|
/* Obtain the actual (captured) length of a `Tvb`. */
|
|
Tvb tvb = checkTvb(L,1);
|
|
|
|
lua_pushnumber(L,tvb_captured_length(tvb->ws_tvb));
|
|
WSLUA_RETURN(1); /* The captured length of the `Tvb`. */
|
|
}
|
|
|
|
WSLUA_METHOD Tvb_reported_length_remaining(lua_State* L) {
|
|
/* Obtain the reported (not captured) length of packet data to end of a `Tvb` or -1 if the
|
|
offset is beyond the end of the `Tvb`. */
|
|
#define Tvb_reported_length_remaining_OFFSET 2 /* offset */
|
|
Tvb tvb = checkTvb(L,1);
|
|
int offset = (int) luaL_optinteger(L, Tvb_reported_length_remaining_OFFSET, 0);
|
|
|
|
lua_pushnumber(L,tvb_reported_length_remaining(tvb->ws_tvb, offset));
|
|
WSLUA_RETURN(1); /* The captured length of the `Tvb`. */
|
|
}
|
|
|
|
WSLUA_METHOD Tvb_offset(lua_State* L) {
|
|
/* Returns the raw offset (from the beginning of the source `Tvb`) of a sub `Tvb`. */
|
|
Tvb tvb = checkTvb(L,1);
|
|
|
|
lua_pushnumber(L,tvb_raw_offset(tvb->ws_tvb));
|
|
WSLUA_RETURN(1); /* The raw offset of the `Tvb`. */
|
|
}
|
|
|
|
|
|
#if USED_FOR_DOC_PURPOSES
|
|
WSLUA_METAMETHOD Tvb__call(lua_State* L) {
|
|
/* Equivalent to tvb:range(...) */
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
WSLUA_CLASS_DEFINE(TvbRange,FAIL_ON_NULL("TvbRange"),NOP);
|
|
/*
|
|
A `TvbRange` represents a usable range of a `Tvb` and is used to extract data from the `Tvb` that generated it.
|
|
|
|
`TvbRange`s are created by calling a `Tvb` (e.g. 'tvb(offset,length)'). If the `TvbRange` span is outside the
|
|
`Tvb`'s range the creation will cause a runtime error.
|
|
*/
|
|
|
|
gboolean push_TvbRange(lua_State* L, tvbuff_t* ws_tvb, int offset, int len) {
|
|
TvbRange tvbr;
|
|
|
|
if (!ws_tvb) {
|
|
luaL_error(L,"expired tvb");
|
|
return FALSE;
|
|
}
|
|
|
|
if (len == -1) {
|
|
len = tvb_captured_length_remaining(ws_tvb,offset);
|
|
if (len < 0) {
|
|
luaL_error(L,"out of bounds");
|
|
return FALSE;
|
|
}
|
|
} else if ( (guint)(len + offset) > tvb_captured_length(ws_tvb)) {
|
|
luaL_error(L,"Range is out of bounds");
|
|
return FALSE;
|
|
}
|
|
|
|
tvbr = (TvbRange)g_malloc(sizeof(struct _wslua_tvbrange));
|
|
tvbr->tvb = (Tvb)g_malloc(sizeof(struct _wslua_tvb));
|
|
tvbr->tvb->ws_tvb = ws_tvb;
|
|
tvbr->tvb->expired = FALSE;
|
|
tvbr->tvb->need_free = FALSE;
|
|
tvbr->offset = offset;
|
|
tvbr->len = len;
|
|
|
|
PUSH_TVBRANGE(L,tvbr);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
WSLUA_METHOD Tvb_range(lua_State* L) {
|
|
/* Creates a `TvbRange` from this `Tvb`. */
|
|
#define WSLUA_OPTARG_Tvb_range_OFFSET 2 /* The offset (in octets) from the beginning of the `Tvb`. Defaults to 0. */
|
|
#define WSLUA_OPTARG_Tvb_range_LENGTH 3 /* The length (in octets) of the range. Defaults to until the end of the `Tvb`. */
|
|
|
|
Tvb tvb = checkTvb(L,1);
|
|
int offset = (int) luaL_optinteger(L,WSLUA_OPTARG_Tvb_range_OFFSET,0);
|
|
int len = (int) luaL_optinteger(L,WSLUA_OPTARG_Tvb_range_LENGTH,-1);
|
|
|
|
if (push_TvbRange(L,tvb->ws_tvb,offset,len)) {
|
|
WSLUA_RETURN(1); /* The TvbRange */
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
WSLUA_METHOD Tvb_raw(lua_State* L) {
|
|
/* Obtain a Lua string of the binary bytes in a `Tvb`.
|
|
|
|
@since 1.11.3
|
|
*/
|
|
#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 = (int) luaL_optinteger(L,WSLUA_OPTARG_Tvb_raw_OFFSET,0);
|
|
int len = (int) luaL_optinteger(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_captured_length(tvb->ws_tvb)) {
|
|
WSLUA_OPTARG_ERROR(Tvb_raw,OFFSET,"offset beyond end of Tvb");
|
|
return 0;
|
|
}
|
|
|
|
if (len == -1) {
|
|
len = tvb_captured_length_remaining(tvb->ws_tvb,offset);
|
|
if (len < 0) {
|
|
luaL_error(L,"out of bounds");
|
|
return FALSE;
|
|
}
|
|
} else if ( (guint)(len + offset) > tvb_captured_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 }
|
|
};
|
|
|
|
WSLUA_META Tvb_meta[] = {
|
|
WSLUA_CLASS_MTREG(Tvb,tostring),
|
|
{"__call", Tvb_range},
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
int Tvb_register(lua_State* L) {
|
|
WSLUA_REGISTER_CLASS(Tvb);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* get a Blefuscuoan unsigned integer from a tvb
|
|
*/
|
|
WSLUA_METHOD TvbRange_uint(lua_State* L) {
|
|
/* Get a Big Endian (network order) unsigned integer from a `TvbRange`.
|
|
The range must be 1, 2, 3 or 4 octets long. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
switch (tvbr->len) {
|
|
case 1:
|
|
lua_pushnumber(L,tvb_get_guint8(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
return 1;
|
|
case 2:
|
|
lua_pushnumber(L,tvb_get_ntohs(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
return 1;
|
|
case 3:
|
|
lua_pushnumber(L,tvb_get_ntoh24(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
return 1;
|
|
case 4:
|
|
lua_pushnumber(L,tvb_get_ntohl(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
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:
|
|
luaL_error(L,"TvbRange:uint() does not handle %d byte integers",tvbr->len);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* get a Lilliputian unsigned integer from a tvb
|
|
*/
|
|
WSLUA_METHOD TvbRange_le_uint(lua_State* L) {
|
|
/* Get a Little Endian unsigned integer from a `TvbRange`.
|
|
The range must be 1, 2, 3 or 4 octets long. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
switch (tvbr->len) {
|
|
case 1:
|
|
/* XXX unsigned anyway */
|
|
lua_pushnumber(L,(lua_Number)(guint)tvb_get_guint8(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
return 1;
|
|
case 2:
|
|
lua_pushnumber(L,tvb_get_letohs(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
return 1;
|
|
case 3:
|
|
lua_pushnumber(L,tvb_get_letoh24(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
return 1;
|
|
case 4:
|
|
lua_pushnumber(L,tvb_get_letohl(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
WSLUA_RETURN(1); /* The unsigned integer value */
|
|
default:
|
|
luaL_error(L,"TvbRange:le_uint() does not handle %d byte integers",tvbr->len);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* get a Blefuscuoan unsigned 64 bit integer from a tvb
|
|
*/
|
|
WSLUA_METHOD TvbRange_uint64(lua_State* L) {
|
|
/* Get a Big Endian (network order) unsigned 64 bit integer from a `TvbRange`, as a `UInt64` object.
|
|
The range must be 1-8 octets long. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
switch (tvbr->len) {
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8: {
|
|
pushUInt64(L,tvb_get_ntoh64(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
WSLUA_RETURN(1); /* The `UInt64` object. */
|
|
}
|
|
default:
|
|
luaL_error(L,"TvbRange:uint64() does not handle %d byte integers",tvbr->len);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* get a Lilliputian unsigned 64 bit integer from a tvb
|
|
*/
|
|
WSLUA_METHOD TvbRange_le_uint64(lua_State* L) {
|
|
/* Get a Little Endian unsigned 64 bit integer from a `TvbRange`, as a `UInt64` object.
|
|
The range must be 1-8 octets long. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
switch (tvbr->len) {
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8: {
|
|
pushUInt64(L,tvb_get_letoh64(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
WSLUA_RETURN(1); /* The `UInt64` object. */
|
|
}
|
|
default:
|
|
luaL_error(L,"TvbRange:le_uint64() does not handle %d byte integers",tvbr->len);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* get a Blefuscuoan signed integer from a tvb
|
|
*/
|
|
WSLUA_METHOD TvbRange_int(lua_State* L) {
|
|
/* Get a Big Endian (network order) signed integer from a `TvbRange`.
|
|
The range must be 1, 2 or 4 octets long. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
switch (tvbr->len) {
|
|
case 1:
|
|
lua_pushnumber(L,(gchar)tvb_get_guint8(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
return 1;
|
|
case 2:
|
|
lua_pushnumber(L,(gshort)tvb_get_ntohs(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
return 1;
|
|
case 4:
|
|
lua_pushnumber(L,(gint)tvb_get_ntohl(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
WSLUA_RETURN(1); /* The signed 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:
|
|
luaL_error(L,"TvbRange:int() does not handle %d byte integers",tvbr->len);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* get a Lilliputian signed integer from a tvb
|
|
*/
|
|
WSLUA_METHOD TvbRange_le_int(lua_State* L) {
|
|
/* Get a Little Endian signed integer from a `TvbRange`.
|
|
The range must be 1, 2 or 4 octets long. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
switch (tvbr->len) {
|
|
case 1:
|
|
lua_pushnumber(L,(gchar)tvb_get_guint8(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
return 1;
|
|
case 2:
|
|
lua_pushnumber(L,(gshort)tvb_get_letohs(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
return 1;
|
|
case 4:
|
|
lua_pushnumber(L,(gint)tvb_get_letohl(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
WSLUA_RETURN(1); /* The signed integer value. */
|
|
default:
|
|
luaL_error(L,"TvbRange:le_int() does not handle %d byte integers",tvbr->len);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* get a Blefuscuoan signed 64 bit integer from a tvb
|
|
*/
|
|
WSLUA_METHOD TvbRange_int64(lua_State* L) {
|
|
/* Get a Big Endian (network order) signed 64 bit integer from a `TvbRange`, as an `Int64` object.
|
|
The range must be 1-8 octets long. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
switch (tvbr->len) {
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8: {
|
|
pushInt64(L,(gint64)tvb_get_ntoh64(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
WSLUA_RETURN(1); /* The `Int64` object. */
|
|
}
|
|
default:
|
|
luaL_error(L,"TvbRange:int64() does not handle %d byte integers",tvbr->len);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* get a Lilliputian signed 64 bit integer from a tvb
|
|
*/
|
|
WSLUA_METHOD TvbRange_le_int64(lua_State* L) {
|
|
/* Get a Little Endian signed 64 bit integer from a `TvbRange`, as an `Int64` object.
|
|
The range must be 1-8 octets long. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
switch (tvbr->len) {
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8: {
|
|
pushInt64(L,(gint64)tvb_get_letoh64(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
WSLUA_RETURN(1); /* The `Int64` object. */
|
|
}
|
|
default:
|
|
luaL_error(L,"TvbRange:le_int64() does not handle %d byte integers",tvbr->len);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* get a Blefuscuoan float
|
|
*/
|
|
WSLUA_METHOD TvbRange_float(lua_State* L) {
|
|
/* Get a Big Endian (network order) floating point number from a `TvbRange`.
|
|
The range must be 4 or 8 octets long. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
switch (tvbr->len) {
|
|
case 4:
|
|
lua_pushnumber(L,(double)tvb_get_ntohieee_float(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
return 1;
|
|
case 8:
|
|
lua_pushnumber(L,tvb_get_ntohieee_double(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
WSLUA_RETURN(1); /* The floating point value. */
|
|
default:
|
|
luaL_error(L,"TvbRange:float() does not handle %d byte floating numbers",tvbr->len);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* get a Lilliputian float
|
|
*/
|
|
WSLUA_METHOD TvbRange_le_float(lua_State* L) {
|
|
/* Get a Little Endian floating point number from a `TvbRange`.
|
|
The range must be 4 or 8 octets long. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
|
|
switch (tvbr->len) {
|
|
case 4:
|
|
lua_pushnumber(L,tvb_get_letohieee_float(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
return 1;
|
|
case 8:
|
|
lua_pushnumber(L,tvb_get_letohieee_double(tvbr->tvb->ws_tvb,tvbr->offset));
|
|
WSLUA_RETURN(1); /* The floating point value. */
|
|
default:
|
|
luaL_error(L,"TvbRange:le_float() does not handle %d byte floating numbers",tvbr->len);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_ipv4(lua_State* L) {
|
|
/* Get an IPv4 Address from a `TvbRange`, as an `Address` object. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
Address addr;
|
|
guint32* ip_addr;
|
|
|
|
if ( !(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
if (tvbr->len != 4) {
|
|
WSLUA_ERROR(TvbRange_ipv4,"The range must be 4 octets long");
|
|
return 0;
|
|
}
|
|
|
|
addr = (address *)g_malloc(sizeof(address));
|
|
|
|
ip_addr = (guint32 *)g_malloc(sizeof(guint32));
|
|
*ip_addr = tvb_get_ipv4(tvbr->tvb->ws_tvb,tvbr->offset);
|
|
|
|
SET_ADDRESS(addr, AT_IPv4, 4, ip_addr);
|
|
pushAddress(L,addr);
|
|
|
|
WSLUA_RETURN(1); /* The IPv4 `Address` object. */
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_le_ipv4(lua_State* L) {
|
|
/* Get an Little Endian IPv4 Address from a `TvbRange`, as an `Address` object. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
Address addr;
|
|
guint32* ip_addr;
|
|
|
|
if ( !(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
if (tvbr->len != 4) {
|
|
WSLUA_ERROR(TvbRange_ipv4,"The range must be 4 octets long");
|
|
return 0;
|
|
}
|
|
|
|
addr = (address *)g_malloc(sizeof(address));
|
|
|
|
ip_addr = (guint32 *)g_malloc(sizeof(guint32));
|
|
*ip_addr = tvb_get_ipv4(tvbr->tvb->ws_tvb,tvbr->offset);
|
|
*((guint32 *)ip_addr) = GUINT32_SWAP_LE_BE(*((guint32 *)ip_addr));
|
|
|
|
SET_ADDRESS(addr, AT_IPv4, 4, ip_addr);
|
|
pushAddress(L,addr);
|
|
|
|
WSLUA_RETURN(1); /* The IPv4 `Address` object. */
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_ether(lua_State* L) {
|
|
/* Get an Ethernet Address from a `TvbRange`, as an `Address` object. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
Address addr;
|
|
guint8* buff;
|
|
|
|
if ( !(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
if (tvbr->len != 6) {
|
|
WSLUA_ERROR(TvbRange_ether,"The range must be 6 bytes long");
|
|
return 0;
|
|
}
|
|
|
|
addr = g_new(address,1);
|
|
|
|
buff = (guint8 *)tvb_memdup(NULL,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len);
|
|
|
|
SET_ADDRESS(addr, AT_ETHER, 6, buff);
|
|
pushAddress(L,addr);
|
|
|
|
WSLUA_RETURN(1); /* The Ethernet `Address` object. */
|
|
}
|
|
|
|
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 = (guint) luaL_optinteger(L, WSLUA_OPTARG_TvbRange_nstime_ENCODING, 0);
|
|
|
|
if ( !(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
nstime = g_new(nstime_t,1);
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
WSLUA_RETURN(2); /* The `NSTime` object and number of bytes used, or nil on failure. */
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_le_nstime(lua_State* L) {
|
|
/* Obtain a nstime from a `TvbRange`, as an `NSTime` object. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
NSTime nstime;
|
|
|
|
if ( !(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
nstime = g_new(nstime_t,1);
|
|
|
|
if (tvbr->len == 4) {
|
|
nstime->secs = tvb_get_letohl(tvbr->tvb->ws_tvb, tvbr->offset);
|
|
nstime->nsecs = 0;
|
|
} else if (tvbr->len == 8) {
|
|
nstime->secs = tvb_get_letohl(tvbr->tvb->ws_tvb, tvbr->offset);
|
|
nstime->nsecs = tvb_get_letohl(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);
|
|
|
|
WSLUA_RETURN(1); /* The `NSTime` object. */
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_string(lua_State* L) {
|
|
/* Obtain a string from a `TvbRange`. */
|
|
#define WSLUA_OPTARG_TvbRange_string_ENCODING 2 /* The encoding to use. Defaults to ENC_ASCII. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
guint encoding = (guint)luaL_optinteger(L,WSLUA_OPTARG_TvbRange_string_ENCODING, ENC_ASCII|ENC_NA);
|
|
|
|
if ( !(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
lua_pushlstring(L, (gchar*)tvb_get_string_enc(wmem_packet_scope(),tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,encoding), tvbr->len);
|
|
|
|
WSLUA_RETURN(1); /* The string */
|
|
}
|
|
|
|
static int TvbRange_ustring_any(lua_State* L, gboolean little_endian) {
|
|
/* Obtain a UTF-16 encoded string from a `TvbRange`. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
gchar * str;
|
|
|
|
if ( !(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
str = (gchar*)tvb_get_string_enc(wmem_packet_scope(),tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,(little_endian ? ENC_UTF_16|ENC_LITTLE_ENDIAN : ENC_UTF_16|ENC_BIG_ENDIAN));
|
|
lua_pushlstring(L, str, strlen(str));
|
|
|
|
return 1; /* The string */
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_ustring(lua_State* L) {
|
|
/* Obtain a Big Endian (network order) UTF-16 encoded string from a `TvbRange`. */
|
|
WSLUA_RETURN(TvbRange_ustring_any(L, FALSE)); /* The string. */
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_le_ustring(lua_State* L) {
|
|
/* Obtain a Little Endian UTF-16 encoded string from a `TvbRange`. */
|
|
WSLUA_RETURN(TvbRange_ustring_any(L, TRUE)); /* The string. */
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_stringz(lua_State* L) {
|
|
/* Obtain a zero terminated string from a `TvbRange`. */
|
|
#define WSLUA_OPTARG_TvbRange_stringz_ENCODING 2 /* The encoding to use. Defaults to ENC_ASCII. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
guint encoding = (guint)luaL_optinteger(L,WSLUA_OPTARG_TvbRange_stringz_ENCODING, ENC_ASCII|ENC_NA);
|
|
gint offset;
|
|
gunichar2 uchar;
|
|
|
|
if ( !(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
switch (encoding & ENC_CHARENCODING_MASK) {
|
|
|
|
case ENC_UTF_16:
|
|
case ENC_UCS_2:
|
|
offset = tvbr->offset;
|
|
do {
|
|
if (!tvb_bytes_exist (tvbr->tvb->ws_tvb, offset, 2)) {
|
|
luaL_error(L,"out of bounds");
|
|
return 0;
|
|
}
|
|
/* Endianness doesn't matter when looking for null */
|
|
uchar = tvb_get_ntohs (tvbr->tvb->ws_tvb, offset);
|
|
offset += 2;
|
|
} while(uchar != 0);
|
|
break;
|
|
|
|
default:
|
|
if (tvb_find_guint8 (tvbr->tvb->ws_tvb, tvbr->offset, -1, 0) == -1) {
|
|
luaL_error(L,"out of bounds");
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
lua_pushstring(L, (gchar*)tvb_get_stringz_enc(wmem_packet_scope(),tvbr->tvb->ws_tvb,tvbr->offset,NULL,encoding));
|
|
|
|
WSLUA_RETURN(1); /* The zero terminated string. */
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_strsize(lua_State* L) {
|
|
/* Find the size of a zero terminated string from a `TvbRange`.
|
|
The size of the string includes the terminating zero.
|
|
|
|
@since 1.11.3
|
|
*/
|
|
#define WSLUA_OPTARG_TvbRange_strsize_ENCODING 2 /* The encoding to use. Defaults to ENC_ASCII. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
guint encoding = (guint)luaL_optinteger(L,WSLUA_OPTARG_TvbRange_strsize_ENCODING, ENC_ASCII|ENC_NA);
|
|
gint offset;
|
|
gunichar2 uchar;
|
|
|
|
if ( !(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
switch (encoding & ENC_CHARENCODING_MASK) {
|
|
|
|
case ENC_UTF_16:
|
|
case ENC_UCS_2:
|
|
offset = tvbr->offset;
|
|
do {
|
|
if (!tvb_bytes_exist (tvbr->tvb->ws_tvb, offset, 2)) {
|
|
luaL_error(L,"out of bounds");
|
|
return 0;
|
|
}
|
|
/* Endianness doesn't matter when looking for null */
|
|
uchar = tvb_get_ntohs (tvbr->tvb->ws_tvb, offset);
|
|
offset += 2;
|
|
} while (uchar != 0);
|
|
lua_pushinteger(L, tvb_unicode_strsize(tvbr->tvb->ws_tvb, tvbr->offset));
|
|
break;
|
|
|
|
default:
|
|
if (tvb_find_guint8 (tvbr->tvb->ws_tvb, tvbr->offset, -1, 0) == -1) {
|
|
luaL_error(L,"out of bounds");
|
|
return 0;
|
|
}
|
|
lua_pushinteger(L, tvb_strsize(tvbr->tvb->ws_tvb, tvbr->offset));
|
|
break;
|
|
}
|
|
|
|
WSLUA_RETURN(1); /* Length of the zero terminated string. */
|
|
}
|
|
|
|
|
|
static int TvbRange_ustringz_any(lua_State* L, gboolean little_endian) {
|
|
/* Obtain a zero terminated string from a TvbRange */
|
|
gint count;
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
gint offset;
|
|
gunichar2 uchar;
|
|
|
|
if ( !(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
offset = tvbr->offset;
|
|
do {
|
|
if (!tvb_bytes_exist (tvbr->tvb->ws_tvb, offset, 2)) {
|
|
luaL_error(L,"out of bounds");
|
|
return 0;
|
|
}
|
|
/* Endianness doesn't matter when looking for null */
|
|
uchar = tvb_get_ntohs (tvbr->tvb->ws_tvb, offset);
|
|
offset += 2;
|
|
} while (uchar != 0);
|
|
|
|
lua_pushstring(L, (gchar*)tvb_get_stringz_enc(wmem_packet_scope(),tvbr->tvb->ws_tvb,tvbr->offset,&count,
|
|
(little_endian ? ENC_UTF_16|ENC_LITTLE_ENDIAN : ENC_UTF_16|ENC_BIG_ENDIAN)) );
|
|
lua_pushinteger(L,count);
|
|
|
|
return 2; /* The zero terminated string, the length found in tvbr */
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_ustringz(lua_State* L) {
|
|
/* Obtain a Big Endian (network order) UTF-16 encoded zero terminated string from a `TvbRange`. */
|
|
WSLUA_RETURN(TvbRange_ustringz_any(L, FALSE)); /* Two return values: the zero terminated string, and the length. */
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_le_ustringz(lua_State* L) {
|
|
/* Obtain a Little Endian UTF-16 encoded zero terminated string from a TvbRange */
|
|
WSLUA_RETURN(TvbRange_ustringz_any(L, TRUE)); /* Two return values: the zero terminated string, and the length. */
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_bytes(lua_State* L) {
|
|
/* Obtain a `ByteArray` from a `TvbRange`.
|
|
|
|
Starting in 1.11.4, this function also takes an optional `encoding` argument,
|
|
which can be set to `ENC_STR_HEX` to decode a hex-string from the `TvbRange`
|
|
into the returned `ByteArray`. The `encoding` can be bitwise-or'ed with one
|
|
or more separator encodings, such as `ENC_SEP_COLON`, to allow separators
|
|
to occur between each pair of hex characters.
|
|
|
|
The return value also now returns the number of bytes used as a second return value.
|
|
|
|
On failure or error, nil is returned for both return values.
|
|
|
|
@note The encoding type of the hex string should also be set, for example
|
|
`ENC_ASCII` or `ENC_UTF_8`, along with `ENC_STR_HEX`.
|
|
*/
|
|
#define WSLUA_OPTARG_TvbRange_bytes_ENCODING 2 /* An optional ENC_* encoding value to use */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
GByteArray* ba;
|
|
const guint encoding = (guint)luaL_optinteger(L, WSLUA_OPTARG_TvbRange_bytes_ENCODING, 0);
|
|
|
|
if ( !(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
ba = g_byte_array_new();
|
|
|
|
if (encoding == 0) {
|
|
g_byte_array_append(ba,(const guint8 *)tvb_memdup(wmem_packet_scope(),tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len),tvbr->len);
|
|
pushByteArray(L,ba);
|
|
lua_pushinteger(L, tvbr->len);
|
|
}
|
|
else if ((encoding & ENC_STR_HEX) == 0) {
|
|
WSLUA_OPTARG_ERROR(TvbRange_nstime, ENCODING, "invalid encoding value");
|
|
}
|
|
else {
|
|
gint endoff = 0;
|
|
GByteArray* retval = tvb_get_string_bytes(tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len,
|
|
encoding, ba, &endoff);
|
|
if (!retval || endoff == 0) {
|
|
g_byte_array_free(ba, TRUE);
|
|
/* push nil nstime and offset */
|
|
lua_pushnil(L);
|
|
lua_pushnil(L);
|
|
}
|
|
else {
|
|
pushByteArray(L,ba);
|
|
lua_pushinteger(L, endoff);
|
|
}
|
|
}
|
|
|
|
WSLUA_RETURN(2); /* The `ByteArray` object or nil, and number of bytes consumed or nil. */
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_bitfield(lua_State* L) {
|
|
/* Get a bitfield from a `TvbRange`. */
|
|
#define WSLUA_OPTARG_TvbRange_bitfield_POSITION 2 /* The bit offset from the beginning of the `TvbRange`. Defaults to 0. */
|
|
#define WSLUA_OPTARG_TvbRange_bitfield_LENGTH 3 /* The length (in bits) of the field. Defaults to 1. */
|
|
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
int pos = (int)luaL_optinteger(L,WSLUA_OPTARG_TvbRange_bitfield_POSITION,0);
|
|
int len = (int)luaL_optinteger(L,WSLUA_OPTARG_TvbRange_bitfield_LENGTH,1);
|
|
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
if ((pos+len) > (tvbr->len<<3)) {
|
|
luaL_error(L, "Requested bitfield out of range");
|
|
return 0;
|
|
}
|
|
|
|
if (len <= 8) {
|
|
lua_pushnumber(L,(lua_Number)(guint)tvb_get_bits8(tvbr->tvb->ws_tvb,tvbr->offset*8 + pos, len));
|
|
return 1;
|
|
} else if (len <= 16) {
|
|
lua_pushnumber(L,tvb_get_bits16(tvbr->tvb->ws_tvb,tvbr->offset*8 + pos, len, FALSE));
|
|
return 1;
|
|
} else if (len <= 32) {
|
|
lua_pushnumber(L,tvb_get_bits32(tvbr->tvb->ws_tvb,tvbr->offset*8 + pos, len, FALSE));
|
|
return 1;
|
|
} else if (len <= 64) {
|
|
pushUInt64(L,tvb_get_bits64(tvbr->tvb->ws_tvb,tvbr->offset*8 + pos, len, FALSE));
|
|
WSLUA_RETURN(1); /* The bitfield value */
|
|
} else {
|
|
luaL_error(L,"TvbRange:bitfield() does not handle %d bits",len);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_range(lua_State* L) {
|
|
/* Creates a sub-`TvbRange` from this `TvbRange`. */
|
|
#define WSLUA_OPTARG_TvbRange_range_OFFSET 2 /* The offset (in octets) from the beginning of the `TvbRange`. Defaults to 0. */
|
|
#define WSLUA_OPTARG_TvbRange_range_LENGTH 3 /* The length (in octets) of the range. Defaults to until the end of the `TvbRange`. */
|
|
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
int offset = (int)luaL_optinteger(L,WSLUA_OPTARG_TvbRange_range_OFFSET,0);
|
|
int len;
|
|
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
|
|
len = (int)luaL_optinteger(L,WSLUA_OPTARG_TvbRange_range_LENGTH,tvbr->len-offset);
|
|
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
if (offset >= tvbr->len || (len + offset) > tvbr->len) {
|
|
luaL_error(L,"Range is out of bounds");
|
|
return 0;
|
|
}
|
|
|
|
if (push_TvbRange(L,tvbr->tvb->ws_tvb,tvbr->offset+offset,len)) {
|
|
WSLUA_RETURN(1); /* The TvbRange */
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_uncompress(lua_State* L) {
|
|
/* Obtain an uncompressed TvbRange from a TvbRange */
|
|
#define WSLUA_ARG_TvbRange_uncompress_NAME 2 /* The name to be given to the new data-source. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
#ifdef HAVE_LIBZ
|
|
const gchar* name = luaL_optstring(L,WSLUA_ARG_TvbRange_uncompress_NAME,"Uncompressed");
|
|
tvbuff_t *uncompr_tvb;
|
|
#endif
|
|
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
#ifdef HAVE_LIBZ
|
|
uncompr_tvb = tvb_child_uncompress(tvbr->tvb->ws_tvb, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len);
|
|
if (uncompr_tvb) {
|
|
add_new_data_source (lua_pinfo, uncompr_tvb, name);
|
|
if (push_TvbRange(L,uncompr_tvb,0,tvb_captured_length(uncompr_tvb))) {
|
|
WSLUA_RETURN(1); /* The TvbRange */
|
|
}
|
|
}
|
|
#else
|
|
luaL_error(L,"Missing support for ZLIB");
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
|
|
static int TvbRange__gc(lua_State* L) {
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
|
|
free_TvbRange(tvbr);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_len(lua_State* L) {
|
|
/* Obtain the length of a `TvbRange`. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
lua_pushnumber(L,(lua_Number)tvbr->len);
|
|
return 1;
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_offset(lua_State* L) {
|
|
/* Obtain the offset in a `TvbRange`. */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
lua_pushnumber(L,(lua_Number)tvbr->offset);
|
|
return 1;
|
|
}
|
|
|
|
WSLUA_METHOD TvbRange_raw(lua_State* L) {
|
|
/* Obtain a Lua string of the binary bytes in a `TvbRange`.
|
|
|
|
@since 1.11.3
|
|
*/
|
|
#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 = (int)luaL_optinteger(L,WSLUA_OPTARG_TvbRange_raw_OFFSET,0);
|
|
int len = (int)luaL_optinteger(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_captured_length(tvbr->tvb->ws_tvb)) {
|
|
WSLUA_OPTARG_ERROR(Tvb_raw,OFFSET,"offset beyond end of Tvb");
|
|
return 0;
|
|
}
|
|
|
|
if (len == -1) {
|
|
len = tvb_captured_length_remaining(tvbr->tvb->ws_tvb,offset);
|
|
if (len < 0) {
|
|
luaL_error(L,"out of bounds");
|
|
return FALSE;
|
|
}
|
|
} else if ( (guint)(len + offset) > tvb_captured_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. Since the string gets truncated,
|
|
you should use this only for debugging purposes
|
|
or if what you want is to have a truncated string in the format 67:89:AB:... */
|
|
TvbRange tvbr = checkTvbRange(L,1);
|
|
char* str = NULL;
|
|
|
|
if (!(tvbr && tvbr->tvb)) return 0;
|
|
if (tvbr->tvb->expired) {
|
|
luaL_error(L,"expired tvb");
|
|
return 0;
|
|
}
|
|
|
|
str = tvb_bytes_to_str(NULL,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len);
|
|
|
|
lua_pushstring(L,str);
|
|
wmem_free(NULL, str);
|
|
|
|
WSLUA_RETURN(1); /* A Lua hex string of the first 24 binary bytes in the `TvbRange`. */
|
|
}
|
|
|
|
WSLUA_METHODS TvbRange_methods[] = {
|
|
WSLUA_CLASS_FNREG(TvbRange,uint),
|
|
WSLUA_CLASS_FNREG(TvbRange,le_uint),
|
|
WSLUA_CLASS_FNREG(TvbRange,int),
|
|
WSLUA_CLASS_FNREG(TvbRange,le_int),
|
|
WSLUA_CLASS_FNREG(TvbRange,uint64),
|
|
WSLUA_CLASS_FNREG(TvbRange,le_uint64),
|
|
WSLUA_CLASS_FNREG(TvbRange,int64),
|
|
WSLUA_CLASS_FNREG(TvbRange,le_int64),
|
|
WSLUA_CLASS_FNREG(TvbRange,float),
|
|
WSLUA_CLASS_FNREG(TvbRange,le_float),
|
|
WSLUA_CLASS_FNREG(TvbRange,ether),
|
|
WSLUA_CLASS_FNREG(TvbRange,ipv4),
|
|
WSLUA_CLASS_FNREG(TvbRange,le_ipv4),
|
|
WSLUA_CLASS_FNREG(TvbRange,nstime),
|
|
WSLUA_CLASS_FNREG(TvbRange,le_nstime),
|
|
WSLUA_CLASS_FNREG(TvbRange,string),
|
|
WSLUA_CLASS_FNREG(TvbRange,stringz),
|
|
WSLUA_CLASS_FNREG(TvbRange,strsize),
|
|
WSLUA_CLASS_FNREG(TvbRange,bytes),
|
|
WSLUA_CLASS_FNREG(TvbRange,bitfield),
|
|
WSLUA_CLASS_FNREG(TvbRange,range),
|
|
WSLUA_CLASS_FNREG(TvbRange,len),
|
|
WSLUA_CLASS_FNREG(TvbRange,offset),
|
|
WSLUA_CLASS_FNREG(TvbRange,tvb),
|
|
WSLUA_CLASS_FNREG(TvbRange,le_ustring),
|
|
WSLUA_CLASS_FNREG(TvbRange,ustring),
|
|
WSLUA_CLASS_FNREG(TvbRange,le_ustringz),
|
|
WSLUA_CLASS_FNREG(TvbRange,ustringz),
|
|
WSLUA_CLASS_FNREG(TvbRange,uncompress),
|
|
WSLUA_CLASS_FNREG(TvbRange,raw),
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
WSLUA_META TvbRange_meta[] = {
|
|
WSLUA_CLASS_MTREG(TvbRange,tostring),
|
|
WSLUA_CLASS_MTREG(wslua,concat),
|
|
{"__call", TvbRange_range},
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
int TvbRange_register(lua_State* L) {
|
|
outstanding_Tvb = g_ptr_array_new();
|
|
outstanding_TvbRange = g_ptr_array_new();
|
|
WSLUA_REGISTER_CLASS(TvbRange);
|
|
return 0;
|
|
}
|
|
|