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; } if (encoding == 0) { ba = g_byte_array_new(); 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; ba = g_byte_array_new(); 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 Tvb_bytes(lua_State* L) { /* Obtain a `ByteArray` from a `Tvb`. @since 1.99.8 */ #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; } 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; } ba = g_byte_array_new(); 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. */ }
/* the following is used by TreeItem_add_packet_field() - this can THROW errors */ static proto_item * try_add_packet_field(lua_State *L, TreeItem tree_item, TvbRange tvbr, const int hfid, const ftenum_t type, const guint encoding, gint *ret_err) { gint err = 0; proto_item* item = NULL; gint endoff = 0; switch(type) { /* these all generate ByteArrays */ case FT_BYTES: case FT_UINT_BYTES: case FT_OID: case FT_REL_OID: case FT_SYSTEM_ID: { /* GByteArray and its data will be g_free'd by Lua */ GByteArray *gba = g_byte_array_new(); item = proto_tree_add_bytes_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, encoding, gba, &endoff, &err); if (err == 0) { pushByteArray(L, gba); lua_pushinteger(L, endoff); } } break; case FT_ABSOLUTE_TIME: case FT_RELATIVE_TIME: { /* nstime_t will be g_free'd by Lua */ nstime_t *nstime = (nstime_t *) g_malloc0(sizeof(nstime_t)); item = proto_tree_add_time_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, encoding, nstime, &endoff, &err); if (err == 0) { pushNSTime(L,nstime); lua_pushinteger(L, endoff); } } break; /* XXX: what about these? */ case FT_NONE: case FT_PROTOCOL: /* anything else just needs to be done the old fashioned way */ default: item = proto_tree_add_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, encoding); lua_pushnil(L); lua_pushnil(L); break; } if (ret_err) *ret_err = err; return item; }
WSLUA_METHOD ByteArray_append(lua_State* L) { /* Append a ByteArray to this ByteArray */ #define WSLUA_ARG_ByteArray_append_APPENDED 2 /* Array to be appended */ ByteArray ba = checkByteArray(L,1); ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray_append_APPENDED); if (! (ba && ba2) ) WSLUA_ERROR(ByteArray_append,"Both arguments must be ByteArrays"); g_byte_array_append(ba,ba2->data,ba2->len); pushByteArray(L,ba); return 1; }
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__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 ba = checkByteArray(L,WSLUA_ARG_ByteArray__cat_FIRST); ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray__cat_SECOND); if (! (ba && ba2) ) WSLUA_ERROR(ByteArray__cat,"Both arguments must be ByteArrays"); g_byte_array_append(ba,ba2->data,ba2->len); pushByteArray(L,ba); WSLUA_RETURN(1); /* The new composite ByteArray. */ }
WSLUA_METHOD TvbRange_bytes(lua_State* L) { /* Obtain a ByteArray */ TvbRange tvbr = checkTvbRange(L,1); GByteArray* ba; if ( !(tvbr && tvbr->tvb)) return 0; if (tvbr->tvb->expired) { luaL_error(L,"expired tvb"); return 0; } ba = g_byte_array_new(); 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); WSLUA_RETURN(1); /* The ByteArray */ }
WSLUA_METHOD ByteArray_base64_decode(lua_State* L) { /* Obtain a base64 decoded ByteArray */ 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_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" */ GByteArray* ba = g_byte_array_new(); const gchar* s; int nibble[2]; int i = 0; gchar c; if (lua_gettop(L) == 1) { s = luaL_checkstring(L,WSLUA_OPTARG_ByteArray_new_HEXBYTES); 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 ( i == 2 ) { guint8 b = (guint8)(nibble[0] * 16 + nibble[1]); g_byte_array_append(ba,&b,1); i = 0; } } } pushByteArray(L,ba); WSLUA_RETURN(1); /* The new ByteArray object. */ }
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 = luaL_checkint(L,WSLUA_ARG_ByteArray_set_index_OFFSET); int len = luaL_checkint(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 contaning the requested segment. */ }
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; 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 (!s) { WSLUA_OPTARG_ERROR(ByteArray_new,HEXBYTES,"must be a string"); return 0; } 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. */ }
WSLUA_METAMETHOD FieldInfo__call(lua_State* L) { /* Obtain the Value of the field */ FieldInfo fi = checkFieldInfo(L,1); switch(fi->hfinfo->type) { case FT_BOOLEAN: lua_pushboolean(L,(int)fvalue_get_uinteger(&(fi->value))); return 1; case FT_UINT8: case FT_UINT16: case FT_UINT24: case FT_UINT32: case FT_FRAMENUM: lua_pushnumber(L,(lua_Number)fvalue_get_uinteger(&(fi->value))); return 1; case FT_INT8: case FT_INT16: case FT_INT24: case FT_INT32: lua_pushnumber(L,(lua_Number)fvalue_get_sinteger(&(fi->value))); return 1; case FT_FLOAT: case FT_DOUBLE: lua_pushnumber(L,(lua_Number)fvalue_get_floating(&(fi->value))); return 1; case FT_INT64: { Int64 num = (Int64)g_malloc(sizeof(gint64)); *num = fvalue_get_integer64(&(fi->value)); pushInt64(L,num); return 1; } case FT_UINT64: { UInt64 num = (UInt64)g_malloc(sizeof(guint64)); *num = fvalue_get_integer64(&(fi->value)); pushUInt64(L,num); return 1; } case FT_ETHER: { Address eth = (Address)g_malloc(sizeof(address)); eth->type = AT_ETHER; eth->len = fi->length; eth->data = tvb_memdup(NULL,fi->ds_tvb,fi->start,fi->length); pushAddress(L,eth); return 1; } case FT_IPv4:{ Address ipv4 = (Address)g_malloc(sizeof(address)); ipv4->type = AT_IPv4; ipv4->len = fi->length; ipv4->data = tvb_memdup(NULL,fi->ds_tvb,fi->start,fi->length); pushAddress(L,ipv4); return 1; } case FT_IPv6: { Address ipv6 = (Address)g_malloc(sizeof(address)); ipv6->type = AT_IPv6; ipv6->len = fi->length; ipv6->data = tvb_memdup(NULL,fi->ds_tvb,fi->start,fi->length); pushAddress(L,ipv6); return 1; } case FT_IPXNET:{ Address ipx = (Address)g_malloc(sizeof(address)); ipx->type = AT_IPX; ipx->len = fi->length; ipx->data = tvb_memdup(NULL,fi->ds_tvb,fi->start,fi->length); pushAddress(L,ipx); return 1; } case FT_ABSOLUTE_TIME: case FT_RELATIVE_TIME: { NSTime nstime = (NSTime)g_malloc(sizeof(nstime_t)); *nstime = *(NSTime)fvalue_get(&(fi->value)); pushNSTime(L,nstime); return 1; } case FT_STRING: case FT_STRINGZ: { gchar* repr = fvalue_to_string_repr(&fi->value,FTREPR_DISPLAY,NULL); if (repr) lua_pushstring(L,repr); else luaL_error(L,"field cannot be represented as string because it may contain invalid characters"); return 1; } case FT_NONE: if (fi->length == 0) { lua_pushnil(L); return 1; } /* FALLTHROUGH */ case FT_BYTES: case FT_UINT_BYTES: case FT_GUID: case FT_PROTOCOL: case FT_REL_OID: case FT_SYSTEM_ID: case FT_OID: { ByteArray ba = g_byte_array_new(); g_byte_array_append(ba, (const guint8 *)tvb_memdup(wmem_packet_scope(),fi->ds_tvb,fi->start,fi->length),fi->length); pushByteArray(L,ba); return 1; } default: luaL_error(L,"FT_ not yet supported"); return 1; } }
/* WSLUA_ATTRIBUTE FieldInfo_value RO The value of this field. */ WSLUA_METAMETHOD FieldInfo__call(lua_State* L) { /* Obtain the Value of the field. Previous to 1.11.4, this function retrieved the value for most field types, but for `ftypes.UINT_BYTES` it retrieved the `ByteArray` of the field's entire `TvbRange`. In other words, it returned a `ByteArray` that included the leading length byte(s), instead of just the *value* bytes. That was a bug, and has been changed in 1.11.4. Furthermore, it retrieved an `ftypes.GUID` as a `ByteArray`, which is also incorrect. If you wish to still get a `ByteArray` of the `TvbRange`, use `FieldInfo:get_range()` to get the `TvbRange`, and then use `Tvb:bytes()` to convert it to a `ByteArray`. */ FieldInfo fi = checkFieldInfo(L,1); switch(fi->ws_fi->hfinfo->type) { case FT_BOOLEAN: lua_pushboolean(L,(int)fvalue_get_uinteger(&(fi->ws_fi->value))); return 1; case FT_UINT8: case FT_UINT16: case FT_UINT24: case FT_UINT32: case FT_FRAMENUM: lua_pushnumber(L,(lua_Number)(fvalue_get_uinteger(&(fi->ws_fi->value)))); return 1; case FT_INT8: case FT_INT16: case FT_INT24: case FT_INT32: lua_pushnumber(L,(lua_Number)(fvalue_get_sinteger(&(fi->ws_fi->value)))); return 1; case FT_FLOAT: case FT_DOUBLE: lua_pushnumber(L,(lua_Number)(fvalue_get_floating(&(fi->ws_fi->value)))); return 1; case FT_INT64: { pushInt64(L,(Int64)(fvalue_get_sinteger64(&(fi->ws_fi->value)))); return 1; } case FT_UINT64: { pushUInt64(L,fvalue_get_uinteger64(&(fi->ws_fi->value))); return 1; } case FT_ETHER: { Address eth = (Address)g_malloc(sizeof(address)); eth->type = AT_ETHER; eth->len = fi->ws_fi->length; eth->data = tvb_memdup(NULL,fi->ws_fi->ds_tvb,fi->ws_fi->start,fi->ws_fi->length); pushAddress(L,eth); return 1; } case FT_IPv4:{ Address ipv4 = (Address)g_malloc(sizeof(address)); ipv4->type = AT_IPv4; ipv4->len = fi->ws_fi->length; ipv4->data = tvb_memdup(NULL,fi->ws_fi->ds_tvb,fi->ws_fi->start,fi->ws_fi->length); pushAddress(L,ipv4); return 1; } case FT_IPv6: { Address ipv6 = (Address)g_malloc(sizeof(address)); ipv6->type = AT_IPv6; ipv6->len = fi->ws_fi->length; ipv6->data = tvb_memdup(NULL,fi->ws_fi->ds_tvb,fi->ws_fi->start,fi->ws_fi->length); pushAddress(L,ipv6); return 1; } case FT_FCWWN: { Address fcwwn = (Address)g_malloc(sizeof(address)); fcwwn->type = AT_FCWWN; fcwwn->len = fi->ws_fi->length; fcwwn->data = tvb_memdup(NULL,fi->ws_fi->ds_tvb,fi->ws_fi->start,fi->ws_fi->length); pushAddress(L,fcwwn); return 1; } case FT_IPXNET:{ Address ipx = (Address)g_malloc(sizeof(address)); ipx->type = AT_IPX; ipx->len = fi->ws_fi->length; ipx->data = tvb_memdup(NULL,fi->ws_fi->ds_tvb,fi->ws_fi->start,fi->ws_fi->length); pushAddress(L,ipx); return 1; } case FT_ABSOLUTE_TIME: case FT_RELATIVE_TIME: { NSTime nstime = (NSTime)g_malloc(sizeof(nstime_t)); *nstime = *(NSTime)fvalue_get(&(fi->ws_fi->value)); pushNSTime(L,nstime); return 1; } case FT_STRING: case FT_STRINGZ: { gchar* repr = fvalue_to_string_repr(&fi->ws_fi->value,FTREPR_DISPLAY,BASE_NONE,NULL); if (repr) lua_pushstring(L,repr); else luaL_error(L,"field cannot be represented as string because it may contain invalid characters"); return 1; } case FT_NONE: if (fi->ws_fi->length > 0 && fi->ws_fi->rep) { /* it has a length, but calling fvalue_get() on an FT_NONE asserts, so get the label instead (it's a FT_NONE, so a label is what it basically is) */ lua_pushstring(L, fi->ws_fi->rep->representation); return 1; } return 0; case FT_BYTES: case FT_UINT_BYTES: case FT_REL_OID: case FT_SYSTEM_ID: case FT_OID: { ByteArray ba = g_byte_array_new(); g_byte_array_append(ba, (const guint8 *) fvalue_get(&fi->ws_fi->value), fvalue_length(&fi->ws_fi->value)); pushByteArray(L,ba); return 1; } case FT_PROTOCOL: { ByteArray ba = g_byte_array_new(); tvbuff_t* tvb = (tvbuff_t *) fvalue_get(&fi->ws_fi->value); g_byte_array_append(ba, (const guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0, tvb_captured_length(tvb)), tvb_captured_length(tvb)); pushByteArray(L,ba); return 1; } case FT_GUID: default: luaL_error(L,"FT_ not yet supported"); return 1; } }
WSLUA_METAMETHOD FieldInfo__call(lua_State* L) { /* Obtain the Value of the field */ FieldInfo fi = checkFieldInfo(L,1); switch(fi->hfinfo->type) { case FT_NONE: lua_pushnil(L); return 1; case FT_UINT8: case FT_UINT16: case FT_UINT24: case FT_UINT32: case FT_FRAMENUM: lua_pushnumber(L,(lua_Number)fvalue_get_uinteger(&(fi->value))); return 1; case FT_INT8: case FT_INT16: case FT_INT24: case FT_INT32: lua_pushnumber(L,(lua_Number)fvalue_get_sinteger(&(fi->value))); return 1; case FT_FLOAT: case FT_DOUBLE: lua_pushnumber(L,(lua_Number)fvalue_get_floating(&(fi->value))); return 1; case FT_INT64: { Int64 num = g_malloc(sizeof(gint64)); *num = fvalue_get_integer64(&(fi->value)); pushInt64(L,num); return 1; } case FT_UINT64: { UInt64 num = g_malloc(sizeof(guint64)); *num = fvalue_get_integer64(&(fi->value)); pushUInt64(L,num); return 1; } case FT_ETHER: { Address eth = g_malloc(sizeof(address)); eth->type = AT_ETHER; eth->len = fi->length; eth->data = tvb_memdup(fi->ds_tvb,fi->start,fi->length); pushAddress(L,eth); return 1; } case FT_IPv4:{ Address ipv4 = g_malloc(sizeof(address)); ipv4->type = AT_IPv4; ipv4->len = fi->length; ipv4->data = tvb_memdup(fi->ds_tvb,fi->start,fi->length); pushAddress(L,ipv4); return 1; } case FT_IPv6: { Address ipv6 = g_malloc(sizeof(address)); ipv6->type = AT_IPv6; ipv6->len = fi->length; ipv6->data = tvb_memdup(fi->ds_tvb,fi->start,fi->length); pushAddress(L,ipv6); return 1; } case FT_IPXNET:{ Address ipx = g_malloc(sizeof(address)); ipx->type = AT_IPX; ipx->len = fi->length; ipx->data = tvb_memdup(fi->ds_tvb,fi->start,fi->length); pushAddress(L,ipx); return 1; } case FT_STRING: case FT_STRINGZ: { gchar* repr = fvalue_to_string_repr(&fi->value,FTREPR_DISPLAY,NULL); if (repr) lua_pushstring(L,repr); else luaL_error(L,"field cannot be represented as string because it may contain invalid characters"); return 1; } case FT_BYTES: case FT_UINT_BYTES: case FT_GUID: case FT_OID: { ByteArray ba = g_byte_array_new(); g_byte_array_append(ba, ep_tvb_memdup(fi->ds_tvb,fi->start,fi->length),fi->length); pushByteArray(L,ba); return 1; } default: luaL_error(L,"FT_ not yet supported"); return 1; } }