Bug Summary

File:builds/wireshark/wireshark/epan/wslua/wslua_tree.c
Warning:line 784, column 5
Undefined or garbage value returned to caller

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name wslua_tree.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/lua5.4 -isystem /builds/wireshark/wireshark/build/epan/wslua -isystem /builds/wireshark/wireshark/epan/wslua -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2026-04-29-100349-3642-1 -x c /builds/wireshark/wireshark/epan/wslua/wslua_tree.c
1/*
2 * wslua_tree.c
3 *
4 * Wireshark's interface to the Lua Programming Language
5 *
6 * (c) 2006, Luis E. Garcia Ontanon <[email protected]>
7 * (c) 2008, Balint Reczey <[email protected]>
8 *
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <[email protected]>
11 * Copyright 1998 Gerald Combs
12 *
13 * SPDX-License-Identifier: GPL-2.0-or-later
14 */
15
16#include "config.h"
17
18/* WSLUA_MODULE Tree Adding Information To The Dissection Tree */
19
20#include "wslua.h"
21#include <epan/exceptions.h>
22#include <epan/show_exception.h>
23
24static int wslua_ett = -1;
25
26static GPtrArray* outstanding_TreeItem;
27
28
29/* pushing a TreeItem with a NULL item or subtree is completely valid for this function */
30TreeItem push_TreeItem(lua_State *L, proto_tree *tree, proto_item *item) {
31 TreeItem ti = g_new(struct _wslua_treeitem, 1)((struct _wslua_treeitem *) g_malloc_n ((1), sizeof (struct _wslua_treeitem
)))
;
32
33 ti->tree = tree;
34 ti->item = item;
35 ti->expired = false0;
36
37 g_ptr_array_add(outstanding_TreeItem, ti);
38
39 return *(pushTreeItem(L,ti));
40}
41
42/* creates the TreeItem but does NOT push it into Lua */
43TreeItem create_TreeItem(proto_tree* tree, proto_item* item)
44{
45 TreeItem tree_item = (TreeItem)g_malloc(sizeof(struct _wslua_treeitem));
46 tree_item->tree = tree;
47 tree_item->item = item;
48 tree_item->expired = false0;
49
50 return tree_item;
51}
52
53CLEAR_OUTSTANDING(TreeItem, expired, true)void clear_outstanding_TreeItem(void) { while (outstanding_TreeItem
->len) { TreeItem p = (TreeItem)g_ptr_array_remove_index_fast
(outstanding_TreeItem,0); if (p) { if (p->expired != 1) p->
expired = 1; else g_free(p); } } }
54
55WSLUA_CLASS_DEFINE(TreeItem,FAIL_ON_NULL_OR_EXPIRED("TreeItem"))TreeItem toTreeItem(lua_State* L, int idx) { TreeItem* v = (TreeItem
*)lua_touserdata (L, idx); if (!v) luaL_error(L, "bad argument %d (%s expected, got %s)"
, idx, "TreeItem", lua_typename(L, lua_type(L, idx))); return
v ? *v : ((void*)0); } TreeItem checkTreeItem(lua_State* L, int
idx) { TreeItem* p; luaL_checktype(L,idx,7); p = (TreeItem*)
luaL_checkudata(L, idx, "TreeItem"); if (!*p) { luaL_argerror
(L,idx,"null " "TreeItem"); } else if ((*p)->expired) { luaL_argerror
(L,idx,"expired " "TreeItem"); }; return p ? *p : ((void*)0);
} TreeItem* pushTreeItem(lua_State* L, TreeItem v) { TreeItem
* p; luaL_checkstack(L,2,"Unable to grow stack\n"); p = (TreeItem
*)lua_newuserdatauv(L,sizeof(TreeItem),1); *p = v; (lua_getfield
(L, (-1000000 - 1000), ("TreeItem"))); lua_setmetatable(L, -2
); return p; }_Bool isTreeItem(lua_State* L,int i) { void *p;
if(!lua_isuserdata(L,i)) return 0; p = lua_touserdata(L, i);
lua_getfield(L, (-1000000 - 1000), "TreeItem"); if (p == ((void
*)0) || !lua_getmetatable(L, i) || !lua_rawequal(L, -1, -2)) p
=((void*)0); lua_settop(L, -(2)-1); return p ? 1 : 0; } TreeItem
shiftTreeItem(lua_State* L,int i) { TreeItem* p; if(!lua_isuserdata
(L,i)) return ((void*)0); p = (TreeItem*)lua_touserdata(L, i)
; lua_getfield(L, (-1000000 - 1000), "TreeItem"); if (p == ((
void*)0) || !lua_getmetatable(L, i) || !lua_rawequal(L, -1, -
2)) p=((void*)0); lua_settop(L, -(2)-1); if (p) { (lua_rotate
(L, (i), -1), lua_settop(L, -(1)-1)); return *p; } else return
((void*)0);} typedef int dummyTreeItem
;
56/* <<lua_class_TreeItem,`TreeItem`>>s represent information in the https://www.wireshark.org/docs/wsug_html_chunked/ChUsePacketDetailsPaneSection.html[packet details] pane of Wireshark, and the packet details view of TShark.
57 A <<lua_class_TreeItem,`TreeItem`>> represents a node in the tree, which might also be a subtree and have a list of children.
58 The children of a subtree have zero or more siblings which are other children of the same <<lua_class_TreeItem,`TreeItem`>> subtree.
59
60 During dissection, heuristic-dissection, and post-dissection, a root <<lua_class_TreeItem,`TreeItem`>> is passed to dissectors as the third argument of the function
61 callback (e.g., `myproto.dissector(tvbuf,pktinfo,root)`).
62
63 In some cases the tree is not truly added to, in order to improve performance.
64 For example for packets not currently displayed/selected in Wireshark's visible
65 window pane, or if TShark isn't invoked with the `-V` switch. However the
66 "add" type <<lua_class_TreeItem,`TreeItem`>> functions can still be called, and still return <<lua_class_TreeItem,`TreeItem`>>
67 objects - but the info isn't really added to the tree. Therefore you do not
68 typically need to worry about whether there's a real tree or not. If, for some
69 reason, you need to know it, you can use the <<lua_class_attrib_treeitem_visible,`TreeItem.visible`>> attribute getter
70 to retrieve the state.
71 */
72
73/* the following is used by TreeItem_add_packet_field() - this can THROW errors */
74static proto_item *
75try_add_packet_field(lua_State *L, TreeItem tree_item, TvbRange tvbr, const int hfid,
76 const ftenum_t type, const unsigned encoding, int *ret_err)
77{
78 int err = 0;
79 proto_item *volatile item = NULL((void*)0);
80 unsigned endoff = 0;
81
82 switch(type) {
83 /* these all generate ByteArrays */
84 case FT_BYTES:
85 case FT_UINT_BYTES:
86 case FT_OID:
87 case FT_REL_OID:
88 case FT_SYSTEM_ID:
89 {
90 /* GByteArray and its data will be g_free'd by Lua */
91 GByteArray *gba = g_byte_array_new();
92 item = proto_tree_add_bytes_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
93 tvbr->offset, tvbr->len, encoding,
94 gba, &endoff, &err);
95 if (err == 0) {
96 pushByteArray(L, gba);
97 lua_pushinteger(L, endoff);
98 }
99 }
100 break;
101
102 case FT_ABSOLUTE_TIME:
103 case FT_RELATIVE_TIME:
104 {
105 /* nstime_t will be g_free'd by Lua */
106 nstime_t *nstime = g_new0(nstime_t, 1)((nstime_t *) g_malloc0_n ((1), sizeof (nstime_t)));
107 item = proto_tree_add_time_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
108 tvbr->offset, tvbr->len, encoding,
109 nstime, &endoff, &err);
110 if (err == 0) {
111 pushNSTime(L,nstime);
112 lua_pushinteger(L, endoff);
113 }
114 }
115 break;
116
117 case FT_INT8:
118 case FT_INT16:
119 case FT_INT24:
120 case FT_INT32:
121 {
122 int32_t ret;
123 item = proto_tree_add_item_ret_int(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
124 tvbr->offset, tvbr->len, encoding,
125 &ret);
126 lua_pushinteger(L, (lua_Integer)ret);
127 lua_pushinteger(L, tvbr->offset + tvbr->len);
128 }
129 break;
130
131 case FT_INT40:
132 case FT_INT48:
133 case FT_INT56:
134 case FT_INT64:
135 {
136 int64_t ret;
137 item = proto_tree_add_item_ret_int64(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
138 tvbr->offset, tvbr->len, encoding,
139 &ret);
140 pushInt64(L, ret);
141 lua_pushinteger(L, tvbr->offset + tvbr->len);
142 }
143 break;
144
145 case FT_CHAR:
146 case FT_UINT8:
147 case FT_UINT16:
148 case FT_UINT24:
149 case FT_UINT32:
150 {
151 uint32_t ret;
152 item = proto_tree_add_item_ret_uint(tree_item-> tree, hfid, tvbr->tvb->ws_tvb,
153 tvbr->offset, tvbr->len, encoding,
154 &ret);
155 lua_pushinteger(L, (lua_Integer)ret);
156 lua_pushinteger(L, tvbr->offset + tvbr->len);
157 }
158 break;
159
160 case FT_UINT40:
161 case FT_UINT48:
162 case FT_UINT56:
163 case FT_UINT64:
164 {
165 uint64_t ret;
166 item = proto_tree_add_item_ret_uint64(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
167 tvbr->offset, tvbr->len, encoding,
168 &ret);
169 pushUInt64(L, ret);
170 lua_pushinteger(L, tvbr->offset + tvbr->len);
171 }
172 break;
173
174 case FT_BOOLEAN:
175 {
176 bool_Bool ret;
177 item = proto_tree_add_item_ret_boolean(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
178 tvbr->offset, tvbr->len, encoding,
179 &ret);
180 lua_pushboolean(L, ret);
181 lua_pushinteger(L, tvbr->offset + tvbr->len);
182 }
183 break;
184
185 case FT_STRING:
186 case FT_STRINGZ:
187 case FT_STRINGZPAD:
188 case FT_STRINGZTRUNC:
189 case FT_UINT_STRING:
190 {
191 const uint8_t *ret;
192 int len;
193 item = proto_tree_add_item_ret_string_and_length(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
194 tvbr->offset, tvbr->len, encoding,
195 NULL((void*)0), &ret, &len);
196 lua_pushstring(L, (const char*)ret);
197 lua_pushinteger(L, tvbr->offset + len);
198 wmem_free(NULL((void*)0), (void*)ret);
199 }
200 break;
201
202 case FT_FLOAT:
203 {
204 float ret;
205 item = proto_tree_add_item_ret_float(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
206 tvbr->offset, tvbr->len, encoding,
207 &ret);
208 lua_pushnumber(L, (lua_Number)ret);
209 lua_pushinteger(L, tvbr->offset + tvbr->len);
210 }
211 break;
212
213 case FT_DOUBLE:
214 {
215 double ret;
216 item = proto_tree_add_item_ret_double(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
217 tvbr->offset, tvbr->len, encoding,
218 &ret);
219 lua_pushnumber(L, (lua_Number)ret);
220 lua_pushinteger(L, tvbr->offset + tvbr->len);
221 }
222 break;
223
224 case FT_IPv4:
225 {
226 Address addr = g_new(address,1)((address *) g_malloc_n ((1), sizeof (address)));
227 ws_in4_addr ret;
228 item = proto_tree_add_item_ret_ipv4(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
229 tvbr->offset, tvbr->len, encoding,
230 &ret);
231 alloc_address_wmem(NULL((void*)0), addr, AT_IPv4, sizeof(ret), &ret);
232 pushAddress(L, addr);
233 lua_pushinteger(L, tvbr->offset + tvbr->len);
234 }
235 break;
236
237 case FT_IPv6:
238 {
239 Address addr = g_new(address, 1)((address *) g_malloc_n ((1), sizeof (address)));
240 ws_in6_addr ret;
241 item = proto_tree_add_item_ret_ipv6(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
242 tvbr->offset, tvbr->len, encoding,
243 &ret);
244 alloc_address_wmem(NULL((void*)0), addr, AT_IPv6, sizeof(ret), &ret);
245 pushAddress(L, addr);
246 lua_pushinteger(L, tvbr->offset + tvbr->len);
247 }
248 break;
249
250 case FT_ETHER:
251 {
252 Address addr = g_new(address, 1)((address *) g_malloc_n ((1), sizeof (address)));
253 uint8_t bytes[FT_ETHER_LEN6];
254
255 item = proto_tree_add_item_ret_ether(tree_item->tree, hfid, tvbr->tvb->ws_tvb,
256 tvbr->offset, tvbr->len, encoding,
257 bytes);
258 alloc_address_wmem(NULL((void*)0), addr, AT_ETHER, sizeof(bytes), bytes);
259 pushAddress(L, addr);
260 lua_pushinteger(L, tvbr->offset + tvbr->len);
261 }
262 break;
263
264 default:
265 item = proto_tree_add_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, encoding);
266 lua_pushnil(L);
267 lua_pushnil(L);
268 break;
269 }
270
271 if (ret_err) *ret_err = err;
272
273 return item;
274}
275
276WSLUA_METHODstatic int TreeItem_add_packet_field(lua_State *L) {
277 /*
278 Adds a new child tree for the given <<lua_class_ProtoField,`ProtoField`>> object to this tree item,
279 returning the new child <<lua_class_TreeItem,`TreeItem`>>.
280
281 Unlike `TreeItem:add()` and `TreeItem:add_le()`, the <<lua_class_ProtoField,`ProtoField`>> argument
282 is not optional, and cannot be a `Proto` object. Instead, this function always
283 uses the <<lua_class_ProtoField,`ProtoField`>> to determine the type of field to extract from the
284 passed-in `TvbRange`, highlighting the relevant bytes in the Packet Bytes pane
285 of the GUI (if there is a GUI), etc. If no <<lua_class_TvbRange,`TvbRange`>>is given, no bytes are
286 highlighted and the field's value cannot be determined; the <<lua_class_ProtoField,`ProtoField`>> must
287 have been defined/created not to have a length in such a case, or an error will
288 occur. For backwards-compatibility reasons the `encoding` argument, however,
289 must still be given.
290
291 Unlike `TreeItem:add()` and `TreeItem:add_le()`, this function performs both
292 big-endian and little-endian decoding, by setting the `encoding` argument to
293 be `ENC_BIG_ENDIAN` or `ENC_LITTLE_ENDIAN`.
294
295 The signature of this function:
296
297 [source,lua]
298 ----
299 tree_item:add_packet_field(proto_field [,tvbrange], encoding, ...)
300 ----
301
302 This function returns more than just the new child <<lua_class_TreeItem,`TreeItem`>>.
303 The child is the first return value, so that function chaining will still work; but it
304 also returns more information. The second return is the value of the extracted field
305 (i.e., a number, `UInt64`, `Address`, etc.). The third return is is the offset where
306 data should be read next. This is useful when the length of the field is not known in
307 advance. The additional return values may be null if the field type is not well supported
308 in the Lua API.
309
310 This function can extract a <<lua_class_ProtoField,`ProtoField`>> of type `ftypes.BYTES`
311 or `ftypes.ABSOLUTE_TIME` from a string in the `TvbRange` in ASCII-based and similar
312 encodings. For example, a `ProtoField` of `ftypes.BYTES` can be extracted from a `TvbRange`
313 containing the ASCII string "a1b2c3d4e5f6", and it will correctly decode the ASCII both in the
314 tree as well as for the second return value, which will be a <<lua_class_ByteArray,`ByteArray`>>.
315 To do so, you must set the `encoding` argument of this function to the appropriate string `ENC_*`
316 value, bitwise-or'd (or added) with the `ENC_STR_HEX` value and one or more `ENC_SEP_XXX` values
317 indicating which encodings are allowed. For `ftypes.ABSOLUTE_TIME`, one of the `ENC_ISO_8601_*`
318 encodings or `ENC_IMF_DATE_TIME` must be used, and the second return value is a <<lua_class_NSTime,`NSTime`>>.
319 Only single-byte ASCII digit string encodings such as `ENC_ASCII` and `ENC_UTF_8` can be used for this.
320
321 For example, assuming the <<lua_class_Tvb,`Tvb`>> named "`tvb`" contains the string "abcdef"
322 (61 62 63 64 65 66 in hex):
323
324 [source,lua]
325 ----
326 -- this is done earlier in the script
327 local myfield = ProtoField.new("Transaction ID", "myproto.trans_id", ftypes.BYTES)
328 myproto.fields = { myfield }
329
330 -- this is done inside a dissector, post-dissector, or heuristic function
331 -- child will be the created child tree, and value will be the ByteArray "abcdef" or nil on failure
332 local child, value = tree:add_packet_field(myfield, tvb:range(0,6), ENC_UTF_8 + ENC_STR_HEX + ENC_SEP_NONE)
333 ----
334
335 */
336#define WSLUA_ARG_TreeItem_add_packet_field_PROTOFIELD2 2 /* The ProtoField field object to add to the tree. */
337#define WSLUA_OPTARG_TreeItem_add_packet_field_TVBRANGE3 3 /* The <<lua_class_TvbRange,`TvbRange`>> of bytes in the packet this tree item covers/represents. */
338#define WSLUA_ARG_TreeItem_add_packet_field_ENCODING4 4 /* The field's encoding in the `TvbRange`. */
339#define WSLUA_OPTARG_TreeItem_add_packet_field_LABEL5 5 /* One or more strings to append to the created <<lua_class_TreeItem,`TreeItem`>>. */
340 volatile TvbRange tvbr;
341 ProtoField field;
342 int hfid;
343 volatile int ett;
344 ftenum_t type;
345 TreeItem tree_item = shiftTreeItem(L,1);
346 unsigned encoding;
347 proto_item* item = NULL((void*)0);
348 volatile int nargs;
349 volatile int err = 0;
350 const char *volatile error = NULL((void*)0);
351
352 if (!tree_item) {
353 return luaL_error(L,"not a TreeItem!");
354 }
355 if (tree_item->expired) {
356 luaL_error(L,"expired TreeItem");
357 return 0;
358 }
359
360 if (! ( field = shiftProtoField(L,1) ) ) {
361 luaL_error(L,"TreeField:add_packet_field not passed a ProtoField");
362 return 0;
363 }
364 if (field->hfid == -2) {
365 luaL_error(L, "ProtoField %s unregistered (not added to a Proto.fields attribute)", field->abbrev);
366 }
367 hfid = field->hfid;
368 type = field->type;
369 ett = field->ett;
370
371 tvbr = shiftTvbRange(L,1);
372 if (!tvbr) {
373 /* No TvbRange specified */
374 tvbr = wmem_new(lua_pinfo->pool, struct _wslua_tvbrange)((struct _wslua_tvbrange*)wmem_alloc((lua_pinfo->pool), sizeof
(struct _wslua_tvbrange)))
;
375 tvbr->tvb = wmem_new(lua_pinfo->pool, struct _wslua_tvb)((struct _wslua_tvb*)wmem_alloc((lua_pinfo->pool), sizeof(
struct _wslua_tvb)))
;
376 tvbr->tvb->ws_tvb = lua_tvb;
377 tvbr->offset = 0;
378 tvbr->len = 0;
379 }
380
381 encoding = wslua_checkuint(L,1)(unsigned) ( luaL_checkinteger(L,1) );
382 lua_remove(L,1)(lua_rotate(L, (1), -1), lua_settop(L, -(1)-1));
383
384 /* get the number of additional args before we add more to the stack */
385 nargs = lua_gettop(L);
386
387 /* XXX: why is this being done? If the length was -1, FT_STRINGZ figures out
388 * the right length in tvb_get_stringz_enc(); if it was 0, it should remain zero;
389 * if it was greater than zero, then it's the length the caller wanted.
390 */
391 if (type == FT_STRINGZ) {
392 switch (encoding & ENC_CHARENCODING_MASK0x0000FFFE) {
393
394 case ENC_UTF_160x00000004:
395 case ENC_UCS_20x00000006:
396 tvbr->len = tvb_unicode_strsize (tvbr->tvb->ws_tvb, tvbr->offset);
397 break;
398
399 default:
400 if (!tvb_find_uint8_remaining(tvbr->tvb->ws_tvb, tvbr->offset, 0, NULL((void*)0))) {
401 luaL_error(L,"out of bounds");
402 return 0;
403 }
404 tvbr->len = tvb_strsize (tvbr->tvb->ws_tvb, tvbr->offset);
405 break;
406 }
407 }
408
409 TRY{ except_t *volatile exc; volatile int except_state = 0; static
const except_id_t catch_spec[] = { { 1, 0 } }; { struct except_stacknode
except_sn; struct except_catch except_ch; except_setup_try(&
except_sn, &except_ch, catch_spec, 1); if (_setjmp (except_ch
.except_jmp)) *(&exc) = &except_ch.except_obj; else *
(&exc) = 0; if(except_state & 1) except_state |= 2; except_state
&= ~1; if (except_state == 0 && exc == 0)
{
410 int errx = 0;
411 item = try_add_packet_field(L, tree_item, tvbr, hfid, type, encoding, &errx);
412 err = errx;
413 } CATCH_ALLif (except_state == 0 && exc != 0 && (except_state
|=1))
{
414 show_exception(tvbr->tvb->ws_tvb, lua_pinfo, tree_item->tree, EXCEPT_CODE((exc)->except_id.except_code), GET_MESSAGE((exc)->except_message));
415 error = "Lua programming error";
416 } ENDTRYif(!(except_state&1) && exc != 0) except_rethrow(
exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}
;
417
418 if (error) { WSLUA_ERROR(TreeItem_add_packet_field,error){ luaL_error(L, "%s%s", "TreeItem_add_packet_field" ": ", error
); }
; }
419
420 if (err != 0) {
421 lua_pushnil(L);
422 lua_pushnil(L);
423 }
424
425 while(nargs) {
426 const char* s;
427 s = lua_tostring(L,1)lua_tolstring(L, (1), ((void*)0));
428 if (s) proto_item_append_text(item, " %s", s);
429 lua_remove(L,1)(lua_rotate(L, (1), -1), lua_settop(L, -(1)-1));
430 nargs--;
431 }
432
433 push_TreeItem(L, proto_item_add_subtree(item,ett > 0 ? ett : wslua_ett), item);
434
435 /* move the tree object before the field value */
436 lua_insert(L, 1)lua_rotate(L, (1), 1);
437
438 WSLUA_RETURN(3)return (3); /* The new child <<lua_class_TreeItem,`TreeItem`>>, the field's extracted value or nil, and offset or nil. */
439}
440
441/* The following is used by TreeItem_add() and TreeItem_le() and can THROW.
442 * It should be called inside a TRY (e.g. WRAP_NON_LUA_EXCEPTIONS) block and
443 * THROW_LUA_ERROR should be used insteadof lua[L]_error.
444 */
445static int TreeItem_add_item_any(lua_State *L, bool_Bool little_endian) {
446 TvbRange tvbr;
447 Proto proto;
448 ProtoField field;
449 int hfid = -1;
450 int ett = -1;
451 ftenum_t type = FT_NONE;
452 TreeItem tree_item = shiftTreeItem(L,1);
453 proto_item* item = NULL((void*)0);
454
455 if (!tree_item) {
456 THROW_LUA_ERROR("not a TreeItem!")except_throwf(1, (6), "not a TreeItem!");
457 }
458 if (tree_item->expired) {
459 THROW_LUA_ERROR("expired TreeItem")except_throwf(1, (6), "expired TreeItem");
460 return 0;
461 }
462
463 if (! ( field = shiftProtoField(L,1) ) ) {
464 if (( proto = shiftProto(L,1) )) {
465 hfid = proto->hfid;
466 type = FT_PROTOCOL;
467 ett = proto->ett;
468 } else if (lua_isnil(L, 1)(lua_type(L, (1)) == 0)) {
469 THROW_LUA_ERROR("first argument to TreeItem:add is nil!")except_throwf(1, (6), "first argument to TreeItem:add is nil!"
)
;
470 }
471 } else {
472 hfid = field->hfid;
473 type = field->type;
474 ett = field->ett;
475 }
476
477 tvbr = shiftTvbRange(L,1);
478
479 if (!tvbr) {
480 tvbr = wmem_new(lua_pinfo->pool, struct _wslua_tvbrange)((struct _wslua_tvbrange*)wmem_alloc((lua_pinfo->pool), sizeof
(struct _wslua_tvbrange)))
;
481 tvbr->tvb = wmem_new(lua_pinfo->pool, struct _wslua_tvb)((struct _wslua_tvb*)wmem_alloc((lua_pinfo->pool), sizeof(
struct _wslua_tvb)))
;
482 tvbr->tvb->ws_tvb = lua_tvb;
483 tvbr->offset = 0;
484 tvbr->len = 0;
485 }
486
487 if (hfid > 0 ) {
488 /* hfid is > 0 when the first arg was a ProtoField or Proto */
489
490 if (type == FT_STRINGZ) {
491 if (!tvb_find_uint8_remaining(tvbr->tvb->ws_tvb, tvbr->offset, 0, NULL((void*)0))) {
492 THROW_LUA_ERROR("out of bounds")except_throwf(1, (6), "out of bounds");
493 return 0;
494 }
495 tvbr->len = tvb_strsize (tvbr->tvb->ws_tvb, tvbr->offset);
496 }
497
498 if (lua_gettop(L)) {
499 /* if we got here, the (L,1) index is the value to add, instead of decoding from the Tvb */
500
501 /* It's invalid for it to be nil (which has been documented for
502 * a long time). Make sure we throw our error instead of an
503 * internal Lua error (due to nested setjmp/longjmp).
504 */
505 if (lua_isnil(L, 1)(lua_type(L, (1)) == 0)) {
506 THROW_LUA_ERROR("TreeItem:add value argument is nil!")except_throwf(1, (6), "TreeItem:add value argument is nil!");
507 }
508
509 switch(type) {
510 case FT_PROTOCOL:
511 item = proto_tree_add_item(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,ENC_NA0x00000000);
512 lua_pushinteger(L,0);
513 lua_insert(L,1)lua_rotate(L, (1), 1);
514 break;
515 case FT_BOOLEAN:
516 {
517 uint64_t val;
518 switch(lua_type(L, 1)) {
519
520 case LUA_TUSERDATA7:
521 val = checkUInt64(L, 1);
522 break;
523
524 default:
525 /* this needs to use checkinteger so that it can accept a Lua boolean and coerce it to an int */
526 val = (uint64_t) (wslua_tointeger(L,1));
527 }
528 item = proto_tree_add_boolean(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,val);
529 }
530 break;
531 case FT_CHAR:
532 case FT_UINT8:
533 case FT_UINT16:
534 case FT_UINT24:
535 case FT_UINT32:
536 case FT_FRAMENUM:
537 if (!lua_isnumber(L,1)) {
538 THROW_LUA_ERROR("Expected number for unsigned integer field")except_throwf(1, (6), "Expected number for unsigned integer field"
)
;
539 return 0;
540 }
541 item = proto_tree_add_uint(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,wslua_checkuint32(L,1)(uint32_t) ( luaL_checkinteger(L,1) ));
542 break;
543 case FT_INT8:
544 case FT_INT16:
545 case FT_INT24:
546 case FT_INT32:
547 if (!lua_isnumber(L,1)) {
548 THROW_LUA_ERROR("Expected number for integer field")except_throwf(1, (6), "Expected number for integer field");
549 return 0;
550 }
551 item = proto_tree_add_int(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,wslua_checkint32(L,1)(int32_t) ( luaL_checkinteger(L,1) ));
552 break;
553 case FT_FLOAT:
554 if (!lua_isnumber(L,1)) {
555 THROW_LUA_ERROR("Expected number for FT_FLOAT field")except_throwf(1, (6), "Expected number for FT_FLOAT field");
556 return 0;
557 }
558 item = proto_tree_add_float(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,(float)luaL_checknumber(L,1));
559 break;
560 case FT_DOUBLE:
561 if (!lua_isnumber(L,1)) {
562 THROW_LUA_ERROR("Expected number for FT_DOUBLE field")except_throwf(1, (6), "Expected number for FT_DOUBLE field");
563 return 0;
564 }
565 item = proto_tree_add_double(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,(double)luaL_checknumber(L,1));
566 break;
567 case FT_ABSOLUTE_TIME:
568 case FT_RELATIVE_TIME:
569 if (!isNSTime(L,1)) {
570 THROW_LUA_ERROR("Expected NSTime for %s field", (type==FT_ABSOLUTE_TIME ? "FT_ABSOLUTE_TIME" : "FT_RELATIVE_TIME"))except_throwf(1, (6), "Expected NSTime for %s field", (type==
FT_ABSOLUTE_TIME ? "FT_ABSOLUTE_TIME" : "FT_RELATIVE_TIME"))
;
571 return 0;
572 }
573 item = proto_tree_add_time(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,checkNSTime(L,1));
574 break;
575 case FT_STRING:
576 case FT_STRINGZ:
577 {
578 const char *value = lua_tostring(L, 1)lua_tolstring(L, (1), ((void*)0));
579 if (value == NULL((void*)0)) {
580 THROW_LUA_ERROR("Expected string for %s field", (type==FT_STRING ? "FT_STRING" : "FT_STRINGZ") )except_throwf(1, (6), "Expected string for %s field", (type==
FT_STRING ? "FT_STRING" : "FT_STRINGZ"))
;
581 return 0;
582 }
583 item = proto_tree_add_string(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,value);
584 }
585 break;
586 case FT_BYTES:
587 {
588 const char *value = lua_tostring(L, 1)lua_tolstring(L, (1), ((void*)0));
589 if (value == NULL((void*)0)) {
590 THROW_LUA_ERROR("Expected bytes for FT_BYTES field")except_throwf(1, (6), "Expected bytes for FT_BYTES field");
591 return 0;
592 }
593 item = proto_tree_add_bytes(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len, (const uint8_t*)value);
594 }
595 break;
596 case FT_UINT64:
597 if (!isUInt64(L,1)) {
598 THROW_LUA_ERROR("Expected UInt64 for FT_UINT64 field")except_throwf(1, (6), "Expected UInt64 for FT_UINT64 field");
599 return 0;
600 }
601 item = proto_tree_add_uint64(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,checkUInt64(L,1));
602 break;
603 case FT_INT64:
604 if (!isInt64(L,1)) {
605 THROW_LUA_ERROR("Expected Int64 for FT_INT64 field")except_throwf(1, (6), "Expected Int64 for FT_INT64 field");
606 return 0;
607 }
608 item = proto_tree_add_int64(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,checkInt64(L,1));
609 break;
610 case FT_IPv4:
611 {
612 Address addr = isAddress(L,1) ? checkAddress(L,1) : NULL((void*)0);
613 uint32_t addr_value;
614
615 if (addr == NULL((void*)0) || addr->type != AT_IPv4) {
616 THROW_LUA_ERROR("Expected IPv4 address for FT_IPv4 field")except_throwf(1, (6), "Expected IPv4 address for FT_IPv4 field"
)
;
617 return 0;
618 }
619
620 /*
621 * The address is not guaranteed to be aligned on a
622 * 32-bit boundary, so we can't safely dereference
623 * the pointer as if it were so aligned.
624 */
625 memcpy(&addr_value, addr->data, sizeof addr_value);
626 item = proto_tree_add_ipv4(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,addr_value);
627 }
628 break;
629 case FT_IPv6:
630 {
631 Address addr = isAddress(L,1) ? checkAddress(L,1) : NULL((void*)0);
632 if (addr == NULL((void*)0) || addr->type != AT_IPv6) {
633 THROW_LUA_ERROR("Expected IPv6 address for FT_IPv6 field")except_throwf(1, (6), "Expected IPv6 address for FT_IPv6 field"
)
;
634 return 0;
635 }
636
637 item = proto_tree_add_ipv6(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, (const ws_in6_addr *)addr->data);
638 }
639 break;
640 case FT_ETHER:
641 {
642 Address addr = isAddress(L,1) ? checkAddress(L,1) : NULL((void*)0);
643 if (addr == NULL((void*)0) || addr->type != AT_ETHER) {
644 THROW_LUA_ERROR("Expected MAC address for FT_ETHER field")except_throwf(1, (6), "Expected MAC address for FT_ETHER field"
)
;
645 return 0;
646 }
647
648 item = proto_tree_add_ether(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, (const uint8_t *)addr->data);
649 }
650 break;
651 case FT_UINT_BYTES:
652 case FT_IPXNET:
653 case FT_GUID:
654 case FT_OID:
655 case FT_REL_OID:
656 case FT_SYSTEM_ID:
657 case FT_VINES:
658 case FT_FCWWN:
659 default:
660 THROW_LUA_ERROR("%s not yet supported", ftype_name(type))except_throwf(1, (6), "%s not yet supported", ftype_name(type
))
;
661 return 0;
662 }
663
664 lua_remove(L,1)(lua_rotate(L, (1), -1), lua_settop(L, -(1)-1));
665
666 } else {
667 if (type == FT_FRAMENUM) {
668 THROW_LUA_ERROR("ProtoField FRAMENUM cannot fetch value from Tvb")except_throwf(1, (6), "ProtoField FRAMENUM cannot fetch value from Tvb"
)
;
669 return 0;
670 }
671 /* the Lua stack is empty - no value was given - so decode the value from the tvb */
672 item = proto_tree_add_item(tree_item->tree, hfid, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, little_endian ? ENC_LITTLE_ENDIAN0x80000000 : ENC_BIG_ENDIAN0x00000000);
673 }
674
675 if ( lua_gettop(L) ) {
676 /* if there was a value, it was removed earlier, so what's left is the display string to set */
677 const char* s = lua_tostring(L,1)lua_tolstring(L, (1), ((void*)0));
678 if (s) proto_item_set_text(item,"%s",s);
679 lua_remove(L,1)(lua_rotate(L, (1), -1), lua_settop(L, -(1)-1));
680 }
681
682 } else {
683 /* no ProtoField or Proto was given - we're adding a text-only field,
684 * any remaining parameters are parts of the text label. */
685 if (lua_gettop(L)) {
686 const char* s = lua_tostring(L,1)lua_tolstring(L, (1), ((void*)0));
687 const int hf = get_hf_wslua_text();
688 if (hf > -1) {
689 /* use proto_tree_add_none_format() instead? */
690 item = proto_tree_add_item(tree_item->tree, hf, tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len, ENC_NA0x00000000);
691 proto_item_set_text(item, "%s", s);
692 } else {
693 THROW_LUA_ERROR("Internal error: hf_wslua_text not registered")except_throwf(1, (6), "Internal error: hf_wslua_text not registered"
)
;
694 }
695 lua_remove(L,1)(lua_rotate(L, (1), -1), lua_settop(L, -(1)-1));
696 } else {
697 THROW_LUA_ERROR("Tree item ProtoField/Protocol handle is invalid (ProtoField/Proto not registered?)")except_throwf(1, (6), "Tree item ProtoField/Protocol handle is invalid (ProtoField/Proto not registered?)"
)
;
698 }
699 }
700
701 while(lua_gettop(L)) {
702 /* keep appending more text */
703 const char* s = lua_tostring(L,1)lua_tolstring(L, (1), ((void*)0));
704 if (s) proto_item_append_text(item, " %s", s);
705 lua_remove(L,1)(lua_rotate(L, (1), -1), lua_settop(L, -(1)-1));
706 }
707
708 push_TreeItem(L, proto_item_add_subtree(item,ett > 0 ? ett : wslua_ett), item);
709
710 return 1;
711}
712
713
714WSLUA_METHODstatic int TreeItem_add(lua_State *L) {
715 /*
716 Adds a child item to this tree item, returning the new child <<lua_class_TreeItem,`TreeItem`>>.
717
718 If the <<lua_class_ProtoField,`ProtoField`>> represents a numeric value (int, uint or float), then it's treated as a Big Endian (network order) value.
719
720 This function has a complicated form: 'treeitem:add([protofield,] [tvbrange,] [[value], label]])', such that if the first
721 argument is a <<lua_class_ProtoField,`ProtoField`>> or a <<lua_class_Proto,`Proto`>>, the second argument is a <<lua_class_TvbRange,`TvbRange`>>, and a third argument is given, it's a value;
722 but if the second argument is a non-<<lua_class_TvbRange,`TvbRange`>>, then it's the value (as opposed to filling that argument with 'nil',
723 which is invalid for this function). If the first argument is a non-<<lua_class_ProtoField,`ProtoField`>> and a non-<<lua_class_Proto,`Proto`>> then this argument can
724 be either a <<lua_class_TvbRange,`TvbRange`>> or a label, and the value is not in use.
725
726 [discrete]
727 ====== Example
728
729 [source,lua]
730 ----
731 local proto_foo = Proto("foo", "Foo Protocol")
732 proto_foo.fields.bytes = ProtoField.bytes("foo.bytes", "Byte array")
733 proto_foo.fields.u16 = ProtoField.uint16("foo.u16", "Unsigned short", base.HEX)
734
735 function proto_foo.dissector(buf, pinfo, tree)
736 -- ignore packets less than 4 bytes long
737 if buf:len() < 4 then return end
738
739 -- ##############################################
740 -- # Assume buf(0,4) == {0x00, 0x01, 0x00, 0x02}
741 -- ##############################################
742
743 local t = tree:add( proto_foo, buf() )
744
745 -- Adds a byte array that shows as: "Byte array: 00010002"
746 t:add( proto_foo.fields.bytes, buf(0,4) )
747
748 -- Adds a byte array that shows as "Byte array: 313233"
749 -- (the ASCII char code of each character in "123")
750 t:add( proto_foo.fields.bytes, buf(0,4), "123" )
751
752 -- Adds a tree item that shows as: "Unsigned short: 0x0001"
753 t:add( proto_foo.fields.u16, buf(0,2) )
754
755 -- Adds a tree item that shows as: "Unsigned short: 0x0064"
756 t:add( proto_foo.fields.u16, buf(0,2), 100 )
757
758 -- Adds a tree item that shows as: "Unsigned short: 0x0064 ( big endian )"
759 t:add( proto_foo.fields.u16, buf(1,2), 100, nil, "(", nil, "big", 999, nil, "endian", nil, ")" )
760
761 -- LITTLE ENDIAN: Adds a tree item that shows as: "Unsigned short: 0x0100"
762 t:add_le( proto_foo.fields.u16, buf(0,2) )
763
764 -- LITTLE ENDIAN: Adds a tree item that shows as: "Unsigned short: 0x6400"
765 t:add_le( proto_foo.fields.u16, buf(0,2), 100 )
766
767 -- LITTLE ENDIAN: Adds a tree item that shows as: "Unsigned short: 0x6400 ( little endian )"
768 t:add_le( proto_foo.fields.u16, buf(1,2), 100, nil, "(", nil, "little", 999, nil, "endian", nil, ")" )
769 end
770
771 udp_table = DissectorTable.get("udp.port")
772 udp_table:add(7777, proto_foo)
773 ----
774 */
775#define WSLUA_OPTARG_TreeItem_add_PROTOFIELD2 2 /* The <<lua_class_ProtoField,`ProtoField`>> field or <<lua_class_Proto,`Proto`>> protocol object to add to the tree. */
776#define WSLUA_OPTARG_TreeItem_add_TVBRANGE3 3 /* The <<lua_class_TvbRange,`TvbRange`>> of bytes in the packet this tree item covers/represents. */
777#define WSLUA_OPTARG_TreeItem_add_VALUE4 4 /* The field's value, instead of the ProtoField/Proto one. */
778#define WSLUA_OPTARG_TreeItem_add_LABEL5 5 /* One or more strings to use for the tree item label, instead of the ProtoField/Proto one. */
779
780 volatile int ret;
1
'ret' declared without an initial value
781 WRAP_NON_LUA_EXCEPTIONS({ volatile _Bool has_error = 0; { except_t *volatile exc; volatile
int except_state = 0; static const except_id_t catch_spec[] =
{ { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch
except_ch; except_setup_try(&except_sn, &except_ch, catch_spec
, 1); if (_setjmp (except_ch.except_jmp)) *(&exc) = &
except_ch.except_obj; else *(&exc) = 0; if(except_state &
1) except_state |= 2; except_state &= ~1; if (except_state
== 0 && exc == 0) { ret = TreeItem_add_item_any(L,0)
; } if (except_state == 0 && exc != 0 && (exc
->except_id.except_code == (1) || exc->except_id.except_code
== (4) || exc->except_id.except_code == (7)) && (
except_state|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree
->tree, ((exc)->except_id.except_code), ((exc)->except_message
)); } if (except_state == 0 && exc != 0 && (except_state
|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree->tree,
((exc)->except_id.except_code), ((exc)->except_message
)); lua_pushfstring(L, "%s: %s", __func__, ((exc)->except_message
) ? ((exc)->except_message) : "Malformed packet"); has_error
= 1; } if(!(except_state&1) && exc != 0) except_rethrow
(exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}; if (has_error) { lua_error(L); } }
2
Assuming the condition is true
3
Taking true branch
4
Taking false branch
5
Taking false branch
6
Assuming field 'except_code' is equal to 1
7
Taking true branch
8
Taking false branch
782 ret = TreeItem_add_item_any(L,false);{ volatile _Bool has_error = 0; { except_t *volatile exc; volatile
int except_state = 0; static const except_id_t catch_spec[] =
{ { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch
except_ch; except_setup_try(&except_sn, &except_ch, catch_spec
, 1); if (_setjmp (except_ch.except_jmp)) *(&exc) = &
except_ch.except_obj; else *(&exc) = 0; if(except_state &
1) except_state |= 2; except_state &= ~1; if (except_state
== 0 && exc == 0) { ret = TreeItem_add_item_any(L,0)
; } if (except_state == 0 && exc != 0 && (exc
->except_id.except_code == (1) || exc->except_id.except_code
== (4) || exc->except_id.except_code == (7)) && (
except_state|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree
->tree, ((exc)->except_id.except_code), ((exc)->except_message
)); } if (except_state == 0 && exc != 0 && (except_state
|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree->tree,
((exc)->except_id.except_code), ((exc)->except_message
)); lua_pushfstring(L, "%s: %s", __func__, ((exc)->except_message
) ? ((exc)->except_message) : "Malformed packet"); has_error
= 1; } if(!(except_state&1) && exc != 0) except_rethrow
(exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}; if (has_error) { lua_error(L); } }
783 ){ volatile _Bool has_error = 0; { except_t *volatile exc; volatile
int except_state = 0; static const except_id_t catch_spec[] =
{ { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch
except_ch; except_setup_try(&except_sn, &except_ch, catch_spec
, 1); if (_setjmp (except_ch.except_jmp)) *(&exc) = &
except_ch.except_obj; else *(&exc) = 0; if(except_state &
1) except_state |= 2; except_state &= ~1; if (except_state
== 0 && exc == 0) { ret = TreeItem_add_item_any(L,0)
; } if (except_state == 0 && exc != 0 && (exc
->except_id.except_code == (1) || exc->except_id.except_code
== (4) || exc->except_id.except_code == (7)) && (
except_state|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree
->tree, ((exc)->except_id.except_code), ((exc)->except_message
)); } if (except_state == 0 && exc != 0 && (except_state
|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree->tree,
((exc)->except_id.except_code), ((exc)->except_message
)); lua_pushfstring(L, "%s: %s", __func__, ((exc)->except_message
) ? ((exc)->except_message) : "Malformed packet"); has_error
= 1; } if(!(except_state&1) && exc != 0) except_rethrow
(exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}; if (has_error) { lua_error(L); } }
784 WSLUA_RETURN(ret)return (ret); /* The new child TreeItem. */
9
Undefined or garbage value returned to caller
785}
786
787WSLUA_METHODstatic int TreeItem_add_le(lua_State *L) {
788 /*
789 Adds a child item to this tree item, returning the new child <<lua_class_TreeItem,`TreeItem`>>.
790
791 If the <<lua_class_ProtoField,`ProtoField`>> represents a numeric value (int, uint or float), then it's treated as a Little Endian value.
792
793 This function has a complicated form: 'treeitem:add_le([protofield,] [tvbrange,] [[value], label]])', such that if the first
794 argument is a <<lua_class_ProtoField,`ProtoField`>> or a <<lua_class_Proto,`Proto`>>, the second argument is a <<lua_class_TvbRange,`TvbRange`>>, and a third argument is given, it's a value;
795 but if the second argument is a non-<<lua_class_TvbRange,`TvbRange`>>, then it's the value (as opposed to filling that argument with 'nil',
796 which is invalid for this function). If the first argument is a non-<<lua_class_ProtoField,`ProtoField`>> and a non-<<lua_class_Proto,`Proto`>> then this argument can
797 be either a <<lua_class_TvbRange,`TvbRange`>> or a label, and the value is not in use.
798 */
799#define WSLUA_OPTARG_TreeItem_add_le_PROTOFIELD2 2 /* The ProtoField field or Proto protocol object to add to the tree. */
800#define WSLUA_OPTARG_TreeItem_add_le_TVBRANGE3 3 /* The TvbRange of bytes in the packet this tree item covers/represents. */
801#define WSLUA_OPTARG_TreeItem_add_le_VALUE4 4 /* The field's value, instead of the ProtoField/Proto one. */
802#define WSLUA_OPTARG_TreeItem_add_le_LABEL5 5 /* One or more strings to use for the tree item label, instead of the ProtoField/Proto one. */
803 volatile int ret;
804 WRAP_NON_LUA_EXCEPTIONS({ volatile _Bool has_error = 0; { except_t *volatile exc; volatile
int except_state = 0; static const except_id_t catch_spec[] =
{ { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch
except_ch; except_setup_try(&except_sn, &except_ch, catch_spec
, 1); if (_setjmp (except_ch.except_jmp)) *(&exc) = &
except_ch.except_obj; else *(&exc) = 0; if(except_state &
1) except_state |= 2; except_state &= ~1; if (except_state
== 0 && exc == 0) { ret = TreeItem_add_item_any(L,1)
; } if (except_state == 0 && exc != 0 && (exc
->except_id.except_code == (1) || exc->except_id.except_code
== (4) || exc->except_id.except_code == (7)) && (
except_state|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree
->tree, ((exc)->except_id.except_code), ((exc)->except_message
)); } if (except_state == 0 && exc != 0 && (except_state
|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree->tree,
((exc)->except_id.except_code), ((exc)->except_message
)); lua_pushfstring(L, "%s: %s", __func__, ((exc)->except_message
) ? ((exc)->except_message) : "Malformed packet"); has_error
= 1; } if(!(except_state&1) && exc != 0) except_rethrow
(exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}; if (has_error) { lua_error(L); } }
805 ret = TreeItem_add_item_any(L,true);{ volatile _Bool has_error = 0; { except_t *volatile exc; volatile
int except_state = 0; static const except_id_t catch_spec[] =
{ { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch
except_ch; except_setup_try(&except_sn, &except_ch, catch_spec
, 1); if (_setjmp (except_ch.except_jmp)) *(&exc) = &
except_ch.except_obj; else *(&exc) = 0; if(except_state &
1) except_state |= 2; except_state &= ~1; if (except_state
== 0 && exc == 0) { ret = TreeItem_add_item_any(L,1)
; } if (except_state == 0 && exc != 0 && (exc
->except_id.except_code == (1) || exc->except_id.except_code
== (4) || exc->except_id.except_code == (7)) && (
except_state|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree
->tree, ((exc)->except_id.except_code), ((exc)->except_message
)); } if (except_state == 0 && exc != 0 && (except_state
|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree->tree,
((exc)->except_id.except_code), ((exc)->except_message
)); lua_pushfstring(L, "%s: %s", __func__, ((exc)->except_message
) ? ((exc)->except_message) : "Malformed packet"); has_error
= 1; } if(!(except_state&1) && exc != 0) except_rethrow
(exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}; if (has_error) { lua_error(L); } }
806 ){ volatile _Bool has_error = 0; { except_t *volatile exc; volatile
int except_state = 0; static const except_id_t catch_spec[] =
{ { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch
except_ch; except_setup_try(&except_sn, &except_ch, catch_spec
, 1); if (_setjmp (except_ch.except_jmp)) *(&exc) = &
except_ch.except_obj; else *(&exc) = 0; if(except_state &
1) except_state |= 2; except_state &= ~1; if (except_state
== 0 && exc == 0) { ret = TreeItem_add_item_any(L,1)
; } if (except_state == 0 && exc != 0 && (exc
->except_id.except_code == (1) || exc->except_id.except_code
== (4) || exc->except_id.except_code == (7)) && (
except_state|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree
->tree, ((exc)->except_id.except_code), ((exc)->except_message
)); } if (except_state == 0 && exc != 0 && (except_state
|=1)) { show_exception(lua_tvb, lua_pinfo, lua_tree->tree,
((exc)->except_id.except_code), ((exc)->except_message
)); lua_pushfstring(L, "%s: %s", __func__, ((exc)->except_message
) ? ((exc)->except_message) : "Malformed packet"); has_error
= 1; } if(!(except_state&1) && exc != 0) except_rethrow
(exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}; if (has_error) { lua_error(L); } }
807 WSLUA_RETURN(ret)return (ret); /* The new child TreeItem. */
808}
809
810/* WSLUA_ATTRIBUTE TreeItem_text RW Set/get the <<lua_class_TreeItem,`TreeItem`>>'s display string (string).
811
812 For the getter, if the TreeItem has no display string, then nil is returned.
813 */
814static int TreeItem_get_text(lua_State* L) {
815 TreeItem ti = checkTreeItem(L,1);
816 char label_str[ITEM_LABEL_LENGTH240+1];
817 char *label_ptr;
818
819 if (ti->item && PITEM_FINFO(ti->item)((ti->item)->finfo)) {
820 field_info *fi = PITEM_FINFO(ti->item)((ti->item)->finfo);
821
822 if (!fi->rep) {
823 label_ptr = label_str;
824 proto_item_fill_label(fi, label_str, NULL((void*)0));
825 } else
826 label_ptr = fi->rep->representation;
827
828 if (label_ptr) {
829 lua_pushstring(L, label_ptr);
830 } else {
831 lua_pushnil(L);
832 }
833 } else {
834 lua_pushnil(L);
835 }
836
837 return 1;
838}
839
840/* the following is used as both a method and attribute */
841WSLUA_METHODstatic int TreeItem_set_text(lua_State *L) {
842 /* Sets the text of the label.
843
844 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
845 */
846#define WSLUA_ARG_TreeItem_set_text_TEXT2 2 /* The text to be used. */
847 TreeItem ti = checkTreeItem(L,1);
848 const char* s = luaL_checkstring(L,WSLUA_ARG_TreeItem_set_text_TEXT)(luaL_checklstring(L, (2), ((void*)0)));
849
850 proto_item_set_text(ti->item,"%s",s);
851
852 /* copy the TreeItem userdata so we give it back */
853 lua_pushvalue(L, 1);
854
855 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
856}
857
858WSLUA_METHODstatic int TreeItem_append_text(lua_State *L) {
859 /* Appends text to the label.
860
861 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
862 */
863#define WSLUA_ARG_TreeItem_append_text_TEXT2 2 /* The text to be appended. */
864 TreeItem ti = checkTreeItem(L,1);
865 const char* s = luaL_checkstring(L,WSLUA_ARG_TreeItem_append_text_TEXT)(luaL_checklstring(L, (2), ((void*)0)));
866
867 proto_item_append_text(ti->item,"%s",s);
868
869 /* copy the TreeItem userdata so we give it back */
870 lua_pushvalue(L, 1);
871
872 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
873}
874
875WSLUA_METHODstatic int TreeItem_prepend_text(lua_State *L) {
876 /* Prepends text to the label.
877
878 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
879 */
880#define WSLUA_ARG_TreeItem_prepend_text_TEXT2 2 /* The text to be prepended. */
881 TreeItem ti = checkTreeItem(L,1);
882 const char* s = luaL_checkstring(L,WSLUA_ARG_TreeItem_prepend_text_TEXT)(luaL_checklstring(L, (2), ((void*)0)));
883
884 proto_item_prepend_text(ti->item,"%s",s);
885
886 /* copy the TreeItem userdata so we give it back */
887 lua_pushvalue(L, 1);
888
889 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
890}
891
892WSLUA_METHODstatic int TreeItem_add_expert_info(lua_State *L) {
893 /* Sets the expert flags of the item and adds expert info to the packet.
894
895 This function does *not* create a truly filterable expert info for a protocol.
896 Instead you should use `TreeItem.add_proto_expert_info()`.
897
898 Note: This function is provided for backwards compatibility only, and should not
899 be used in new Lua code. It may be removed in the future. You should only
900 use `TreeItem.add_proto_expert_info()`.
901 */
902#define WSLUA_OPTARG_TreeItem_add_expert_info_GROUP2 2 /* One of:
903 `PI_CHECKSUM`,
904 `PI_SEQUENCE`,
905 `PI_RESPONSE_CODE`,
906 `PI_REQUEST_CODE`,
907 `PI_UNDECODED`,
908 `PI_REASSEMBLE`,
909 `PI_MALFORMED`,
910 `PI_DEBUG`,
911 `PI_PROTOCOL`,
912 `PI_SECURITY`,
913 `PI_COMMENTS_GROUP`,
914 `PI_DECRYPTION`,
915 `PI_ASSUMPTION`,
916 `PI_DEPRECATED`,
917 `PI_RECEIVE`,
918 `PI_INTERFACE`,
919 or `PI_DISSECTOR_BUG`. */
920#define WSLUA_OPTARG_TreeItem_add_expert_info_SEVERITY3 3 /* One of:
921 `PI_COMMENT`,
922 `PI_CHAT`,
923 `PI_NOTE`,
924 `PI_WARN`,
925 or `PI_ERROR`. */
926#define WSLUA_OPTARG_TreeItem_add_expert_info_TEXT4 4 /* The text for the expert info display. */
927 TreeItem ti = checkTreeItem(L,1);
928 int group = (int)luaL_optinteger(L,WSLUA_OPTARG_TreeItem_add_expert_info_GROUP2,PI_DEBUG0x08000000);
929 int severity = (int)luaL_optinteger(L,WSLUA_OPTARG_TreeItem_add_expert_info_SEVERITY3,PI_CHAT0x00200000);
930 expert_field* ei_info = wslua_get_expert_field(group, severity);
931 const char* str;
932
933 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_add_expert_info_TEXT4) {
934 str = wslua_checkstring_only(L, WSLUA_OPTARG_TreeItem_add_expert_info_TEXT4);
935 expert_add_info_format(lua_pinfo, ti->item, ei_info, "%s", str);
936 } else {
937 expert_add_info(lua_pinfo, ti->item, ei_info);
938 }
939
940 /* copy the TreeItem userdata so we give it back */
941 lua_pushvalue(L, 1);
942
943 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
944}
945
946WSLUA_METHODstatic int TreeItem_add_proto_expert_info(lua_State *L) {
947 /* Sets the expert flags of the tree item and adds expert info to the packet. */
948#define WSLUA_ARG_TreeItem_add_proto_expert_info_EXPERT2 2 /* The <<lua_class_ProtoExpert,`ProtoExpert`>> object to add to the tree. */
949#define WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT3 3 /* Text for the expert info display
950 (default is to use the registered
951 text). */
952 TreeItem ti = checkTreeItem(L,1);
953 ProtoExpert expert = checkProtoExpert(L,WSLUA_ARG_TreeItem_add_proto_expert_info_EXPERT2);
954 const char* str;
955
956 if (expert->ids.ei == EI_INIT_EI0 || expert->ids.hf == EI_INIT_HF0) {
957 luaL_error(L, "ProtoExpert is not registered");
958 return 0;
959 }
960
961 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT3) {
962 str = wslua_checkstring_only(L, WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT3);
963 expert_add_info_format(lua_pinfo, ti->item, &expert->ids, "%s", str);
964 } else {
965 expert_add_info(lua_pinfo, ti->item, &expert->ids);
966 }
967
968 /* copy the TreeItem userdata so we give it back */
969 lua_pushvalue(L, 1);
970
971 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
972}
973
974WSLUA_METHODstatic int TreeItem_add_tvb_expert_info(lua_State *L) {
975 /* Sets the expert flags of the tree item and adds expert info to the packet
976 associated with the <<lua_class_Tvb,`Tvb`>> or <<lua_class_TvbRange,`TvbRange`>> bytes in the packet. */
977#define WSLUA_ARG_TreeItem_add_tvb_expert_info_EXPERT2 2 /* The <<lua_class_ProtoExpert,`ProtoExpert`>> object to add to the tree. */
978#define WSLUA_ARG_TreeItem_add_tvb_expert_info_TVB3 3 /* The <<lua_class_Tvb,`Tvb`>> or <<lua_class_TvbRange,`TvbRange`>> object bytes to associate
979 the expert info with. */
980#define WSLUA_OPTARG_TreeItem_add_tvb_expert_info_TEXT4 4 /* Text for the expert info display
981 (default is to use the registered
982 text). */
983 TreeItem ti = checkTreeItem(L,1);
984 ProtoExpert expert = checkProtoExpert(L,WSLUA_ARG_TreeItem_add_proto_expert_info_EXPERT2);
985 TvbRange tvbr;
986 const char* str;
987
988 if (expert->ids.ei == EI_INIT_EI0 || expert->ids.hf == EI_INIT_HF0) {
989 luaL_error(L, "ProtoExpert is not registered");
990 return 0;
991 }
992
993 tvbr = shiftTvbRange(L,WSLUA_ARG_TreeItem_add_tvb_expert_info_TVB3);
994
995 if (!tvbr) {
996 tvbr = wmem_new(lua_pinfo->pool, struct _wslua_tvbrange)((struct _wslua_tvbrange*)wmem_alloc((lua_pinfo->pool), sizeof
(struct _wslua_tvbrange)))
;
997 tvbr->tvb = shiftTvb(L,WSLUA_ARG_TreeItem_add_tvb_expert_info_TVB3);
998 if (!tvbr->tvb) {
999 tvbr->tvb = wmem_new(lua_pinfo->pool, struct _wslua_tvb)((struct _wslua_tvb*)wmem_alloc((lua_pinfo->pool), sizeof(
struct _wslua_tvb)))
;
1000 }
1001 tvbr->tvb->ws_tvb = lua_tvb;
1002 tvbr->offset = 0;
1003 tvbr->len = 0;
1004 }
1005
1006 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT3) {
1007 str = wslua_checkstring_only(L, WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT3);
1008 proto_tree_add_expert_format(ti->tree, lua_pinfo, &expert->ids,
1009 tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len,
1010 "%s", str);
1011 } else {
1012 proto_tree_add_expert(ti->tree, lua_pinfo, &expert->ids,
1013 tvbr->tvb->ws_tvb, tvbr->offset, tvbr->len);
1014 }
1015
1016 /* copy the TreeItem userdata so we give it back */
1017 lua_pushvalue(L, 1);
1018
1019 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
1020}
1021
1022
1023/* WSLUA_ATTRIBUTE TreeItem_visible RO Get the <<lua_class_TreeItem,`TreeItem`>>'s subtree visibility status (boolean). */
1024static int TreeItem_get_visible(lua_State* L) {
1025 TreeItem ti = checkTreeItem(L,1);
1026
1027 if (ti->tree) {
1028 lua_pushboolean(L, PTREE_DATA(ti->tree)((ti->tree)->tree_data)->visible);
1029 }
1030 else {
1031 lua_pushboolean(L, false0);
1032 }
1033
1034 return 1;
1035}
1036
1037
1038/* WSLUA_ATTRIBUTE TreeItem_generated RW Set/get the <<lua_class_TreeItem,`TreeItem`>>'s generated state (boolean). */
1039static int TreeItem_get_generated(lua_State* L) {
1040 TreeItem ti = checkTreeItem(L,1);
1041
1042 lua_pushboolean(L, proto_item_is_generated(ti->item));
1043
1044 return 1;
1045}
1046
1047/* the following is used as both a method and attribute. As a method it defaults
1048 to setting the value, because that's what it used to do before. */
1049WSLUA_METHODstatic int TreeItem_set_generated(lua_State *L) {
1050 /* Marks the <<lua_class_TreeItem,`TreeItem`>> as a generated field (with data inferred but not contained in the packet).
1051
1052 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
1053 */
1054#define WSLUA_OPTARG_TreeItem_set_generated_BOOL2 2 /* A Lua boolean, which if `true` sets the <<lua_class_TreeItem,`TreeItem`>>
1055 generated flag, else clears it (default=true) */
1056 TreeItem ti = checkTreeItem(L,1);
1057 bool_Bool set = wslua_optbool(L, WSLUA_OPTARG_TreeItem_set_generated_BOOL2, true1);
1058
1059 if (set) {
1060 proto_item_set_generated(ti->item);
1061 } else {
1062 if (ti->item)
1063 FI_RESET_FLAG(PITEM_FINFO(ti->item), FI_GENERATED)do { if (((ti->item)->finfo)) (((ti->item)->finfo
))->flags = (((ti->item)->finfo))->flags & ~(
0x00000002); } while(0)
;
1064 }
1065
1066 /* copy the TreeItem userdata so we give it back */
1067 lua_pushvalue(L, 1);
1068
1069 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
1070}
1071
1072/* WSLUA_ATTRIBUTE TreeItem_hidden RW Set/get <<lua_class_TreeItem,`TreeItem`>>'s hidden state (boolean). */
1073static int TreeItem_get_hidden(lua_State* L) {
1074 TreeItem ti = checkTreeItem(L,1);
1075
1076 lua_pushboolean(L, proto_item_is_hidden(ti->item));
1077
1078 return 1;
1079}
1080
1081/* the following is used as both a method and attribute. As a method it defaults
1082 to setting the value, because that's what it used to do before. */
1083WSLUA_METHODstatic int TreeItem_set_hidden(lua_State *L) {
1084 /*
1085 Marks the <<lua_class_TreeItem,`TreeItem`>> as a hidden field (neither displayed nor used in filters).
1086 Deprecated
1087
1088 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
1089 */
1090#define WSLUA_OPTARG_TreeItem_set_hidden_BOOL2 2 /* A Lua boolean, which if `true` sets the <<lua_class_TreeItem,`TreeItem`>>
1091 hidden flag, else clears it. Default is `true`. */
1092 TreeItem ti = checkTreeItem(L,1);
1093 bool_Bool set = wslua_optbool(L, WSLUA_OPTARG_TreeItem_set_hidden_BOOL2, true1);
1094
1095 if (set) {
1096 proto_item_set_hidden(ti->item);
1097 } else {
1098 proto_item_set_visible(ti->item);
1099 }
1100
1101 /* copy the TreeItem userdata so we give it back */
1102 lua_pushvalue(L, 1);
1103
1104 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
1105}
1106
1107/* WSLUA_ATTRIBUTE TreeItem_len RW Set/get <<lua_class_TreeItem,`TreeItem`>>'s length inside tvb, after it has already been created. */
1108static int TreeItem_get_len(lua_State* L) {
1109 TreeItem ti = checkTreeItem(L,1);
1110 int len = 0;
1111
1112 /* XXX - this is *NOT* guaranteed to return a correct value! */
1113 len = proto_item_get_len(ti->item);
1114
1115 lua_pushinteger(L, len > 0 ? len : 0);
1116
1117 return 1;
1118}
1119
1120WSLUA_METHODstatic int TreeItem_set_len(lua_State *L) {
1121 /* Set <<lua_class_TreeItem,`TreeItem`>>'s length inside tvb, after it has already been created.
1122
1123 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
1124 */
1125#define WSLUA_ARG_TreeItem_set_len_LEN2 2 /* The length to be used. */
1126 TreeItem ti = checkTreeItem(L,1);
1127 int len = (int)luaL_checkinteger(L,WSLUA_ARG_TreeItem_set_len_LEN2);
1128
1129 if (len < 0) {
1130 luaL_argerror(L,WSLUA_ARG_TreeItem_set_len_LEN2,"must be a positive value");
1131 return 0;
1132 }
1133
1134 proto_item_set_len(ti->item, len);
1135
1136 /* copy the TreeItem userdata so we give it back */
1137 lua_pushvalue(L, 1);
1138
1139 WSLUA_RETURN(1)return (1); /* The same TreeItem. */
1140}
1141
1142WSLUA_METHODstatic int TreeItem_referenced(lua_State *L) {
1143 /* Checks if a <<lua_class_ProtoField,`ProtoField`>> or <<lua_class_Dissector,`Dissector`>> is referenced by a filter/tap/UI.
1144
1145 If this function returns `false`, it means that the field (or dissector) does not need to be dissected
1146 and can be safely skipped. By skipping a field rather than dissecting it, the dissector will
1147 usually run faster since Wireshark will not do extra dissection work when it doesn't need the field.
1148
1149 You can use this in conjunction with the TreeItem.visible attribute. This function will always return
1150 true when the TreeItem is visible. When it is not visible and the field is not referenced, you can
1151 speed up the dissection by not dissecting the field as it is not needed for display or filtering.
1152
1153 This function takes one parameter that can be a <<lua_class_ProtoField,`ProtoField`>> or <<lua_class_Dissector,`Dissector`>>.
1154 The <<lua_class_Dissector,`Dissector`>> form is useful when you need to decide whether to call a sub-dissector.
1155 */
1156#define WSLUA_ARG_TreeItem_referenced_PROTOFIELD2 2 /* The <<lua_class_ProtoField,`ProtoField`>> or <<lua_class_Dissector,`Dissector`>> to check if referenced. */
1157 TreeItem ti = checkTreeItem(L, 1);
1158 if (!ti) return 0;
1159 ProtoField f = shiftProtoField(L, WSLUA_ARG_TreeItem_referenced_PROTOFIELD2);
1160 if (f) {
1161 lua_pushboolean(L, proto_field_is_referenced(ti->tree, f->hfid));
1162 }
1163 else {
1164 Dissector d = checkDissector(L, WSLUA_ARG_TreeItem_referenced_PROTOFIELD2);
1165 if (!d) return 0;
1166 lua_pushboolean(L, proto_field_is_referenced(ti->tree, dissector_handle_get_protocol_index(d)));
1167 }
1168 WSLUA_RETURN(1)return (1); /* A boolean indicating if the ProtoField/Dissector is referenced */
1169}
1170
1171WSLUA_METHODstatic int TreeItem_get_child_count(lua_State *L) {
1172 /* Returns the number of direct child tree items.
1173
1174 This method counts and returns the number of direct children of this tree item.
1175 Only immediate children are counted; grandchildren and deeper descendants are not included.
1176
1177 [source,lua]
1178 ----
1179 local tree = root:add(myproto, tvbuf())
1180 tree:add("Child 1")
1181 tree:add("Child 2")
1182
1183 local count = tree:get_child_count()
1184 -- count is now 2
1185 ----
1186
1187 @since 4.7.0
1188 */
1189
1190 /* Retrieve and validate the TreeItem from Lua stack position 1 */
1191 TreeItem ti = checkTreeItem(L, 1);
1192 if (!ti) {
1193 return 0;
1194 }
1195
1196 int count = 0;
1197 proto_tree *tree = ti->tree;
1198
1199 if (tree) {
1200 /* Get the first child node from the proto_tree structure */
1201 proto_node *current = ((proto_node *)tree)->first_child;
1202
1203 /* Iterate through the linked list of children using the 'next' pointer */
1204 while (current) {
1205 count++;
1206 current = current->next; /* Move to next sibling */
1207 }
1208 }
1209
1210 /* Push the count as an integer onto the Lua stack */
1211 lua_pushinteger(L, count);
1212 WSLUA_RETURN(1)return (1); /* The number of child tree items. */
1213}
1214
1215WSLUA_METHODstatic int TreeItem_get_parent(lua_State *L) {
1216 /* Returns the parent tree item.
1217
1218 Returns the parent tree item of this item, or nil if this is a root item
1219 (i.e., a top-level tree item added directly to the protocol tree).
1220
1221 [source,lua]
1222 ----
1223 local parent_tree = root:add(myproto, tvbuf())
1224 local child_tree = parent_tree:add("Child")
1225
1226 local parent = child_tree:get_parent()
1227 -- parent is the same as parent_tree
1228
1229 local root_parent = parent_tree:get_parent()
1230 -- root_parent is nil (assuming parent_tree is a root item)
1231 ----
1232 @since 4.7.0
1233 */
1234
1235 /* Retrieve and validate the TreeItem from Lua stack */
1236 TreeItem ti = checkTreeItem(L, 1);
1237 if (!ti) {
1238 return 0;
1239 }
1240
1241 proto_item *parent = NULL((void*)0);
1242
1243 if (ti->item) {
1244 /* Use Wireshark's built-in function to get the parent proto_item */
1245 parent = proto_item_get_parent(ti->item);
1246 }
1247
1248 if (parent) {
1249 /* Parent exists - get its subtree (may be NULL if parent has no children) */
1250 proto_tree *parent_tree = proto_item_get_subtree(parent);
1251
1252 /* Create a new Lua TreeItem object wrapping the parent and push it to Lua */
1253 push_TreeItem(L, parent_tree, parent);
1254 } else {
1255 /* No parent exists - this is a root item, return nil */
1256 lua_pushnil(L);
1257 }
1258
1259 WSLUA_RETURN(1)return (1); /* The parent TreeItem, or nil if this is a root item. */
1260}
1261
1262WSLUA_METHODstatic int TreeItem_get_child(lua_State *L) {
1263 /* Returns the child tree item at the specified index.
1264
1265 Returns the direct child TreeItem at the given index using 0-based indexing.
1266 This provides random access to child items by their position.
1267
1268 [source,lua]
1269 ----
1270 local tree = root:add(myproto, tvbuf())
1271 tree:add("First child") -- index 0
1272 tree:add("Second child") -- index 1
1273 tree:add("Third child") -- index 2
1274
1275 local first = tree:get_child(0) -- Returns first child
1276 local second = tree:get_child(1) -- Returns second child
1277 local invalid = tree:get_child(5) -- Returns nil (out of range)
1278 ----
1279 @since 4.7.0
1280 */
1281
1282#define WSLUA_ARG_TreeItem_get_child_INDEX2 2 /* The index of the child (0-based). */
1283 /* Retrieve and validate the TreeItem */
1284 TreeItem ti = checkTreeItem(L, 1);
1285 if (!ti)
1286 return 0;
1287
1288 /* Get the index parameter from Lua (must be an integer) */
1289 lua_Integer index = luaL_checkinteger(L, WSLUA_ARG_TreeItem_get_child_INDEX2);
1290
1291 /* Validate index - must be non-negative for 0-based indexing */
1292 if (index < 0) {
1293 WSLUA_ARG_ERROR(TreeItem_get_child, INDEX, "index must be non-negative"){ luaL_argerror(L,2, "TreeItem_get_child" ": " "index must be non-negative"
); }
;
1294 }
1295
1296 proto_node *current = NULL((void*)0);
1297
1298 if (ti->tree) {
1299 /* Get the first child in the linked list */
1300 current = ((proto_node *)ti->tree)->first_child;
1301 }
1302
1303 /* Navigate to the index-th child by following the 'next' pointers */
1304 lua_Integer current_index = 0;
1305 while (current && current_index < index) {
1306 current = current->next; /* Move to next sibling */
1307 current_index++;
1308 }
1309
1310 if (current) {
1311 /* Child found at the specified index */
1312 /* Get the subtree (may be NULL if this node has no children) */
1313 proto_tree *child_tree = proto_item_get_subtree((proto_item *)current);
1314
1315 /* Create and push the TreeItem to Lua */
1316 push_TreeItem(L, child_tree, (proto_item *)current);
1317 } else {
1318 /* Index out of range - no child exists at this position */
1319 lua_pushnil(L);
1320 }
1321
1322 WSLUA_RETURN(1)return (1); /* The child TreeItem at the specified index, or nil if out of range. */
1323}
1324
1325/* Structure to hold iterator state with optional field name filters and recursion */
1326typedef struct
1327{
1328 proto_node *current_node; /* Current node being processed in iteration */
1329 char **field_filters; /* Array of field name strings to match (e.g., "tcp.port") */
1330 int num_filters; /* Number of filter strings in the array */
1331 bool_Bool recursive; /* If true, iterate through entire subtree depth-first */
1332 proto_node **stack; /* Stack for recursive depth-first traversal */
1333 int stack_size; /* Number of nodes currently on the stack */
1334 int stack_capacity; /* Maximum capacity of stack (grows dynamically) */
1335} TreeItem_iterator_state;
1336
1337/* Helper function to push a node onto the stack for recursive iteration */
1338static void push_node_to_stack(TreeItem_iterator_state *state, proto_node *node) {
1339 if (!node)
1340 return;
1341
1342 /* Dynamically expand stack capacity if needed */
1343 if (state->stack_size >= state->stack_capacity) {
1344 /* Double capacity plus initial buffer to reduce reallocation frequency */
1345 state->stack_capacity = state->stack_capacity * 2 + 10;
1346 state->stack = (proto_node **)g_realloc(state->stack,
1347 state->stack_capacity * sizeof(proto_node *));
1348 }
1349
1350 /* Add node to top of stack and increment size */
1351 state->stack[state->stack_size++] = node;
1352}
1353
1354/* Helper function to pop a node from the stack */
1355static proto_node *pop_node_from_stack(TreeItem_iterator_state *state) {
1356 /* Check if stack is empty */
1357 if (state->stack_size <= 0)
1358 return NULL((void*)0);
1359
1360 /* Return top element and decrement stack size */
1361 return state->stack[--state->stack_size];
1362}
1363
1364/* Helper function for the children iterator with optional filtering and recursion */
1365static int TreeItem_children_iterator(lua_State *L) {
1366 /* Retrieve the iterator state from the closure's upvalue */
1367 TreeItem_iterator_state *state = (TreeItem_iterator_state *)lua_touserdata(L, lua_upvalueindex(1)((-1000000 - 1000) - (1)));
1368
1369 /* Continue iterating while we have nodes to process */
1370 /* Either from current sibling chain OR from recursive stack */
1371 while (state->current_node || (state->recursive && state->stack_size > 0)) {
1372 proto_node *node = NULL((void*)0);
1373
1374 if (state->current_node) {
1375 /* Process next node in current sibling chain */
1376 node = state->current_node;
1377 state->current_node = node->next; /* Advance to next sibling for next iteration */
1378 } else if (state->recursive && state->stack_size > 0) {
1379 /* No more siblings - pop from stack for recursive traversal */
1380 node = pop_node_from_stack(state);
1381 if (!node)
1382 continue; /* Stack had invalid entry, skip */
1383
1384 /* Set current_node to first child of popped node */
1385 /* This allows iteration through all siblings before going deeper */
1386 proto_tree *subtree = proto_item_get_subtree((proto_item *)node);
1387 if (subtree) {
1388 state->current_node = ((proto_node *)subtree)->first_child;
1389 }
1390 }
1391
1392 if (!node)
1393 continue; /* Safety check - should not happen */
1394
1395 /* IMPORTANT: For recursive mode, always add children to stack regardless of filter match
1396 * This ensures that even if the current node doesn't match the filter,
1397 * its children are still searched recursively (depth-first traversal)
1398 *
1399 * Example: If we filter for "tcp.port" but current node is "tcp.flags",
1400 * we still need to check if "tcp.flags" has "tcp.port" children
1401 */
1402 if (state->recursive) {
1403 proto_tree *subtree = proto_item_get_subtree((proto_item *)node);
1404 if (subtree) {
1405 /* Collect all children first (needed for reverse-order pushing) */
1406 proto_node *child = ((proto_node *)subtree)->first_child;
1407 proto_node **children = NULL((void*)0);
1408 int child_count = 0;
1409
1410 /* Count and collect all children in forward order */
1411 while (child) {
1412 child_count++;
1413 children = (proto_node **)g_realloc(children, child_count * sizeof(proto_node *));
1414 children[child_count - 1] = child;
1415 child = child->next;
1416 }
1417
1418 /* Push children in REVERSE order to stack */
1419 /* This ensures depth-first left-to-right traversal */
1420 /* (first child is on top of stack, gets popped first) */
1421 for (int i = child_count - 1; i >= 0; i--) {
1422 push_node_to_stack(state, children[i]);
1423 }
1424
1425 /* Free temporary children array */
1426 if (children)
1427 g_free(children);
1428 }
1429 }
1430
1431 /* Check if this node matches the filter criteria */
1432 bool_Bool matches = false0;
1433 if (state->num_filters > 0) {
1434 /* Filters are specified - check if node's field name matches any filter */
1435 field_info *finfo = node->finfo;
1436
1437 /* Ensure node has valid field_info with abbreviated name */
1438 if (finfo && finfo->hfinfo && finfo->hfinfo->abbrev) {
1439 /* Check against all filter strings (OR logic) */
1440 for (int i = 0; i < state->num_filters; i++) {
1441 if (strcmp(finfo->hfinfo->abbrev, state->field_filters[i]) == 0) {
1442 matches = true1;
1443 break; /* Found match, no need to check remaining filters */
1444 }
1445 }
1446 }
1447 /* If finfo is NULL or has no abbrev, matches remains false */
1448 } else {
1449 /* No filters specified - return all children/descendants */
1450 matches = true1;
1451 }
1452
1453 /* Only return matching nodes to Lua, but continue processing regardless
1454 * (children were already added to stack above for recursive mode) */
1455 if (matches) {
1456 /* Get the subtree for this matching node (may be NULL) */
1457 proto_tree *child_tree = proto_item_get_subtree((proto_item *)node);
1458
1459 /* Push matching TreeItem to Lua stack */
1460 push_TreeItem(L, child_tree, (proto_item *)node);
1461 return 1; /* Return 1 value to Lua iterator */
1462 }
1463
1464 /* If no match, continue to next node
1465 * Children are already on stack for recursive mode,
1466 * ensuring we don't miss matching descendants */
1467 }
1468
1469 /* No more nodes to process - iteration complete */
1470 return 0; /* Return no values - signals end of iteration to Lua */
1471}
1472
1473/* Garbage collector for the iterator state */
1474static int TreeItem_iterator_state_gc(lua_State *L) {
1475 /* Retrieve the iterator state userdata */
1476 TreeItem_iterator_state *state = (TreeItem_iterator_state *)lua_touserdata(L, 1);
1477
1478 /* Free the filter strings array */
1479 if (state->field_filters) {
1480 /* Free each individual filter string */
1481 for (int i = 0; i < state->num_filters; i++) {
1482 g_free(state->field_filters[i]);
1483 }
1484 /* Free the array itself */
1485 g_free(state->field_filters);
1486 }
1487
1488 /* Free the recursion stack */
1489 if (state->stack) {
1490 g_free(state->stack);
1491 }
1492
1493 /* Note: The state struct itself is freed by Lua's GC */
1494 return 0;
1495}
1496
1497WSLUA_METHODstatic int TreeItem_children(lua_State *L) {
1498 /* Returns an iterator function to iterate over child tree items.
1499
1500 Returns an iterator function that can be used in a Lua for loop to iterate
1501 over children of this tree item. Supports optional filtering and recursive traversal.
1502
1503 The basic usage iterates over direct children only:
1504 [source,lua]
1505 ----
1506 for child in tree:children() do
1507 print("Child: " .. tostring(child))
1508 end
1509 ----
1510
1511 You can filter by field names to only get children with specific fields:
1512 [source,lua]
1513 ----
1514 -- Single field filter
1515 for child in tree:children("tcp.flags") do
1516 print("TCP flags child: " .. tostring(child))
1517 end
1518
1519 -- Multiple field filters
1520 for child in tree:children({"tcp.port", "tcp.srcport", "tcp.dstport"}) do
1521 print("TCP port child: " .. tostring(child))
1522 end
1523 ----
1524
1525 Enable recursive iteration to traverse the entire subtree in depth-first order:
1526 [source,lua]
1527 ----
1528 -- Recursive iteration without filter
1529 for child in tree:children(nil, true) do
1530 print("Descendant: " .. tostring(child))
1531 end
1532
1533 -- Recursive iteration with field filter
1534 for child in tree:children("tcp.flags", true) do
1535 print("TCP flags anywhere in subtree: " .. tostring(child))
1536 end
1537 ----
1538
1539 When using recursive mode with filters, the iterator searches through all descendants
1540 even if parent nodes don't match the filter, ensuring no matching children are missed.
1541
1542 IMPORTANT: Field extractors must still be created for the fields you want to iterate over.
1543 Wireshark optimizes dissection by only creating tree items for fields that are explicitly
1544 requested through field extractors, display filters, or taps. Without proper field extractors,
1545 the fields may not exist in the dissection tree and will not be found by this iterator.
1546
1547 Example of proper field extractor setup:
1548 [source,lua]
1549 ----
1550 -- Define field extractors first
1551 local tcp_flags_extractor = Field.new("tcp.flags")
1552 local tcp_port_extractor = Field.new("tcp.port")
1553
1554 -- Then use tree navigation (extractors ensure fields exist in tree)
1555 for child in tree:children("tcp.flags") do
1556 local field_info = child:get_field_info()
1557 print("TCP Flags:", field_info.value)
1558 end
1559 ----
1560 @since 4.7.0
1561 */
1562
1563#define WSLUA_OPTARG_TreeItem_children_FIELD_FILTER2 2 /* Optional field name(s) to filter by (string or table of strings). */
1564#define WSLUA_OPTARG_TreeItem_children_RECURSIVE3 3 /* Optional boolean to enable recursive (depth-first) iteration. Default is false. */
1565
1566 /* Retrieve and validate the TreeItem */
1567 TreeItem ti = checkTreeItem(L, 1);
1568 if (!ti)
1569 return 0;
1570
1571 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_children_RECURSIVE3 &&
1572 !lua_isnil(L, WSLUA_OPTARG_TreeItem_children_RECURSIVE)(lua_type(L, (3)) == 0) &&
1573 !lua_isboolean(L, WSLUA_OPTARG_TreeItem_children_RECURSIVE)(lua_type(L, (3)) == 1)) {
1574 luaL_error(L, "TreeItem:children() recursive argument must be a boolean");
1575 return 0;
1576 }
1577
1578 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_children_FIELD_FILTER2 &&
1579 !lua_isnil(L, WSLUA_OPTARG_TreeItem_children_FIELD_FILTER)(lua_type(L, (2)) == 0)) {
1580 int filter_arg = WSLUA_OPTARG_TreeItem_children_FIELD_FILTER2;
1581
1582 if (lua_type(L, filter_arg) != LUA_TSTRING4 && !lua_istable(L, filter_arg)(lua_type(L, (filter_arg)) == 5)) {
1583 luaL_error(L, "TreeItem:children() field filter must be a string or table of strings");
1584 return 0;
1585 }
1586
1587 if (lua_istable(L, filter_arg)(lua_type(L, (filter_arg)) == 5)) {
1588 int table_len = (int)lua_rawlen(L, filter_arg);
1589 for (int i = 0; i < table_len; i++) {
1590 lua_rawgeti(L, filter_arg, i + 1);
1591 if (lua_type(L, -1) != LUA_TSTRING4) {
1592 luaL_error(L, "TreeItem:children() field filter table entries must be strings");
1593 return 0;
1594 }
1595 lua_pop(L, 1)lua_settop(L, -(1)-1);
1596 }
1597 }
1598 }
1599
1600 proto_node *first_child = NULL((void*)0);
1601
1602 if (ti->tree) {
1603 /* Get the first child from the tree's linked list */
1604 first_child = ((proto_node *)ti->tree)->first_child;
1605 }
1606
1607 /* Create the iterator state userdata that will be used by the iterator closure */
1608 /* This userdata will be garbage collected when the iterator is no longer referenced */
1609 TreeItem_iterator_state *state = (TreeItem_iterator_state *)lua_newuserdata(L, sizeof(TreeItem_iterator_state))lua_newuserdatauv(L,sizeof(TreeItem_iterator_state),1);
1610
1611 /* Initialize all state fields to safe defaults */
1612 state->current_node = first_child; /* Start with first child */
1613 state->field_filters = NULL((void*)0); /* No filters by default */
1614 state->num_filters = 0;
1615 state->recursive = false0; /* Non-recursive by default */
1616 state->stack = NULL((void*)0); /* Stack only allocated if recursive */
1617 state->stack_size = 0;
1618 state->stack_capacity = 0;
1619
1620 /* Set up garbage collection metatable for the state userdata */
1621 /* This ensures proper cleanup when iterator is no longer referenced */
1622 lua_newtable(L)lua_createtable(L, 0, 0); /* Create metatable */
1623 lua_pushcfunction(L, TreeItem_iterator_state_gc)lua_pushcclosure(L, (TreeItem_iterator_state_gc), 0);
1624 lua_setfield(L, -2, "__gc"); /* Set __gc metamethod */
1625 lua_setmetatable(L, -2); /* Apply metatable to userdata */
1626
1627 /* Check for recursive parameter (argument 3) */
1628 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_children_RECURSIVE3 &&
1629 !lua_isnil(L, WSLUA_OPTARG_TreeItem_children_RECURSIVE)(lua_type(L, (3)) == 0)) {
1630 /* Convert Lua boolean to C bool */
1631 state->recursive = lua_toboolean(L, WSLUA_OPTARG_TreeItem_children_RECURSIVE3);
1632 }
1633
1634 /* Check if filter argument (argument 2) is provided */
1635 if (lua_gettop(L) >= WSLUA_OPTARG_TreeItem_children_FIELD_FILTER2 &&
1636 !lua_isnil(L, WSLUA_OPTARG_TreeItem_children_FIELD_FILTER)(lua_type(L, (2)) == 0)) {
1637 int filter_arg = WSLUA_OPTARG_TreeItem_children_FIELD_FILTER2;
1638
1639 if (lua_type(L, filter_arg) == LUA_TSTRING4) {
1640 /* Single filter string - allocate array of size 1 */
1641 state->num_filters = 1;
1642 state->field_filters = (char **)g_malloc(sizeof(char *));
1643 /* Duplicate the string (Lua string becomes C string copy) */
1644 state->field_filters[0] = g_strdup(lua_tostring(L, filter_arg))g_strdup_inline (lua_tolstring(L, (filter_arg), ((void*)0)));
1645 } else if (lua_istable(L, filter_arg)(lua_type(L, (filter_arg)) == 5)) {
1646 /* Table of filter strings - extract all strings from table */
1647 int table_len = (int)lua_rawlen(L, filter_arg);
1648 state->num_filters = table_len;
1649 state->field_filters = (char **)g_malloc(sizeof(char *) * table_len);
1650
1651 /* Iterate through Lua table (1-based indexing) */
1652 for (int i = 0; i < table_len; i++) {
1653 lua_rawgeti(L, filter_arg, i + 1); /* Get table[i+1] */
1654 /* Valid string entry - duplicate it */
1655 state->field_filters[i] = g_strdup(lua_tostring(L, -1))g_strdup_inline (lua_tolstring(L, (-1), ((void*)0)));
1656 lua_pop(L, 1)lua_settop(L, -(1)-1); /* Remove the value from stack */
1657 }
1658 }
1659 /* If neither string nor table, filters remain NULL (no filtering) */
1660 }
1661
1662 /* Push the iterator function as a closure with state as upvalue */
1663 /* The state userdata is kept alive as long as the closure exists */
1664 lua_pushcclosure(L, TreeItem_children_iterator, 1);
1665
1666 WSLUA_RETURN(1)return (1); /* An iterator function for use in Lua for loops. */
1667}
1668
1669WSLUA_METHODstatic int TreeItem_get_field_info(lua_State *L) {
1670 /* Returns the FieldInfo object associated with this tree item.
1671
1672 Returns a FieldInfo object that provides access to the underlying field
1673 information including name, abbreviated name, type, value, data offset,
1674 length, and other protocol field properties.
1675
1676 This is particularly useful for extracting actual field values and
1677 metadata from tree items during packet analysis.
1678
1679 [source,lua]
1680 ----
1681 for child in tree:children() do
1682 local field_info = child:get_field_info()
1683 if field_info then
1684 print("Field name: " .. field_info.name)
1685 print("Field abbrev: " .. field_info.abbrev)
1686 print("Field type: " .. field_info.type)
1687 print("Field value: " .. tostring(field_info.value))
1688 print("Field offset: " .. field_info.offset)
1689 print("Field len: " .. field_info.len)
1690 else
1691 print("No field info (text-only or generated item)")
1692 end
1693 end
1694 ----
1695
1696 NOTE: Field extractors are still required to ensure fields exist in the dissection tree.
1697 This method only provides access to field information for tree items that already exist.
1698
1699 @since 4.7.0
1700 */
1701
1702 /* Retrieve and validate the TreeItem */
1703 TreeItem ti = checkTreeItem(L, 1);
1704 if (!ti)
1705 return 0;
1706
1707 field_info *finfo = NULL((void*)0);
1708
1709 /* Get field_info from the proto_item */
1710 if (ti->item) {
1711 /* Cast proto_item to proto_node to access finfo member */
1712 proto_node *node = (proto_node *)ti->item;
1713 finfo = node->finfo; /* May be NULL for text-only tree items */
1714 }
1715
1716 if (finfo) {
1717 /* Valid field_info exists - create and push FieldInfo Lua object */
1718 /* This makes all field properties accessible from Lua */
1719 push_FieldInfo(L, finfo);
1720 } else {
1721 /* No field_info - this is a text-only tree item or generated content */
1722 lua_pushnil(L);
1723 }
1724
1725 WSLUA_RETURN(1)return (1); /* The FieldInfo object, or nil if not available. */
1726}
1727
1728WSLUA_METAMETHODstatic int TreeItem__tostring(lua_State* L) {
1729 /* Returns a short label of the form `TreeItem: <abbrev>` for an
1730 attached field, `TreeItem: (root)` for a text-only/root tree,
1731 or `TreeItem: (no item)` / `TreeItem: (expired)` /
1732 `TreeItem: (null)` for the degenerate cases. The previous
1733 form dumped only boolean flags (expired/item/tree/same),
1734 which were not very useful for identifying which TreeItem
1735 the debugger is looking at. */
1736 TreeItem ti = toTreeItem(L,1);
1737
1738 if (!ti) {
1739 lua_pushstring(L, "TreeItem: (null)");
1740 } else if (ti->expired) {
1741 lua_pushstring(L, "TreeItem: (expired)");
1742 } else if (!ti->item) {
1743 lua_pushstring(L, "TreeItem: (no item)");
1744 } else {
1745 proto_node *node = (proto_node *)ti->item;
1746 field_info *finfo = node ? node->finfo : NULL((void*)0);
1747 if (finfo && finfo->hfinfo && finfo->hfinfo->abbrev) {
1748 lua_pushfstring(L, "TreeItem: %s", finfo->hfinfo->abbrev);
1749 } else {
1750 lua_pushstring(L, "TreeItem: (root)");
1751 }
1752 }
1753
1754 return 1;
1755}
1756
1757/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
1758static int TreeItem__gc(lua_State* L) {
1759 TreeItem ti = toTreeItem(L,1);
1760 if (!ti) return 0;
1761 if (!ti->expired)
1762 ti->expired = true1;
1763 else
1764 g_free(ti);
1765 return 0;
1766}
1767
1768WSLUA_ATTRIBUTESstatic const wslua_attribute_table TreeItem_attributes[] = {
1769 WSLUA_ATTRIBUTE_RWREG(TreeItem,generated){ "generated", TreeItem_get_generated, TreeItem_set_generated
}
,
1770 WSLUA_ATTRIBUTE_RWREG(TreeItem,hidden){ "hidden", TreeItem_get_hidden, TreeItem_set_hidden },
1771 WSLUA_ATTRIBUTE_RWREG(TreeItem,len){ "len", TreeItem_get_len, TreeItem_set_len },
1772 WSLUA_ATTRIBUTE_RWREG(TreeItem,text){ "text", TreeItem_get_text, TreeItem_set_text },
1773 WSLUA_ATTRIBUTE_ROREG(TreeItem,visible){ "visible", TreeItem_get_visible, ((void*)0) },
1774 { NULL((void*)0), NULL((void*)0), NULL((void*)0) }
1775};
1776
1777WSLUA_METHODSstatic const luaL_Reg TreeItem_methods[] = {
1778 WSLUA_CLASS_FNREG(TreeItem, add_packet_field){ "add_packet_field", TreeItem_add_packet_field },
1779 WSLUA_CLASS_FNREG(TreeItem, add){ "add", TreeItem_add },
1780 WSLUA_CLASS_FNREG(TreeItem, add_le){ "add_le", TreeItem_add_le },
1781 WSLUA_CLASS_FNREG(TreeItem, set_text){ "set_text", TreeItem_set_text },
1782 WSLUA_CLASS_FNREG(TreeItem, append_text){ "append_text", TreeItem_append_text },
1783 WSLUA_CLASS_FNREG(TreeItem, prepend_text){ "prepend_text", TreeItem_prepend_text },
1784 WSLUA_CLASS_FNREG(TreeItem, add_expert_info){ "add_expert_info", TreeItem_add_expert_info },
1785 WSLUA_CLASS_FNREG(TreeItem, add_proto_expert_info){ "add_proto_expert_info", TreeItem_add_proto_expert_info },
1786 WSLUA_CLASS_FNREG(TreeItem, add_tvb_expert_info){ "add_tvb_expert_info", TreeItem_add_tvb_expert_info },
1787 WSLUA_CLASS_FNREG(TreeItem, set_generated){ "set_generated", TreeItem_set_generated },
1788 WSLUA_CLASS_FNREG(TreeItem, set_hidden){ "set_hidden", TreeItem_set_hidden },
1789 WSLUA_CLASS_FNREG(TreeItem, set_len){ "set_len", TreeItem_set_len },
1790 WSLUA_CLASS_FNREG(TreeItem, referenced){ "referenced", TreeItem_referenced },
1791 WSLUA_CLASS_FNREG(TreeItem, get_child_count){ "get_child_count", TreeItem_get_child_count },
1792 WSLUA_CLASS_FNREG(TreeItem, get_parent){ "get_parent", TreeItem_get_parent },
1793 WSLUA_CLASS_FNREG(TreeItem, get_child){ "get_child", TreeItem_get_child },
1794 WSLUA_CLASS_FNREG(TreeItem, children){ "children", TreeItem_children },
1795 WSLUA_CLASS_FNREG(TreeItem, get_field_info){ "get_field_info", TreeItem_get_field_info },
1796 {NULL((void*)0), NULL((void*)0)}};
1797
1798WSLUA_METAstatic const luaL_Reg TreeItem_meta[] = {
1799 WSLUA_CLASS_MTREG(TreeItem,tostring){ "__" "tostring", TreeItem__tostring },
1800 { NULL((void*)0), NULL((void*)0) }
1801};
1802
1803int TreeItem_register(lua_State *L) {
1804 int* etts[] = { &wslua_ett };
1805 wslua_ett = -1; /* Reset to support reload Lua plugins */
1806 WSLUA_REGISTER_CLASS_WITH_ATTRS(TreeItem){ const wslua_class TreeItem_class = { .name = "TreeItem", .class_methods
= TreeItem_methods, .class_meta = TreeItem_meta, .instance_methods
= TreeItem_methods, .instance_meta = TreeItem_meta, .attrs =
TreeItem_attributes }; wslua_register_class(L, &TreeItem_class
); (lua_getfield(L, (-1000000 - 1000), ("TreeItem"))); lua_pushcclosure
(L, (TreeItem__gc), 0); lua_setfield(L, -2, "__gc"); lua_settop
(L, -(1)-1); }
;
1807 if (outstanding_TreeItem != NULL((void*)0)) {
1808 g_ptr_array_unref(outstanding_TreeItem);
1809 }
1810 outstanding_TreeItem = g_ptr_array_new();
1811 proto_register_subtree_array(etts,1);
1812 return 0;
1813}
1814
1815/*
1816 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1817 *
1818 * Local variables:
1819 * c-basic-offset: 4
1820 * tab-width: 8
1821 * indent-tabs-mode: nil
1822 * End:
1823 *
1824 * vi: set shiftwidth=4 tabstop=8 expandtab:
1825 * :indentSize=4:tabSize=8:noTabs=true:
1826 */