4 * Wireshark's interface to the Lua Programming Language
6 * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
7 * (c) 2008, Balint Reczey <balint.reczey@ericsson.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
18 /* WSLUA_MODULE Tree Adding Information To The Dissection Tree */
21 #include <epan/exceptions.h>
22 #include <epan/show_exception.h>
24 static int wslua_ett
= -1;
26 static GPtrArray
* outstanding_TreeItem
;
29 /* pushing a TreeItem with a NULL item or subtree is completely valid for this function */
30 TreeItem
push_TreeItem(lua_State
*L
, proto_tree
*tree
, proto_item
*item
) {
31 TreeItem ti
= g_new(struct _wslua_treeitem
, 1);
37 g_ptr_array_add(outstanding_TreeItem
, ti
);
39 return *(pushTreeItem(L
,ti
));
42 /* creates the TreeItem but does NOT push it into Lua */
43 TreeItem
create_TreeItem(proto_tree
* tree
, proto_item
* item
)
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
= false;
53 CLEAR_OUTSTANDING(TreeItem
, expired
, true)
55 WSLUA_CLASS_DEFINE(TreeItem
,FAIL_ON_NULL_OR_EXPIRED("TreeItem"));
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.
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)`).
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.
73 /* the following is used by TreeItem_add_packet_field() - this can THROW errors */
75 try_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
)
79 proto_item
*volatile item
= NULL
;
83 /* these all generate ByteArrays */
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
,
96 pushByteArray(L
, gba
);
97 lua_pushinteger(L
, endoff
);
102 case FT_ABSOLUTE_TIME
:
103 case FT_RELATIVE_TIME
:
105 /* nstime_t will be g_free'd by Lua */
106 nstime_t
*nstime
= g_new0(nstime_t
, 1);
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
);
111 pushNSTime(L
,nstime
);
112 lua_pushinteger(L
, endoff
);
123 item
= proto_tree_add_item_ret_int(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
,
124 tvbr
->offset
, tvbr
->len
, encoding
,
126 lua_pushinteger(L
, (lua_Integer
)ret
);
127 lua_pushinteger(L
, tvbr
->offset
+ tvbr
->len
);
137 item
= proto_tree_add_item_ret_int64(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
,
138 tvbr
->offset
, tvbr
->len
, encoding
,
141 lua_pushinteger(L
, tvbr
->offset
+ tvbr
->len
);
152 item
= proto_tree_add_item_ret_uint(tree_item
-> tree
, hfid
, tvbr
->tvb
->ws_tvb
,
153 tvbr
->offset
, tvbr
->len
, encoding
,
155 lua_pushinteger(L
, (lua_Integer
)ret
);
156 lua_pushinteger(L
, tvbr
->offset
+ tvbr
->len
);
166 item
= proto_tree_add_item_ret_uint64(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
,
167 tvbr
->offset
, tvbr
->len
, encoding
,
170 lua_pushinteger(L
, tvbr
->offset
+ tvbr
->len
);
177 item
= proto_tree_add_item_ret_boolean(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
,
178 tvbr
->offset
, tvbr
->len
, encoding
,
180 lua_pushboolean(L
, ret
);
181 lua_pushinteger(L
, tvbr
->offset
+ tvbr
->len
);
189 item
= proto_tree_add_item_ret_string_and_length(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
,
190 tvbr
->offset
, tvbr
->len
, encoding
,
192 lua_pushstring(L
, ret
);
193 lua_pushinteger(L
, tvbr
->offset
+ len
);
194 wmem_free(NULL
, (void*)ret
);
202 item
= proto_tree_add_item_ret_string_and_length(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
,
203 tvbr
->offset
, -1, encoding
,
205 lua_pushstring(L
, ret
);
206 lua_pushinteger(L
, tvbr
->offset
+ len
);
207 wmem_free(NULL
, (void*)ret
);
214 item
= proto_tree_add_item_ret_float(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
,
215 tvbr
->offset
, tvbr
->len
, encoding
,
217 lua_pushnumber(L
, (lua_Number
)ret
);
218 lua_pushinteger(L
, tvbr
->offset
+ tvbr
->len
);
225 item
= proto_tree_add_item_ret_double(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
,
226 tvbr
->offset
, tvbr
->len
, encoding
,
228 lua_pushnumber(L
, (lua_Number
)ret
);
229 lua_pushinteger(L
, tvbr
->offset
+ tvbr
->len
);
235 Address addr
= g_new(address
,1);
237 item
= proto_tree_add_item_ret_ipv4(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
,
238 tvbr
->offset
, tvbr
->len
, encoding
,
240 alloc_address_wmem(NULL
, addr
, AT_IPv4
, sizeof(ret
), &ret
);
241 pushAddress(L
, addr
);
242 lua_pushinteger(L
, tvbr
->offset
+ tvbr
->len
);
248 Address addr
= g_new(address
, 1);
250 item
= proto_tree_add_item_ret_ipv6(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
,
251 tvbr
->offset
, tvbr
->len
, encoding
,
253 alloc_address_wmem(NULL
, addr
, AT_IPv6
, sizeof(ret
), &ret
);
254 pushAddress(L
, addr
);
255 lua_pushinteger(L
, tvbr
->offset
+ tvbr
->len
);
261 Address addr
= g_new(address
, 1);
262 uint8_t bytes
[FT_ETHER_LEN
];
264 item
= proto_tree_add_item_ret_ether(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
,
265 tvbr
->offset
, tvbr
->len
, encoding
,
267 alloc_address_wmem(NULL
, addr
, AT_ETHER
, sizeof(bytes
), bytes
);
268 pushAddress(L
, addr
);
269 lua_pushinteger(L
, tvbr
->offset
+ tvbr
->len
);
274 item
= proto_tree_add_item(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
, tvbr
->offset
, tvbr
->len
, encoding
);
280 if (ret_err
) *ret_err
= err
;
285 WSLUA_METHOD
TreeItem_add_packet_field(lua_State
*L
) {
287 Adds a new child tree for the given <<lua_class_ProtoField,`ProtoField`>> object to this tree item,
288 returning the new child <<lua_class_TreeItem,`TreeItem`>>.
290 Unlike `TreeItem:add()` and `TreeItem:add_le()`, the <<lua_class_ProtoField,`ProtoField`>> argument
291 is not optional, and cannot be a `Proto` object. Instead, this function always
292 uses the <<lua_class_ProtoField,`ProtoField`>> to determine the type of field to extract from the
293 passed-in `TvbRange`, highlighting the relevant bytes in the Packet Bytes pane
294 of the GUI (if there is a GUI), etc. If no <<lua_class_TvbRange,`TvbRange`>>is given, no bytes are
295 highlighted and the field's value cannot be determined; the <<lua_class_ProtoField,`ProtoField`>> must
296 have been defined/created not to have a length in such a case, or an error will
297 occur. For backwards-compatibility reasons the `encoding` argument, however,
300 Unlike `TreeItem:add()` and `TreeItem:add_le()`, this function performs both
301 big-endian and little-endian decoding, by setting the `encoding` argument to
302 be `ENC_BIG_ENDIAN` or `ENC_LITTLE_ENDIAN`.
304 The signature of this function:
308 tree_item:add_packet_field(proto_field [,tvbrange], encoding, ...)
311 This function returns more than just the new child <<lua_class_TreeItem,`TreeItem`>>.
312 The child is the first return value, so that function chaining will still work; but it
313 also returns more information. The second return is the value of the extracted field
314 (i.e., a number, `UInt64`, `Address`, etc.). The third return is is the offset where
315 data should be read next. This is useful when the length of the field is not known in
316 advance. The additional return values may be null if the field type is not well supported
319 This function can extract a <<lua_class_ProtoField,`ProtoField`>> of type `ftypes.BYTES`
320 or `ftypes.ABSOLUTE_TIME` from a string in the `TvbRange` in ASCII-based and similar
321 encodings. For example, a `ProtoField` of `ftypes.BYTES` can be extracted from a `TvbRange`
322 containing the ASCII string "a1b2c3d4e5f6", and it will correctly decode the ASCII both in the
323 tree as well as for the second return value, which will be a <<lua_class_ByteArray,`ByteArray`>>.
324 To do so, you must set the `encoding` argument of this function to the appropriate string `ENC_*`
325 value, bitwise-or'd (or added) with the `ENC_STR_HEX` value and one or more `ENC_SEP_XXX` values
326 indicating which encodings are allowed. For `ftypes.ABSOLUTE_TIME`, one of the `ENC_ISO_8601_*`
327 encodings or `ENC_IMF_DATE_TIME` must be used, and the second return value is a <<lua_class_NSTime,`NSTime`>>.
328 Only single-byte ASCII digit string encodings such as `ENC_ASCII` and `ENC_UTF_8` can be used for this.
330 For example, assuming the <<lua_class_Tvb,`Tvb`>> named "`tvb`" contains the string "abcdef"
331 (61 62 63 64 65 66 in hex):
335 -- this is done earlier in the script
336 local myfield = ProtoField.new("Transaction ID", "myproto.trans_id", ftypes.BYTES)
337 myproto.fields = { myfield }
339 -- this is done inside a dissector, post-dissector, or heuristic function
340 -- child will be the created child tree, and value will be the ByteArray "abcdef" or nil on failure
341 local child, value = tree:add_packet_field(myfield, tvb:range(0,6), ENC_UTF_8 + ENC_STR_HEX + ENC_SEP_NONE)
345 #define WSLUA_ARG_TreeItem_add_packet_field_PROTOFIELD 2 /* The ProtoField field object to add to the tree. */
346 #define WSLUA_OPTARG_TreeItem_add_packet_field_TVBRANGE 3 /* The <<lua_class_TvbRange,`TvbRange`>> of bytes in the packet this tree item covers/represents. */
347 #define WSLUA_ARG_TreeItem_add_packet_field_ENCODING 4 /* The field's encoding in the `TvbRange`. */
348 #define WSLUA_OPTARG_TreeItem_add_packet_field_LABEL 5 /* One or more strings to append to the created <<lua_class_TreeItem,`TreeItem`>>. */
349 volatile TvbRange tvbr
;
354 TreeItem tree_item
= shiftTreeItem(L
,1);
356 proto_item
* item
= NULL
;
358 volatile int err
= 0;
359 const char *volatile error
= NULL
;
362 return luaL_error(L
,"not a TreeItem!");
364 if (tree_item
->expired
) {
365 luaL_error(L
,"expired TreeItem");
369 if (! ( field
= shiftProtoField(L
,1) ) ) {
370 luaL_error(L
,"TreeField:add_packet_field not passed a ProtoField");
373 if (field
->hfid
== -2) {
374 luaL_error(L
, "ProtoField %s unregistered (not added to a Proto.fields attribute)", field
->abbrev
);
380 tvbr
= shiftTvbRange(L
,1);
382 /* No TvbRange specified */
383 tvbr
= wmem_new(lua_pinfo
->pool
, struct _wslua_tvbrange
);
384 tvbr
->tvb
= wmem_new(lua_pinfo
->pool
, struct _wslua_tvb
);
385 tvbr
->tvb
->ws_tvb
= lua_tvb
;
390 encoding
= wslua_checkuint(L
,1);
393 /* get the number of additional args before we add more to the stack */
394 nargs
= lua_gettop(L
);
396 /* XXX: why is this being done? If the length was -1, FT_STRINGZ figures out
397 * the right length in tvb_get_stringz_enc(); if it was 0, it should remain zero;
398 * if it was greater than zero, then it's the length the caller wanted.
400 if (type
== FT_STRINGZ
) {
401 switch (encoding
& ENC_CHARENCODING_MASK
) {
405 tvbr
->len
= tvb_unicode_strsize (tvbr
->tvb
->ws_tvb
, tvbr
->offset
);
409 if (tvb_find_uint8 (tvbr
->tvb
->ws_tvb
, tvbr
->offset
, -1, 0) == -1) {
410 luaL_error(L
,"out of bounds");
413 tvbr
->len
= tvb_strsize (tvbr
->tvb
->ws_tvb
, tvbr
->offset
);
420 item
= try_add_packet_field(L
, tree_item
, tvbr
, hfid
, type
, encoding
, &errx
);
423 show_exception(tvbr
->tvb
->ws_tvb
, lua_pinfo
, tree_item
->tree
, EXCEPT_CODE
, GET_MESSAGE
);
424 error
= "Lua programming error";
427 if (error
) { WSLUA_ERROR(TreeItem_add_packet_field
,error
); }
436 s
= lua_tostring(L
,1);
437 if (s
) proto_item_append_text(item
, " %s", s
);
442 push_TreeItem(L
, proto_item_add_subtree(item
,ett
> 0 ? ett
: wslua_ett
), item
);
444 /* move the tree object before the field value */
447 WSLUA_RETURN(3); /* The new child <<lua_class_TreeItem,`TreeItem`>>, the field's extracted value or nil, and offset or nil. */
450 /* The following is used by TreeItem_add() and TreeItem_le() and can THROW.
451 * It should be called inside a TRY (e.g. WRAP_NON_LUA_EXCEPTIONS) block and
452 * THROW_LUA_ERROR should be used insteadof lua[L]_error.
454 static int TreeItem_add_item_any(lua_State
*L
, bool little_endian
) {
460 ftenum_t type
= FT_NONE
;
461 TreeItem tree_item
= shiftTreeItem(L
,1);
462 proto_item
* item
= NULL
;
465 THROW_LUA_ERROR("not a TreeItem!");
467 if (tree_item
->expired
) {
468 THROW_LUA_ERROR("expired TreeItem");
472 if (! ( field
= shiftProtoField(L
,1) ) ) {
473 if (( proto
= shiftProto(L
,1) )) {
477 } else if (lua_isnil(L
, 1)) {
478 THROW_LUA_ERROR("first argument to TreeItem:add is nil!");
486 tvbr
= shiftTvbRange(L
,1);
489 tvbr
= wmem_new(lua_pinfo
->pool
, struct _wslua_tvbrange
);
490 tvbr
->tvb
= wmem_new(lua_pinfo
->pool
, struct _wslua_tvb
);
491 tvbr
->tvb
->ws_tvb
= lua_tvb
;
497 /* hfid is > 0 when the first arg was a ProtoField or Proto */
499 if (type
== FT_STRINGZ
) {
500 if (tvb_find_uint8 (tvbr
->tvb
->ws_tvb
, tvbr
->offset
, -1, 0) == -1) {
501 THROW_LUA_ERROR("out of bounds");
504 tvbr
->len
= tvb_strsize (tvbr
->tvb
->ws_tvb
, tvbr
->offset
);
508 /* if we got here, the (L,1) index is the value to add, instead of decoding from the Tvb */
510 /* It's invalid for it to be nil (which has been documented for
511 * a long time). Make sure we throw our error instead of an
512 * internal Lua error (due to nested setjmp/longjmp).
514 if (lua_isnil(L
, 1)) {
515 THROW_LUA_ERROR("TreeItem:add value argument is nil!");
520 item
= proto_tree_add_item(tree_item
->tree
,hfid
,tvbr
->tvb
->ws_tvb
,tvbr
->offset
,tvbr
->len
,ENC_NA
);
521 lua_pushinteger(L
,0);
527 switch(lua_type(L
, 1)) {
530 val
= checkUInt64(L
, 1);
534 /* this needs to use checkinteger so that it can accept a Lua boolean and coerce it to an int */
535 val
= (uint64_t) (wslua_tointeger(L
,1));
537 item
= proto_tree_add_boolean(tree_item
->tree
,hfid
,tvbr
->tvb
->ws_tvb
,tvbr
->offset
,tvbr
->len
,val
);
546 item
= proto_tree_add_uint(tree_item
->tree
,hfid
,tvbr
->tvb
->ws_tvb
,tvbr
->offset
,tvbr
->len
,wslua_checkuint32(L
,1));
552 item
= proto_tree_add_int(tree_item
->tree
,hfid
,tvbr
->tvb
->ws_tvb
,tvbr
->offset
,tvbr
->len
,wslua_checkint32(L
,1));
555 item
= proto_tree_add_float(tree_item
->tree
,hfid
,tvbr
->tvb
->ws_tvb
,tvbr
->offset
,tvbr
->len
,(float)luaL_checknumber(L
,1));
558 item
= proto_tree_add_double(tree_item
->tree
,hfid
,tvbr
->tvb
->ws_tvb
,tvbr
->offset
,tvbr
->len
,(double)luaL_checknumber(L
,1));
560 case FT_ABSOLUTE_TIME
:
561 case FT_RELATIVE_TIME
:
562 item
= proto_tree_add_time(tree_item
->tree
,hfid
,tvbr
->tvb
->ws_tvb
,tvbr
->offset
,tvbr
->len
,checkNSTime(L
,1));
566 item
= proto_tree_add_string(tree_item
->tree
,hfid
,tvbr
->tvb
->ws_tvb
,tvbr
->offset
,tvbr
->len
,luaL_checkstring(L
,1));
569 item
= proto_tree_add_bytes(tree_item
->tree
,hfid
,tvbr
->tvb
->ws_tvb
,tvbr
->offset
,tvbr
->len
, (const uint8_t*) luaL_checkstring(L
,1));
572 item
= proto_tree_add_uint64(tree_item
->tree
,hfid
,tvbr
->tvb
->ws_tvb
,tvbr
->offset
,tvbr
->len
,checkUInt64(L
,1));
575 item
= proto_tree_add_int64(tree_item
->tree
,hfid
,tvbr
->tvb
->ws_tvb
,tvbr
->offset
,tvbr
->len
,checkInt64(L
,1));
579 Address addr
= checkAddress(L
,1);
582 if (addr
->type
!= AT_IPv4
) {
583 THROW_LUA_ERROR("Expected IPv4 address for FT_IPv4 field");
588 * The address is not guaranteed to be aligned on a
589 * 32-bit boundary, so we can't safely dereference
590 * the pointer as if it were so aligned.
592 memcpy(&addr_value
, addr
->data
, sizeof addr_value
);
593 item
= proto_tree_add_ipv4(tree_item
->tree
,hfid
,tvbr
->tvb
->ws_tvb
,tvbr
->offset
,tvbr
->len
,addr_value
);
598 Address addr
= checkAddress(L
,1);
599 if (addr
->type
!= AT_IPv6
) {
600 THROW_LUA_ERROR("Expected IPv6 address for FT_IPv6 field");
604 item
= proto_tree_add_ipv6(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
, tvbr
->offset
, tvbr
->len
, (const ws_in6_addr
*)addr
->data
);
609 Address addr
= checkAddress(L
,1);
610 if (addr
->type
!= AT_ETHER
) {
611 THROW_LUA_ERROR("Expected MAC address for FT_ETHER field");
615 item
= proto_tree_add_ether(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
, tvbr
->offset
, tvbr
->len
, (const uint8_t *)addr
->data
);
627 THROW_LUA_ERROR("%s not yet supported", ftype_name(type
));
634 if (type
== FT_FRAMENUM
) {
635 THROW_LUA_ERROR("ProtoField FRAMENUM cannot fetch value from Tvb");
638 /* the Lua stack is empty - no value was given - so decode the value from the tvb */
639 item
= proto_tree_add_item(tree_item
->tree
, hfid
, tvbr
->tvb
->ws_tvb
, tvbr
->offset
, tvbr
->len
, little_endian
? ENC_LITTLE_ENDIAN
: ENC_BIG_ENDIAN
);
642 if ( lua_gettop(L
) ) {
643 /* if there was a value, it was removed earlier, so what's left is the display string to set */
644 const char* s
= lua_tostring(L
,1);
645 if (s
) proto_item_set_text(item
,"%s",s
);
650 /* no ProtoField or Proto was given - we're adding a text-only field,
651 * any remaining parameters are parts of the text label. */
653 const char* s
= lua_tostring(L
,1);
654 const int hf
= get_hf_wslua_text();
656 /* use proto_tree_add_none_format() instead? */
657 item
= proto_tree_add_item(tree_item
->tree
, hf
, tvbr
->tvb
->ws_tvb
, tvbr
->offset
, tvbr
->len
, ENC_NA
);
658 proto_item_set_text(item
, "%s", s
);
660 THROW_LUA_ERROR("Internal error: hf_wslua_text not registered");
664 THROW_LUA_ERROR("Tree item ProtoField/Protocol handle is invalid (ProtoField/Proto not registered?)");
668 while(lua_gettop(L
)) {
669 /* keep appending more text */
670 const char* s
= lua_tostring(L
,1);
671 if (s
) proto_item_append_text(item
, " %s", s
);
675 push_TreeItem(L
, proto_item_add_subtree(item
,ett
> 0 ? ett
: wslua_ett
), item
);
681 WSLUA_METHOD
TreeItem_add(lua_State
*L
) {
683 Adds a child item to this tree item, returning the new child <<lua_class_TreeItem,`TreeItem`>>.
685 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.
687 This function has a complicated form: 'treeitem:add([protofield,] [tvbrange,] [[value], label]])', such that if the first
688 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;
689 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',
690 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
691 be either a <<lua_class_TvbRange,`TvbRange`>> or a label, and the value is not in use.
698 local proto_foo = Proto("foo", "Foo Protocol")
699 proto_foo.fields.bytes = ProtoField.bytes("foo.bytes", "Byte array")
700 proto_foo.fields.u16 = ProtoField.uint16("foo.u16", "Unsigned short", base.HEX)
702 function proto_foo.dissector(buf, pinfo, tree)
703 -- ignore packets less than 4 bytes long
704 if buf:len() < 4 then return end
706 -- ##############################################
707 -- # Assume buf(0,4) == {0x00, 0x01, 0x00, 0x02}
708 -- ##############################################
710 local t = tree:add( proto_foo, buf() )
712 -- Adds a byte array that shows as: "Byte array: 00010002"
713 t:add( proto_foo.fields.bytes, buf(0,4) )
715 -- Adds a byte array that shows as "Byte array: 313233"
716 -- (the ASCII char code of each character in "123")
717 t:add( proto_foo.fields.bytes, buf(0,4), "123" )
719 -- Adds a tree item that shows as: "Unsigned short: 0x0001"
720 t:add( proto_foo.fields.u16, buf(0,2) )
722 -- Adds a tree item that shows as: "Unsigned short: 0x0064"
723 t:add( proto_foo.fields.u16, buf(0,2), 100 )
725 -- Adds a tree item that shows as: "Unsigned short: 0x0064 ( big endian )"
726 t:add( proto_foo.fields.u16, buf(1,2), 100, nil, "(", nil, "big", 999, nil, "endian", nil, ")" )
728 -- LITTLE ENDIAN: Adds a tree item that shows as: "Unsigned short: 0x0100"
729 t:add_le( proto_foo.fields.u16, buf(0,2) )
731 -- LITTLE ENDIAN: Adds a tree item that shows as: "Unsigned short: 0x6400"
732 t:add_le( proto_foo.fields.u16, buf(0,2), 100 )
734 -- LITTLE ENDIAN: Adds a tree item that shows as: "Unsigned short: 0x6400 ( little endian )"
735 t:add_le( proto_foo.fields.u16, buf(1,2), 100, nil, "(", nil, "little", 999, nil, "endian", nil, ")" )
738 udp_table = DissectorTable.get("udp.port")
739 udp_table:add(7777, proto_foo)
742 #define WSLUA_OPTARG_TreeItem_add_PROTOFIELD 2 /* The <<lua_class_ProtoField,`ProtoField`>> field or <<lua_class_Proto,`Proto`>> protocol object to add to the tree. */
743 #define WSLUA_OPTARG_TreeItem_add_TVBRANGE 3 /* The <<lua_class_TvbRange,`TvbRange`>> of bytes in the packet this tree item covers/represents. */
744 #define WSLUA_OPTARG_TreeItem_add_VALUE 4 /* The field's value, instead of the ProtoField/Proto one. */
745 #define WSLUA_OPTARG_TreeItem_add_LABEL 5 /* One or more strings to use for the tree item label, instead of the ProtoField/Proto one. */
748 WRAP_NON_LUA_EXCEPTIONS(
749 ret
= TreeItem_add_item_any(L
,false);
751 WSLUA_RETURN(ret
); /* The new child TreeItem. */
754 WSLUA_METHOD
TreeItem_add_le(lua_State
*L
) {
756 Adds a child item to this tree item, returning the new child <<lua_class_TreeItem,`TreeItem`>>.
758 If the <<lua_class_ProtoField,`ProtoField`>> represents a numeric value (int, uint or float), then it's treated as a Little Endian value.
760 This function has a complicated form: 'treeitem:add_le([protofield,] [tvbrange,] [[value], label]])', such that if the first
761 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;
762 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',
763 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
764 be either a <<lua_class_TvbRange,`TvbRange`>> or a label, and the value is not in use.
766 #define WSLUA_OPTARG_TreeItem_add_le_PROTOFIELD 2 /* The ProtoField field or Proto protocol object to add to the tree. */
767 #define WSLUA_OPTARG_TreeItem_add_le_TVBRANGE 3 /* The TvbRange of bytes in the packet this tree item covers/represents. */
768 #define WSLUA_OPTARG_TreeItem_add_le_VALUE 4 /* The field's value, instead of the ProtoField/Proto one. */
769 #define WSLUA_OPTARG_TreeItem_add_le_LABEL 5 /* One or more strings to use for the tree item label, instead of the ProtoField/Proto one. */
771 WRAP_NON_LUA_EXCEPTIONS(
772 ret
= TreeItem_add_item_any(L
,true);
774 WSLUA_RETURN(ret
); /* The new child TreeItem. */
777 /* WSLUA_ATTRIBUTE TreeItem_text RW Set/get the <<lua_class_TreeItem,`TreeItem`>>'s display string (string).
779 For the getter, if the TreeItem has no display string, then nil is returned.
781 static int TreeItem_get_text(lua_State
* L
) {
782 TreeItem ti
= checkTreeItem(L
,1);
783 char label_str
[ITEM_LABEL_LENGTH
+1];
786 if (ti
->item
&& PITEM_FINFO(ti
->item
)) {
787 field_info
*fi
= PITEM_FINFO(ti
->item
);
790 label_ptr
= label_str
;
791 proto_item_fill_label(fi
, label_str
, NULL
);
793 label_ptr
= fi
->rep
->representation
;
796 lua_pushstring(L
, label_ptr
);
807 /* the following is used as both a method and attribute */
808 WSLUA_METHOD
TreeItem_set_text(lua_State
*L
) {
809 /* Sets the text of the label.
811 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
813 #define WSLUA_ARG_TreeItem_set_text_TEXT 2 /* The text to be used. */
814 TreeItem ti
= checkTreeItem(L
,1);
815 const char* s
= luaL_checkstring(L
,WSLUA_ARG_TreeItem_set_text_TEXT
);
817 proto_item_set_text(ti
->item
,"%s",s
);
819 /* copy the TreeItem userdata so we give it back */
822 WSLUA_RETURN(1); /* The same TreeItem. */
825 WSLUA_METHOD
TreeItem_append_text(lua_State
*L
) {
826 /* Appends text to the label.
828 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
830 #define WSLUA_ARG_TreeItem_append_text_TEXT 2 /* The text to be appended. */
831 TreeItem ti
= checkTreeItem(L
,1);
832 const char* s
= luaL_checkstring(L
,WSLUA_ARG_TreeItem_append_text_TEXT
);
834 proto_item_append_text(ti
->item
,"%s",s
);
836 /* copy the TreeItem userdata so we give it back */
839 WSLUA_RETURN(1); /* The same TreeItem. */
842 WSLUA_METHOD
TreeItem_prepend_text(lua_State
*L
) {
843 /* Prepends text to the label.
845 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
847 #define WSLUA_ARG_TreeItem_prepend_text_TEXT 2 /* The text to be prepended. */
848 TreeItem ti
= checkTreeItem(L
,1);
849 const char* s
= luaL_checkstring(L
,WSLUA_ARG_TreeItem_prepend_text_TEXT
);
851 proto_item_prepend_text(ti
->item
,"%s",s
);
853 /* copy the TreeItem userdata so we give it back */
856 WSLUA_RETURN(1); /* The same TreeItem. */
859 WSLUA_METHOD
TreeItem_add_expert_info(lua_State
*L
) {
860 /* Sets the expert flags of the item and adds expert info to the packet.
862 This function does *not* create a truly filterable expert info for a protocol.
863 Instead you should use `TreeItem.add_proto_expert_info()`.
865 Note: This function is provided for backwards compatibility only, and should not
866 be used in new Lua code. It may be removed in the future. You should only
867 use `TreeItem.add_proto_expert_info()`.
869 #define WSLUA_OPTARG_TreeItem_add_expert_info_GROUP 2 /* One of:
886 or `PI_DISSECTOR_BUG`. */
887 #define WSLUA_OPTARG_TreeItem_add_expert_info_SEVERITY 3 /* One of:
893 #define WSLUA_OPTARG_TreeItem_add_expert_info_TEXT 4 /* The text for the expert info display. */
894 TreeItem ti
= checkTreeItem(L
,1);
895 int group
= (int)luaL_optinteger(L
,WSLUA_OPTARG_TreeItem_add_expert_info_GROUP
,PI_DEBUG
);
896 int severity
= (int)luaL_optinteger(L
,WSLUA_OPTARG_TreeItem_add_expert_info_SEVERITY
,PI_CHAT
);
897 expert_field
* ei_info
= wslua_get_expert_field(group
, severity
);
900 if (lua_gettop(L
) >= WSLUA_OPTARG_TreeItem_add_expert_info_TEXT
) {
901 str
= wslua_checkstring_only(L
, WSLUA_OPTARG_TreeItem_add_expert_info_TEXT
);
902 expert_add_info_format(lua_pinfo
, ti
->item
, ei_info
, "%s", str
);
904 expert_add_info(lua_pinfo
, ti
->item
, ei_info
);
907 /* copy the TreeItem userdata so we give it back */
910 WSLUA_RETURN(1); /* The same TreeItem. */
913 WSLUA_METHOD
TreeItem_add_proto_expert_info(lua_State
*L
) {
914 /* Sets the expert flags of the tree item and adds expert info to the packet. */
915 #define WSLUA_ARG_TreeItem_add_proto_expert_info_EXPERT 2 /* The <<lua_class_ProtoExpert,`ProtoExpert`>> object to add to the tree. */
916 #define WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT 3 /* Text for the expert info display
917 (default is to use the registered
919 TreeItem ti
= checkTreeItem(L
,1);
920 ProtoExpert expert
= checkProtoExpert(L
,WSLUA_ARG_TreeItem_add_proto_expert_info_EXPERT
);
923 if (expert
->ids
.ei
== EI_INIT_EI
|| expert
->ids
.hf
== EI_INIT_HF
) {
924 luaL_error(L
, "ProtoExpert is not registered");
928 if (lua_gettop(L
) >= WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT
) {
929 str
= wslua_checkstring_only(L
, WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT
);
930 expert_add_info_format(lua_pinfo
, ti
->item
, &expert
->ids
, "%s", str
);
932 expert_add_info(lua_pinfo
, ti
->item
, &expert
->ids
);
935 /* copy the TreeItem userdata so we give it back */
938 WSLUA_RETURN(1); /* The same TreeItem. */
941 WSLUA_METHOD
TreeItem_add_tvb_expert_info(lua_State
*L
) {
942 /* Sets the expert flags of the tree item and adds expert info to the packet
943 associated with the <<lua_class_Tvb,`Tvb`>> or <<lua_class_TvbRange,`TvbRange`>> bytes in the packet. */
944 #define WSLUA_ARG_TreeItem_add_tvb_expert_info_EXPERT 2 /* The <<lua_class_ProtoExpert,`ProtoExpert`>> object to add to the tree. */
945 #define WSLUA_ARG_TreeItem_add_tvb_expert_info_TVB 3 /* The <<lua_class_Tvb,`Tvb`>> or <<lua_class_TvbRange,`TvbRange`>> object bytes to associate
946 the expert info with. */
947 #define WSLUA_OPTARG_TreeItem_add_tvb_expert_info_TEXT 4 /* Text for the expert info display
948 (default is to use the registered
950 TreeItem ti
= checkTreeItem(L
,1);
951 ProtoExpert expert
= checkProtoExpert(L
,WSLUA_ARG_TreeItem_add_proto_expert_info_EXPERT
);
955 if (expert
->ids
.ei
== EI_INIT_EI
|| expert
->ids
.hf
== EI_INIT_HF
) {
956 luaL_error(L
, "ProtoExpert is not registered");
960 tvbr
= shiftTvbRange(L
,WSLUA_ARG_TreeItem_add_tvb_expert_info_TVB
);
963 tvbr
= wmem_new(lua_pinfo
->pool
, struct _wslua_tvbrange
);
964 tvbr
->tvb
= shiftTvb(L
,WSLUA_ARG_TreeItem_add_tvb_expert_info_TVB
);
966 tvbr
->tvb
= wmem_new(lua_pinfo
->pool
, struct _wslua_tvb
);
968 tvbr
->tvb
->ws_tvb
= lua_tvb
;
973 if (lua_gettop(L
) >= WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT
) {
974 str
= wslua_checkstring_only(L
, WSLUA_OPTARG_TreeItem_add_proto_expert_info_TEXT
);
975 proto_tree_add_expert_format(ti
->tree
, lua_pinfo
, &expert
->ids
,
976 tvbr
->tvb
->ws_tvb
, tvbr
->offset
, tvbr
->len
,
979 proto_tree_add_expert(ti
->tree
, lua_pinfo
, &expert
->ids
,
980 tvbr
->tvb
->ws_tvb
, tvbr
->offset
, tvbr
->len
);
983 /* copy the TreeItem userdata so we give it back */
986 WSLUA_RETURN(1); /* The same TreeItem. */
990 /* WSLUA_ATTRIBUTE TreeItem_visible RO Get the <<lua_class_TreeItem,`TreeItem`>>'s subtree visibility status (boolean). */
991 static int TreeItem_get_visible(lua_State
* L
) {
992 TreeItem ti
= checkTreeItem(L
,1);
995 lua_pushboolean(L
, PTREE_DATA(ti
->tree
)->visible
);
998 lua_pushboolean(L
, false);
1005 /* WSLUA_ATTRIBUTE TreeItem_generated RW Set/get the <<lua_class_TreeItem,`TreeItem`>>'s generated state (boolean). */
1006 static int TreeItem_get_generated(lua_State
* L
) {
1007 TreeItem ti
= checkTreeItem(L
,1);
1009 lua_pushboolean(L
, proto_item_is_generated(ti
->item
));
1014 /* the following is used as both a method and attribute. As a method it defaults
1015 to setting the value, because that's what it used to do before. */
1016 WSLUA_METHOD
TreeItem_set_generated(lua_State
*L
) {
1017 /* Marks the <<lua_class_TreeItem,`TreeItem`>> as a generated field (with data inferred but not contained in the packet).
1019 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
1021 #define WSLUA_OPTARG_TreeItem_set_generated_BOOL 2 /* A Lua boolean, which if `true` sets the <<lua_class_TreeItem,`TreeItem`>>
1022 generated flag, else clears it (default=true) */
1023 TreeItem ti
= checkTreeItem(L
,1);
1024 bool set
= wslua_optbool(L
, WSLUA_OPTARG_TreeItem_set_generated_BOOL
, true);
1027 proto_item_set_generated(ti
->item
);
1030 FI_RESET_FLAG(PITEM_FINFO(ti
->item
), FI_GENERATED
);
1033 /* copy the TreeItem userdata so we give it back */
1034 lua_pushvalue(L
, 1);
1036 WSLUA_RETURN(1); /* The same TreeItem. */
1039 /* WSLUA_ATTRIBUTE TreeItem_hidden RW Set/get <<lua_class_TreeItem,`TreeItem`>>'s hidden state (boolean). */
1040 static int TreeItem_get_hidden(lua_State
* L
) {
1041 TreeItem ti
= checkTreeItem(L
,1);
1043 lua_pushboolean(L
, proto_item_is_hidden(ti
->item
));
1048 /* the following is used as both a method and attribute. As a method it defaults
1049 to setting the value, because that's what it used to do before. */
1050 WSLUA_METHOD
TreeItem_set_hidden(lua_State
*L
) {
1052 Marks the <<lua_class_TreeItem,`TreeItem`>> as a hidden field (neither displayed nor used in filters).
1055 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
1057 #define WSLUA_OPTARG_TreeItem_set_hidden_BOOL 2 /* A Lua boolean, which if `true` sets the <<lua_class_TreeItem,`TreeItem`>>
1058 hidden flag, else clears it. Default is `true`. */
1059 TreeItem ti
= checkTreeItem(L
,1);
1060 bool set
= wslua_optbool(L
, WSLUA_OPTARG_TreeItem_set_hidden_BOOL
, true);
1063 proto_item_set_hidden(ti
->item
);
1065 proto_item_set_visible(ti
->item
);
1068 /* copy the TreeItem userdata so we give it back */
1069 lua_pushvalue(L
, 1);
1071 WSLUA_RETURN(1); /* The same TreeItem. */
1074 /* WSLUA_ATTRIBUTE TreeItem_len RW Set/get <<lua_class_TreeItem,`TreeItem`>>'s length inside tvb, after it has already been created. */
1075 static int TreeItem_get_len(lua_State
* L
) {
1076 TreeItem ti
= checkTreeItem(L
,1);
1079 /* XXX - this is *NOT* guaranteed to return a correct value! */
1080 len
= proto_item_get_len(ti
->item
);
1082 lua_pushinteger(L
, len
> 0 ? len
: 0);
1087 WSLUA_METHOD
TreeItem_set_len(lua_State
*L
) {
1088 /* Set <<lua_class_TreeItem,`TreeItem`>>'s length inside tvb, after it has already been created.
1090 This used to return nothing, but as of 1.11.3 it returns the same tree item to allow chained calls.
1092 #define WSLUA_ARG_TreeItem_set_len_LEN 2 /* The length to be used. */
1093 TreeItem ti
= checkTreeItem(L
,1);
1094 int len
= (int)luaL_checkinteger(L
,WSLUA_ARG_TreeItem_set_len_LEN
);
1096 proto_item_set_len(ti
->item
, len
);
1098 /* copy the TreeItem userdata so we give it back */
1099 lua_pushvalue(L
, 1);
1101 WSLUA_RETURN(1); /* The same TreeItem. */
1104 WSLUA_METHOD
TreeItem_referenced(lua_State
*L
) {
1105 /* Checks if a <<lua_class_ProtoField,`ProtoField`>> or <<lua_class_Dissector,`Dissector`>> is referenced by a filter/tap/UI.
1107 If this function returns `false`, it means that the field (or dissector) does not need to be dissected
1108 and can be safely skipped. By skipping a field rather than dissecting it, the dissector will
1109 usually run faster since Wireshark will not do extra dissection work when it doesn't need the field.
1111 You can use this in conjunction with the TreeItem.visible attribute. This function will always return
1112 true when the TreeItem is visible. When it is not visible and the field is not referenced, you can
1113 speed up the dissection by not dissecting the field as it is not needed for display or filtering.
1115 This function takes one parameter that can be a <<lua_class_ProtoField,`ProtoField`>> or <<lua_class_Dissector,`Dissector`>>.
1116 The <<lua_class_Dissector,`Dissector`>> form is useful when you need to decide whether to call a sub-dissector.
1118 #define WSLUA_ARG_TreeItem_referenced_PROTOFIELD 2 /* The <<lua_class_ProtoField,`ProtoField`>> or <<lua_class_Dissector,`Dissector`>> to check if referenced. */
1119 TreeItem ti
= checkTreeItem(L
, 1);
1121 ProtoField f
= shiftProtoField(L
, WSLUA_ARG_TreeItem_referenced_PROTOFIELD
);
1123 lua_pushboolean(L
, proto_field_is_referenced(ti
->tree
, f
->hfid
));
1126 Dissector d
= checkDissector(L
, WSLUA_ARG_TreeItem_referenced_PROTOFIELD
);
1128 lua_pushboolean(L
, proto_field_is_referenced(ti
->tree
, dissector_handle_get_protocol_index(d
)));
1130 WSLUA_RETURN(1); /* A boolean indicating if the ProtoField/Dissector is referenced */
1133 WSLUA_METAMETHOD
TreeItem__tostring(lua_State
* L
) {
1134 /* Returns string debug information about the <<lua_class_TreeItem,`TreeItem`>>. */
1135 TreeItem ti
= toTreeItem(L
,1);
1139 "TreeItem: expired=%s, has item=%s, has subtree=%s, they are %sthe same",
1140 ti
->expired
? "true" : "false",
1141 ti
->item
? "true" : "false",
1142 ti
->tree
? "true" : "false",
1143 (ti
->tree
== ti
->item
) ? "" : "not ");
1146 lua_pushstring(L
, "No TreeItem object!");
1152 /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
1153 static int TreeItem__gc(lua_State
* L
) {
1154 TreeItem ti
= toTreeItem(L
,1);
1163 WSLUA_ATTRIBUTES TreeItem_attributes
[] = {
1164 WSLUA_ATTRIBUTE_RWREG(TreeItem
,generated
),
1165 WSLUA_ATTRIBUTE_RWREG(TreeItem
,hidden
),
1166 WSLUA_ATTRIBUTE_RWREG(TreeItem
,len
),
1167 WSLUA_ATTRIBUTE_RWREG(TreeItem
,text
),
1168 WSLUA_ATTRIBUTE_ROREG(TreeItem
,visible
),
1169 { NULL
, NULL
, NULL
}
1172 WSLUA_METHODS TreeItem_methods
[] = {
1173 WSLUA_CLASS_FNREG(TreeItem
,add_packet_field
),
1174 WSLUA_CLASS_FNREG(TreeItem
,add
),
1175 WSLUA_CLASS_FNREG(TreeItem
,add_le
),
1176 WSLUA_CLASS_FNREG(TreeItem
,set_text
),
1177 WSLUA_CLASS_FNREG(TreeItem
,append_text
),
1178 WSLUA_CLASS_FNREG(TreeItem
,prepend_text
),
1179 WSLUA_CLASS_FNREG(TreeItem
,add_expert_info
),
1180 WSLUA_CLASS_FNREG(TreeItem
,add_proto_expert_info
),
1181 WSLUA_CLASS_FNREG(TreeItem
,add_tvb_expert_info
),
1182 WSLUA_CLASS_FNREG(TreeItem
,set_generated
),
1183 WSLUA_CLASS_FNREG(TreeItem
,set_hidden
),
1184 WSLUA_CLASS_FNREG(TreeItem
,set_len
),
1185 WSLUA_CLASS_FNREG(TreeItem
,referenced
),
1189 WSLUA_META TreeItem_meta
[] = {
1190 WSLUA_CLASS_MTREG(TreeItem
,tostring
),
1194 int TreeItem_register(lua_State
*L
) {
1195 int* etts
[] = { &wslua_ett
};
1196 wslua_ett
= -1; /* Reset to support reload Lua plugins */
1197 WSLUA_REGISTER_CLASS_WITH_ATTRS(TreeItem
);
1198 if (outstanding_TreeItem
!= NULL
) {
1199 g_ptr_array_unref(outstanding_TreeItem
);
1201 outstanding_TreeItem
= g_ptr_array_new();
1202 proto_register_subtree_array(etts
,1);
1207 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1212 * indent-tabs-mode: nil
1215 * vi: set shiftwidth=4 tabstop=8 expandtab:
1216 * :indentSize=4:tabSize=8:noTabs=true: