Bug Summary

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