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>
8 * (c) 2011, Stig Bjorlykke <stig@bjorlykke.org>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * SPDX-License-Identifier: GPL-2.0-or-later
18 #include "wslua_pinfo_common.h"
20 #include <epan/wmem_scopes.h>
21 #include <epan/conversation.h>
25 /* WSLUA_MODULE Pinfo Obtaining Packet Information */
29 * Track pointers to wireshark's structures.
30 * see comment on wslua_tvb.c
33 static GPtrArray
* outstanding_Pinfo
;
34 static GPtrArray
* outstanding_PrivateTable
;
36 CLEAR_OUTSTANDING(Pinfo
,expired
, true)
37 CLEAR_OUTSTANDING(PrivateTable
,expired
, true)
39 Pinfo
* push_Pinfo(lua_State
* L
, packet_info
* ws_pinfo
) {
42 pinfo
= (Pinfo
)g_malloc(sizeof(struct _wslua_pinfo
));
43 pinfo
->ws_pinfo
= ws_pinfo
;
44 pinfo
->expired
= false;
45 g_ptr_array_add(outstanding_Pinfo
,pinfo
);
47 return pushPinfo(L
,pinfo
);
50 #define PUSH_PRIVATE_TABLE(L,c) {g_ptr_array_add(outstanding_PrivateTable,c);pushPrivateTable(L,c);}
53 WSLUA_CLASS_DEFINE(PrivateTable
,FAIL_ON_NULL_OR_EXPIRED("PrivateTable"));
54 /* PrivateTable represents the pinfo->private_table. */
56 WSLUA_METAMETHOD
PrivateTable__tostring(lua_State
* L
) {
57 /* Gets debugging type information about the private table. */
58 PrivateTable priv
= toPrivateTable(L
,1);
64 key_string
= g_string_new ("");
65 keys
= g_hash_table_get_keys (priv
->table
);
66 key
= g_list_first (keys
);
68 key_string
= g_string_append (key_string
, (const char *)key
->data
);
69 key
= g_list_next (key
);
71 key_string
= g_string_append_c (key_string
, ',');
75 lua_pushstring(L
,key_string
->str
);
77 g_string_free (key_string
, TRUE
);
80 WSLUA_RETURN(1); /* A string with all keys in the table, mostly for debugging. */
83 static int PrivateTable__index(lua_State
* L
) {
84 /* Gets the text of a specific entry. */
85 PrivateTable priv
= checkPrivateTable(L
,1);
86 const char* name
= luaL_checkstring(L
,2);
89 string
= (const char *)(g_hash_table_lookup (priv
->table
, name
));
92 lua_pushstring(L
, string
);
100 static int PrivateTable__newindex(lua_State
* L
) {
101 /* Sets the text of a specific entry. */
102 PrivateTable priv
= checkPrivateTable(L
,1);
103 const char* name
= luaL_checkstring(L
,2);
104 const char* string
= NULL
;
106 if (lua_isstring(L
,3)) {
107 /* This also catches numbers, which is converted to string */
108 string
= luaL_checkstring(L
,3);
109 } else if (lua_isboolean(L
,3)) {
110 /* We support boolean by setting a empty string if true and NULL if false */
111 string
= lua_toboolean(L
,3) ? "" : NULL
;
112 } else if (!lua_isnil(L
,3)) {
113 luaL_error(L
,"unsupported type: %s", lua_typename(L
,3));
118 g_hash_table_replace (priv
->table
, (void *) g_strdup(name
), (void *) g_strdup(string
));
120 g_hash_table_remove (priv
->table
, (const void *) name
);
126 /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
127 static int PrivateTable__gc(lua_State
* L
) {
128 PrivateTable priv
= toPrivateTable(L
,1);
132 if (!priv
->expired
) {
133 priv
->expired
= true;
135 if (priv
->is_allocated
) {
136 g_hash_table_destroy (priv
->table
);
144 WSLUA_META PrivateTable_meta
[] = {
145 WSLUA_CLASS_MTREG(PrivateTable
,index
),
146 WSLUA_CLASS_MTREG(PrivateTable
,newindex
),
147 WSLUA_CLASS_MTREG(PrivateTable
,tostring
),
151 int PrivateTable_register(lua_State
* L
) {
152 WSLUA_REGISTER_META(PrivateTable
);
157 WSLUA_CLASS_DEFINE(Pinfo
,FAIL_ON_NULL_OR_EXPIRED("Pinfo"));
158 /* Packet information. */
160 static int Pinfo__tostring(lua_State
*L
) { lua_pushstring(L
,"a Pinfo"); return 1; }
162 #define PINFO_ADDRESS_GETTER(name) \
163 WSLUA_ATTRIBUTE_GET(Pinfo,name, { \
164 Address addr = g_new(address,1); \
165 copy_address(addr, &(obj->ws_pinfo->name)); \
166 pushAddress(L,addr); \
170 * Addresses within the Pinfo structure are only valid for a single packet, so
171 * allocate memory from the pinfo pool.
173 #define PINFO_ADDRESS_SETTER(name) \
174 WSLUA_ATTRIBUTE_SET(Pinfo,name, { \
175 const address* from = checkAddress(L,-1); \
176 copy_address_wmem(obj->ws_pinfo->pool, &(obj->ws_pinfo->name), from); \
179 #define PINFO_NAMED_BOOLEAN_GETTER(name,member) \
180 WSLUA_ATTRIBUTE_NAMED_BOOLEAN_GETTER(Pinfo,name,ws_pinfo->member)
182 #define PINFO_NAMED_BOOLEAN_SETTER(name,member) \
183 WSLUA_ATTRIBUTE_NAMED_BOOLEAN_SETTER(Pinfo,name,ws_pinfo->member)
185 #define PINFO_INTEGER_GETTER(name) \
186 WSLUA_ATTRIBUTE_NAMED_INTEGER_GETTER(Pinfo,name,ws_pinfo->name)
188 #define PINFO_NAMED_INTEGER_GETTER(name,member) \
189 WSLUA_ATTRIBUTE_NAMED_INTEGER_GETTER(Pinfo,name,ws_pinfo->member)
191 #define PINFO_NUMBER_SETTER(name,cast) \
192 WSLUA_ATTRIBUTE_NAMED_INTEGER_SETTER(Pinfo,name,ws_pinfo->name,cast)
194 #define PINFO_NAMED_INTEGER_SETTER(name,member,cast) \
195 WSLUA_ATTRIBUTE_NAMED_INTEGER_SETTER(Pinfo,name,ws_pinfo->member,cast)
198 lua_nstime_to_sec(const nstime_t
*nstime
)
200 return (((double)nstime
->secs
) + (((double)nstime
->nsecs
) / 1000000000.0));
204 lua_delta_nstime_to_sec(const Pinfo pinfo
, const frame_data
*fd
, uint32_t prev_num
)
208 frame_delta_abs_time(pinfo
->ws_pinfo
->epan
, fd
, prev_num
, &del
);
209 return lua_nstime_to_sec(&del
);
213 /* WSLUA_ATTRIBUTE Pinfo_visited RO Whether this packet has been already visited. */
214 PINFO_NAMED_BOOLEAN_GETTER(visited
,fd
->visited
);
216 /* WSLUA_ATTRIBUTE Pinfo_number RO The number of this packet in the current file. */
217 PINFO_NAMED_INTEGER_GETTER(number
,num
);
219 /* WSLUA_ATTRIBUTE Pinfo_len RO The length of the frame. */
220 PINFO_NAMED_INTEGER_GETTER(len
,fd
->pkt_len
);
222 /* WSLUA_ATTRIBUTE Pinfo_caplen RO The captured length of the frame. */
223 PINFO_NAMED_INTEGER_GETTER(caplen
,fd
->cap_len
);
225 /* WSLUA_ATTRIBUTE Pinfo_abs_ts RO When the packet was captured. */
226 WSLUA_ATTRIBUTE_BLOCK_NUMBER_GETTER(Pinfo
,abs_ts
,lua_nstime_to_sec(&obj
->ws_pinfo
->abs_ts
));
228 /* WSLUA_ATTRIBUTE Pinfo_rel_ts RO Number of seconds passed since beginning of capture. */
229 WSLUA_ATTRIBUTE_BLOCK_NUMBER_GETTER(Pinfo
,rel_ts
,lua_nstime_to_sec(&obj
->ws_pinfo
->rel_ts
));
231 /* WSLUA_ATTRIBUTE Pinfo_delta_ts RO Number of seconds passed since the last captured packet. */
232 WSLUA_ATTRIBUTE_BLOCK_NUMBER_GETTER(Pinfo
,delta_ts
,lua_delta_nstime_to_sec(obj
, obj
->ws_pinfo
->fd
, obj
->ws_pinfo
->num
- 1));
234 /* WSLUA_ATTRIBUTE Pinfo_delta_dis_ts RO Number of seconds passed since the last displayed packet. */
235 WSLUA_ATTRIBUTE_BLOCK_NUMBER_GETTER(Pinfo
,delta_dis_ts
,lua_delta_nstime_to_sec(obj
, obj
->ws_pinfo
->fd
, obj
->ws_pinfo
->fd
->prev_dis_num
));
237 /* WSLUA_ATTRIBUTE Pinfo_curr_proto RO Which Protocol are we dissecting. */
238 WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(Pinfo
,curr_proto
,ws_pinfo
->current_proto
);
240 /* WSLUA_ATTRIBUTE Pinfo_can_desegment RW Set if this segment could be desegmented. */
241 PINFO_INTEGER_GETTER(can_desegment
);
242 PINFO_NUMBER_SETTER(can_desegment
,uint16_t);
244 /* WSLUA_ATTRIBUTE Pinfo_saved_can_desegment RO Value of can_desegment before the current dissector was called.
245 Supplied so that proxy protocols like SOCKS can restore it to whatever the previous dissector (e.g. TCP) set it,
246 so that the dissectors they call are desegmented via the previous dissector.
248 PINFO_INTEGER_GETTER(saved_can_desegment
);
250 /* WSLUA_ATTRIBUTE Pinfo_desegment_len RW Estimated number of additional bytes required for completing the PDU. */
251 PINFO_INTEGER_GETTER(desegment_len
);
252 PINFO_NUMBER_SETTER(desegment_len
,uint32_t);
254 /* WSLUA_ATTRIBUTE Pinfo_desegment_offset RW Offset in the tvbuff at which the dissector will continue processing when next called. */
255 PINFO_INTEGER_GETTER(desegment_offset
);
256 PINFO_NUMBER_SETTER(desegment_offset
,int);
258 /* WSLUA_ATTRIBUTE Pinfo_fragmented RO If the protocol is only a fragment. */
259 PINFO_NAMED_BOOLEAN_GETTER(fragmented
,fragmented
);
261 /* WSLUA_ATTRIBUTE Pinfo_in_error_pkt RW If we're inside an error packet. */
262 PINFO_NAMED_BOOLEAN_GETTER(in_error_pkt
,flags
.in_error_pkt
);
263 PINFO_NAMED_BOOLEAN_SETTER(in_error_pkt
,flags
.in_error_pkt
);
265 /* WSLUA_ATTRIBUTE Pinfo_match_uint RO Matched uint for calling subdissector from table. */
266 PINFO_INTEGER_GETTER(match_uint
);
268 /* WSLUA_ATTRIBUTE Pinfo_match_string RO Matched string for calling subdissector from table. */
269 WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(Pinfo
,match_string
,ws_pinfo
->match_string
);
271 /* WSLUA_ATTRIBUTE Pinfo_port_type RW Type of Port of .src_port and .dst_port. */
272 PINFO_NAMED_INTEGER_GETTER(port_type
,ptype
);
273 PINFO_NAMED_INTEGER_SETTER(port_type
,ptype
,uint8_t);
275 /* WSLUA_ATTRIBUTE Pinfo_src_port RW Source Port of this Packet. */
276 PINFO_NAMED_INTEGER_GETTER(src_port
,srcport
);
277 PINFO_NAMED_INTEGER_SETTER(src_port
,srcport
,uint32_t);
279 /* WSLUA_ATTRIBUTE Pinfo_dst_port RW Destination Port of this Packet. */
280 PINFO_NAMED_INTEGER_GETTER(dst_port
,destport
);
281 PINFO_NAMED_INTEGER_SETTER(dst_port
,destport
,uint32_t);
283 /* WSLUA_ATTRIBUTE Pinfo_dl_src RW Data Link Source Address of this Packet. */
284 PINFO_ADDRESS_GETTER(dl_src
);
285 PINFO_ADDRESS_SETTER(dl_src
);
287 /* WSLUA_ATTRIBUTE Pinfo_dl_dst RW Data Link Destination Address of this Packet. */
288 PINFO_ADDRESS_GETTER(dl_dst
);
289 PINFO_ADDRESS_SETTER(dl_dst
);
291 /* WSLUA_ATTRIBUTE Pinfo_net_src RW Network Layer Source Address of this Packet. */
292 PINFO_ADDRESS_GETTER(net_src
);
293 PINFO_ADDRESS_SETTER(net_src
);
295 /* WSLUA_ATTRIBUTE Pinfo_net_dst RW Network Layer Destination Address of this Packet. */
296 PINFO_ADDRESS_GETTER(net_dst
);
297 PINFO_ADDRESS_SETTER(net_dst
);
299 /* WSLUA_ATTRIBUTE Pinfo_src RW Source Address of this Packet. */
300 PINFO_ADDRESS_GETTER(src
);
301 PINFO_ADDRESS_SETTER(src
);
303 /* WSLUA_ATTRIBUTE Pinfo_dst RW Destination Address of this Packet. */
304 PINFO_ADDRESS_GETTER(dst
);
305 PINFO_ADDRESS_SETTER(dst
);
307 /* WSLUA_ATTRIBUTE Pinfo_p2p_dir RW Direction of this Packet. (incoming / outgoing) */
308 PINFO_INTEGER_GETTER(p2p_dir
);
309 PINFO_NUMBER_SETTER(p2p_dir
,int);
311 /* WSLUA_ATTRIBUTE Pinfo_match RO Port/Data we are matching. */
312 static int Pinfo_get_match(lua_State
*L
) {
313 Pinfo pinfo
= checkPinfo(L
,1);
315 if (pinfo
->ws_pinfo
->match_string
) {
316 lua_pushstring(L
,pinfo
->ws_pinfo
->match_string
);
318 lua_pushinteger(L
,(lua_Integer
)(pinfo
->ws_pinfo
->match_uint
));
324 /* WSLUA_ATTRIBUTE Pinfo_columns RO Access to the packet list columns. */
325 /* WSLUA_ATTRIBUTE Pinfo_cols RO Access to the packet list columns (equivalent to pinfo.columns). */
326 static int Pinfo_get_columns(lua_State
*L
) {
328 Pinfo pinfo
= checkPinfo(L
,1);
329 const char* colname
= luaL_optstring(L
,2,NULL
);
331 cols
= (Columns
)g_malloc(sizeof(struct _wslua_cols
));
332 cols
->cinfo
= pinfo
->ws_pinfo
->cinfo
;
333 cols
->expired
= false;
336 Push_Columns(L
,cols
);
339 Push_Columns(L
,cols
);
340 lua_pushstring(L
,colname
);
341 return get_Columns_index(L
);
346 /* WSLUA_ATTRIBUTE Pinfo_private RO Access to the private table entries. */
347 static int Pinfo_get_private(lua_State
*L
) {
348 PrivateTable priv
= NULL
;
349 Pinfo pinfo
= checkPinfo(L
,1);
350 const char* privname
= luaL_optstring(L
,2,NULL
);
351 bool is_allocated
= false;
353 if (!pinfo
->ws_pinfo
->private_table
) {
354 pinfo
->ws_pinfo
->private_table
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
, g_free
);
358 priv
= (PrivateTable
)g_malloc(sizeof(struct _wslua_private_table
));
359 priv
->table
= pinfo
->ws_pinfo
->private_table
;
360 priv
->is_allocated
= is_allocated
;
361 priv
->expired
= false;
364 PUSH_PRIVATE_TABLE(L
,priv
);
367 PUSH_PRIVATE_TABLE(L
,priv
);
368 lua_pushstring(L
,privname
);
369 return PrivateTable__index(L
);
374 /* WSLUA_ATTRIBUTE Pinfo_hi RW Higher Address of this Packet. */
375 static int Pinfo_get_hi(lua_State
*L
) {
376 Pinfo pinfo
= checkPinfo(L
,1);
379 addr
= (Address
)g_malloc(sizeof(address
));
380 if (cmp_address(&(pinfo
->ws_pinfo
->src
), &(pinfo
->ws_pinfo
->dst
) ) >= 0) {
381 copy_address(addr
, &(pinfo
->ws_pinfo
->src
));
383 copy_address(addr
, &(pinfo
->ws_pinfo
->dst
));
390 /* WSLUA_ATTRIBUTE Pinfo_lo RO Lower Address of this Packet. */
391 static int Pinfo_get_lo(lua_State
*L
) {
392 Pinfo pinfo
= checkPinfo(L
,1);
395 addr
= (Address
)g_malloc(sizeof(address
));
396 if (cmp_address(&(pinfo
->ws_pinfo
->src
), &(pinfo
->ws_pinfo
->dst
) ) < 0) {
397 copy_address(addr
, &(pinfo
->ws_pinfo
->src
));
399 copy_address(addr
, &(pinfo
->ws_pinfo
->dst
));
406 /* WSLUA_ATTRIBUTE Pinfo_conversation WO Sets the packet conversation to the given Proto object. */
407 static int Pinfo_set_conversation(lua_State
*L
) {
408 Pinfo pinfo
= checkPinfo(L
,1);
409 Proto proto
= checkProto(L
,2);
410 conversation_t
*conversation
;
412 if (!proto
->handle
) {
413 luaL_error(L
,"Proto %s has no registered dissector", proto
->name
? proto
->name
:"<UNKNOWN>");
417 conversation
= find_or_create_conversation(pinfo
->ws_pinfo
);
418 conversation_set_dissector(conversation
,proto
->handle
);
423 /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
424 static int Pinfo__gc(lua_State
* L
) {
425 Pinfo pinfo
= toPinfo(L
,1);
427 if (!pinfo
) return 0;
430 pinfo
->expired
= true;
438 /* This table is ultimately registered as a sub-table of the class' metatable,
439 * and if __index/__newindex is invoked then it calls the appropriate function
440 * from this table for getting/setting the members.
442 WSLUA_ATTRIBUTES Pinfo_attributes
[] = {
443 WSLUA_ATTRIBUTE_ROREG(Pinfo
,number
),
444 WSLUA_ATTRIBUTE_ROREG(Pinfo
,len
),
445 WSLUA_ATTRIBUTE_ROREG(Pinfo
,caplen
),
446 WSLUA_ATTRIBUTE_ROREG(Pinfo
,abs_ts
),
447 WSLUA_ATTRIBUTE_ROREG(Pinfo
,rel_ts
),
448 WSLUA_ATTRIBUTE_ROREG(Pinfo
,delta_ts
),
449 WSLUA_ATTRIBUTE_ROREG(Pinfo
,delta_dis_ts
),
450 WSLUA_ATTRIBUTE_ROREG(Pinfo
,visited
),
451 WSLUA_ATTRIBUTE_RWREG(Pinfo
,src
),
452 WSLUA_ATTRIBUTE_RWREG(Pinfo
,dst
),
453 WSLUA_ATTRIBUTE_ROREG(Pinfo
,lo
),
454 WSLUA_ATTRIBUTE_ROREG(Pinfo
,hi
),
455 WSLUA_ATTRIBUTE_RWREG(Pinfo
,dl_src
),
456 WSLUA_ATTRIBUTE_RWREG(Pinfo
,dl_dst
),
457 WSLUA_ATTRIBUTE_RWREG(Pinfo
,net_src
),
458 WSLUA_ATTRIBUTE_RWREG(Pinfo
,net_dst
),
459 WSLUA_ATTRIBUTE_RWREG(Pinfo
,port_type
),
460 WSLUA_ATTRIBUTE_RWREG(Pinfo
,src_port
),
461 WSLUA_ATTRIBUTE_RWREG(Pinfo
,dst_port
),
462 WSLUA_ATTRIBUTE_ROREG(Pinfo
,match
),
463 WSLUA_ATTRIBUTE_ROREG(Pinfo
,curr_proto
),
464 WSLUA_ATTRIBUTE_ROREG(Pinfo
,columns
),
465 { "cols", Pinfo_get_columns
, NULL
},
466 WSLUA_ATTRIBUTE_RWREG(Pinfo
,can_desegment
),
467 WSLUA_ATTRIBUTE_ROREG(Pinfo
,saved_can_desegment
),
468 WSLUA_ATTRIBUTE_RWREG(Pinfo
,desegment_len
),
469 WSLUA_ATTRIBUTE_RWREG(Pinfo
,desegment_offset
),
470 WSLUA_ATTRIBUTE_ROREG(Pinfo
,private),
471 WSLUA_ATTRIBUTE_ROREG(Pinfo
,fragmented
),
472 WSLUA_ATTRIBUTE_RWREG(Pinfo
,in_error_pkt
),
473 WSLUA_ATTRIBUTE_ROREG(Pinfo
,match_uint
),
474 WSLUA_ATTRIBUTE_ROREG(Pinfo
,match_string
),
475 WSLUA_ATTRIBUTE_WOREG(Pinfo
,conversation
),
476 WSLUA_ATTRIBUTE_RWREG(Pinfo
,p2p_dir
),
480 WSLUA_META Pinfo_meta
[] = {
481 WSLUA_CLASS_MTREG(Pinfo
,tostring
),
485 int Pinfo_register(lua_State
* L
) {
486 WSLUA_REGISTER_META_WITH_ATTRS(Pinfo
);
487 if (outstanding_Pinfo
!= NULL
) {
488 g_ptr_array_unref(outstanding_Pinfo
);
490 outstanding_Pinfo
= g_ptr_array_new();
491 if (outstanding_PrivateTable
!= NULL
) {
492 g_ptr_array_unref(outstanding_PrivateTable
);
494 outstanding_PrivateTable
= g_ptr_array_new();
499 * Editor modelines - https://www.wireshark.org/tools/modelines.html
504 * indent-tabs-mode: nil
507 * vi: set shiftwidth=4 tabstop=8 expandtab:
508 * :indentSize=4:tabSize=8:noTabs=true: