regen pidl all: rm epan/dissectors/pidl/*-stamp; pushd epan/dissectors/pidl/ && make...
[wireshark-sm.git] / epan / wslua / wslua_dissector.c
blob6c9edc6f9959b78dbaebccd7ecfe490d4262ce0e
1 /*
2 * wslua_dissector.c
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>
9 * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com>
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
15 * SPDX-License-Identifier: GPL-2.0-or-later
18 #include "config.h"
20 #include <stdint.h>
21 #include "epan/guid-utils.h"
22 #include "epan/proto.h"
23 #include "wslua.h"
25 #include <epan/decode_as.h>
26 #include <epan/exceptions.h>
27 #include <epan/show_exception.h>
28 #include <epan/dissectors/packet-dcerpc.h>
29 #include <string.h>
32 /* WSLUA_CONTINUE_MODULE Proto */
35 WSLUA_CLASS_DEFINE(Dissector,NOP);
37 A refererence to a dissector, used to call a dissector against a packet or a part of it.
40 WSLUA_CONSTRUCTOR Dissector_get (lua_State *L) {
41 /* Obtains a dissector reference by name. */
42 #define WSLUA_ARG_Dissector_get_NAME 1 /* The name of the dissector. */
43 const char* name = luaL_checkstring(L,WSLUA_ARG_Dissector_get_NAME);
44 Dissector d;
46 if ((d = find_dissector(name))) {
47 pushDissector(L, d);
48 } else {
49 lua_pushnil(L);
52 WSLUA_RETURN(1); /* The <<lua_class_Dissector,`Dissector`>> reference if found, otherwise `nil`. */
55 /* Allow dissector key names to be sorted alphabetically. */
56 static int
57 compare_dissector_key_name(const void *dissector_a, const void *dissector_b)
59 return strcmp((const char*)dissector_a, (const char*)dissector_b);
62 WSLUA_CONSTRUCTOR Dissector_list (lua_State *L) {
63 /* Gets a Lua array table of all registered Dissector names.
65 Note: This is an expensive operation, and should only be used for troubleshooting.
67 GList* list = get_dissector_names();
68 GList* elist = NULL;
69 int i = 1;
71 if (!list) return luaL_error(L,"Cannot retrieve Dissector name list");
73 list = g_list_sort(list, (GCompareFunc)compare_dissector_key_name);
74 elist = g_list_first(list);
76 lua_newtable(L);
77 for (i=1; elist; i++, elist = g_list_next(elist)) {
78 lua_pushstring(L,(const char *) elist->data);
79 lua_rawseti(L,-2,i);
82 g_list_free(list);
83 WSLUA_RETURN(1); /* The array table of registered dissector names. */
86 WSLUA_METHOD Dissector_call(lua_State* L) {
87 /* Calls a dissector against a given packet (or part of it). */
88 #define WSLUA_ARG_Dissector_call_TVB 2 /* The buffer to dissect. */
89 #define WSLUA_ARG_Dissector_call_PINFO 3 /* The packet info. */
90 #define WSLUA_ARG_Dissector_call_TREE 4 /* The tree on which to add the protocol items. */
92 Dissector volatile d = checkDissector(L,1);
93 Tvb tvb = checkTvb(L,WSLUA_ARG_Dissector_call_TVB);
94 Pinfo pinfo = checkPinfo(L,WSLUA_ARG_Dissector_call_PINFO);
95 TreeItem ti = checkTreeItem(L,WSLUA_ARG_Dissector_call_TREE);
96 volatile int len = 0;
98 if (! ( d && tvb && pinfo) ) return 0;
100 WRAP_NON_LUA_EXCEPTIONS(
101 len = call_dissector(d, tvb->ws_tvb, pinfo->ws_pinfo, ti->tree);
104 lua_pushinteger(L,(lua_Integer)len);
105 WSLUA_RETURN(1); /* Number of bytes dissected. Note that some dissectors always return number of bytes in incoming buffer, so be aware. */
108 WSLUA_METAMETHOD Dissector__call(lua_State* L) {
109 /* Calls a dissector against a given packet (or part of it). */
110 #define WSLUA_ARG_Dissector__call_TVB 2 /* The buffer to dissect. */
111 #define WSLUA_ARG_Dissector__call_PINFO 3 /* The packet info. */
112 #define WSLUA_ARG_Dissector__call_TREE 4 /* The tree on which to add the protocol items. */
113 return Dissector_call(L);
116 WSLUA_METAMETHOD Dissector__tostring(lua_State* L) {
117 /* Gets the Dissector's description. */
118 Dissector d = checkDissector(L,1);
119 if (!d) return 0;
120 lua_pushstring(L,dissector_handle_get_description(d));
121 WSLUA_RETURN(1); /* A string of the Dissector's description. */
124 /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
125 static int Dissector__gc(lua_State* L _U_) {
126 /* do NOT free Dissector */
127 return 0;
130 WSLUA_METHODS Dissector_methods[] = {
131 WSLUA_CLASS_FNREG(Dissector,get),
132 WSLUA_CLASS_FNREG(Dissector,call),
133 WSLUA_CLASS_FNREG(Dissector,list),
134 { NULL, NULL }
137 WSLUA_META Dissector_meta[] = {
138 WSLUA_CLASS_MTREG(Dissector,tostring),
139 WSLUA_CLASS_MTREG(Dissector,call),
140 { NULL, NULL }
143 int Dissector_register(lua_State* L) {
144 WSLUA_REGISTER_CLASS(Dissector);
145 return 0;
148 WSLUA_CLASS_DEFINE(DissectorTable,NOP);
150 A table of subdissectors of a particular protocol (e.g. TCP subdissectors like http, smtp, sip are added to table "tcp.port").
152 Useful to add more dissectors to a table so that they appear in the “Decode As...” dialog.
155 static int dissectortable_table_ref = LUA_NOREF;
157 WSLUA_CONSTRUCTOR DissectorTable_new (lua_State *L) {
158 /* Creates a new `DissectorTable` for your dissector's use. */
159 #define WSLUA_ARG_DissectorTable_new_TABLENAME 1 /* The short name of the table. Use lower-case alphanumeric, dot, and/or underscores (e.g., "ansi_map.tele_id" or "udp.port"). */
160 #define WSLUA_OPTARG_DissectorTable_new_UINAME 2 /* The name of the table in the user interface.
161 Defaults to the name given in `tablename`, but can be any string. */
162 #define WSLUA_OPTARG_DissectorTable_new_TYPE 3 /* One of `ftypes.UINT8`, `ftypes.UINT16`,
163 `ftypes.UINT24`, `ftypes.UINT32`,
164 `ftypes.STRING`, `ftypes.NONE`,
165 or `ftypes.GUID`.
166 Defaults to `ftypes.UINT32`. */
167 #define WSLUA_OPTARG_DissectorTable_new_BASE 4 /* One of `base.NONE`, `base.DEC`, `base.HEX`,
168 `base.OCT`, `base.DEC_HEX` or `base.HEX_DEC`.
169 Defaults to `base.DEC`. */
170 #define WSLUA_OPTARG_DissectorTable_new_PROTO 5 /* The <<lua_class_Proto,`Proto`>> object that uses this dissector table. */
171 const char* name = (const char*)luaL_checkstring(L,WSLUA_ARG_DissectorTable_new_TABLENAME);
172 const char* ui_name = (const char*)luaL_optstring(L,WSLUA_OPTARG_DissectorTable_new_UINAME,name);
173 enum ftenum type = (enum ftenum)luaL_optinteger(L,WSLUA_OPTARG_DissectorTable_new_TYPE,FT_UINT32);
174 unsigned base = (unsigned)luaL_optinteger(L,WSLUA_OPTARG_DissectorTable_new_BASE,BASE_DEC);
175 DissectorTable dt;
176 int proto_id = -1;
178 switch(type) {
179 case FT_STRING:
180 base = BASE_NONE;
181 break;
183 case FT_NONE:
184 break;
186 case FT_UINT8:
187 case FT_UINT16:
188 case FT_UINT24:
189 case FT_UINT32:
190 break;
192 case FT_GUID:
193 base = BASE_HEX;
194 break;
196 default:
197 /* Calling WSLUA_OPTARG_ERROR raises a Lua error and
198 returns from this function. */
199 WSLUA_OPTARG_ERROR(
200 DissectorTable_new, TYPE,
201 "must be ftypes.UINT{8,16,24,32}, ftypes.STRING, ftypes.GUID or ftypes.NONE");
202 break;
205 dt = (DissectorTable)g_malloc(sizeof(struct _wslua_distbl_t));
207 if (isProto(L, WSLUA_OPTARG_DissectorTable_new_PROTO)) {
208 Proto proto = checkProto(L, WSLUA_OPTARG_DissectorTable_new_PROTO);
209 proto_id = proto_get_id_by_short_name(proto->name);
212 dt->table = (type == FT_NONE) ?
213 register_decode_as_next_proto(proto_id, name, ui_name, NULL) :
214 register_dissector_table(name, ui_name, proto_id, type, base);
215 dt->heur_list = NULL;
216 dt->name = g_strdup(name);
217 dt->ui_name = g_strdup(ui_name);
218 dt->created = true;
219 dt->expired = false;
221 lua_rawgeti(L, LUA_REGISTRYINDEX, dissectortable_table_ref);
222 lua_pushstring(L, name);
223 pushDissectorTable(L, dt);
224 lua_settable(L, -3);
226 pushDissectorTable(L, dt);
227 WSLUA_RETURN(1); /* The newly created DissectorTable. */
230 WSLUA_CONSTRUCTOR DissectorTable_heuristic_new(lua_State *L) {
231 /* Creates a new heuristic `DissectorTable` for your dissector's use. Returns true if table was created successfully.
232 * XXX - Currently it always returns nil.
234 @since 4.2.0
236 #define WSLUA_ARG_DissectorTable_heuristic_new_TABLENAME 1 /* The short name of the table. Use lower-case alphanumeric, dot, and/or underscores. */
237 #define WSLUA_OPTARG_DissectorTable_heuristic_new_UINAME 2 /* The name of the table in the user interface.
238 Defaults to the name given in `tablename`, but can be any string. */
239 #define WSLUA_ARG_DissectorTable_heuristic_new_PROTO 3 /* The <<lua_class_Proto,`Proto`>> object that uses this dissector table. */
240 const char* name = (const char*)luaL_checkstring(L,WSLUA_ARG_DissectorTable_heuristic_new_TABLENAME);
241 const char* ui_name = NULL;
242 Proto proto = NULL;
243 int proto_id = -1;
244 heur_dissector_list_t list;
245 int idx = WSLUA_OPTARG_DissectorTable_heuristic_new_UINAME;
247 if (lua_isstring(L, idx)) {
248 ui_name = luaL_checkstring(L, idx);
249 idx++;
252 proto = checkProto(L, idx);
253 proto_id = proto_get_id_by_short_name(proto->name);
255 list = find_heur_dissector_list(name);
256 if (list) {
257 luaL_error(L, "Heuristic list '%s' already exists", name);
258 return 0;
262 DissectorTable dt;
263 dt = (DissectorTable)g_malloc(sizeof(struct _wslua_distbl_t));
264 dt->table = NULL;
265 dt->heur_list = register_heur_dissector_list_with_description(name, ui_name, proto_id);
266 dt->name = g_strdup(name);
267 dt->ui_name = g_strdup(ui_name);
268 dt->created = true;
269 dt->expired = false;
271 lua_rawgeti(L, LUA_REGISTRYINDEX, dissectortable_table_ref);
272 lua_pushstring(L, name);
273 pushDissectorTable(L, dt);
274 lua_settable(L, -3);
276 #if 0
277 /* Return nil because this is not a regular DissectorTable that could
278 * be used with _try, _set, _add, etc., and so we need to build checks
279 * into the functions similar to File and CaptureInfo so that it
280 * doesn't get used as one. However, not returning it means that it
281 * doesn't get properly garbage collected. */
282 pushDissectorTable(L, dt);
283 WSLUA_RETURN(1); /* The newly created DissectorTable. */
284 #endif
285 return 0;
288 /* this struct is used for passing ourselves user_data through dissector_all_tables_foreach_table(). */
289 typedef struct dissector_tables_foreach_table_info {
290 int num;
291 lua_State *L;
292 } dissector_tables_foreach_table_info_t;
294 /* this is the DATFunc_table function used for dissector_all_tables_foreach_table()
295 so we can get all dissector_table names. This pushes the name into a table at stack index 1 */
296 static void
297 dissector_tables_list_func(const char *table_name, const char *ui_name _U_, void *user_data) {
298 dissector_tables_foreach_table_info_t *data = (dissector_tables_foreach_table_info_t*) user_data;
299 lua_pushstring(data->L, table_name);
300 lua_rawseti(data->L, 1, data->num);
301 data->num = data->num + 1;
304 WSLUA_CONSTRUCTOR DissectorTable_list (lua_State *L) {
305 /* Gets a Lua array table of all DissectorTable names - i.e., the string names you can
306 use for the first argument to DissectorTable.get().
308 Note: This is an expensive operation, and should only be used for troubleshooting.
310 dissector_tables_foreach_table_info_t data = { 1, L };
312 lua_newtable(L);
314 dissector_all_tables_foreach_table(dissector_tables_list_func, (void *)&data,
315 (GCompareFunc)compare_dissector_key_name);
317 WSLUA_RETURN(1); /* The array table of registered DissectorTable names. */
320 /* this is the DATFunc_heur_table function used for dissector_all_heur_tables_foreach_table()
321 so we can get all heuristic dissector list names. This pushes the name into a table at stack index 1 */
322 static void
323 heur_dissector_tables_list_func(const char *table_name, struct heur_dissector_list *table _U_, void *user_data) {
324 dissector_tables_foreach_table_info_t *data = (dissector_tables_foreach_table_info_t*) user_data;
325 lua_pushstring(data->L, table_name);
326 lua_rawseti(data->L, 1, data->num);
327 data->num = data->num + 1;
330 WSLUA_CONSTRUCTOR DissectorTable_heuristic_list (lua_State *L) {
331 /* Gets a Lua array table of all heuristic list names - i.e., the string names you can
332 use for the first argument in Proto:register_heuristic().
334 Note: This is an expensive operation, and should only be used for troubleshooting.
336 dissector_tables_foreach_table_info_t data = { 1, L };
338 lua_newtable(L);
340 dissector_all_heur_tables_foreach_table(heur_dissector_tables_list_func, (void *)&data, NULL);
342 WSLUA_RETURN(1); /* The array table of registered heuristic list names */
345 WSLUA_CONSTRUCTOR DissectorTable_try_heuristics (lua_State *L) {
347 Try all the dissectors in a given heuristic dissector table.
349 #define WSLUA_ARG_DissectorTable_try_heuristics_LISTNAME 1 /* The name of the heuristic dissector. */
350 #define WSLUA_ARG_DissectorTable_try_heuristics_TVB 2 /* The buffer to dissect. */
351 #define WSLUA_ARG_DissectorTable_try_heuristics_PINFO 3 /* The packet info. */
352 #define WSLUA_ARG_DissectorTable_try_heuristics_TREE 4 /* The tree on which to add the protocol items. */
354 const char* name = luaL_checkstring(L,WSLUA_ARG_DissectorTable_try_heuristics_LISTNAME);
355 Tvb tvb = checkTvb(L,WSLUA_ARG_DissectorTable_try_heuristics_TVB);
356 Pinfo pinfo = checkPinfo(L,WSLUA_ARG_DissectorTable_try_heuristics_PINFO);
357 TreeItem tree = checkTreeItem(L,WSLUA_ARG_DissectorTable_try_heuristics_TREE);
358 heur_dissector_list_t list;
359 heur_dtbl_entry_t *entry;
361 if (!(name && tvb && pinfo && tree)) return 0;
363 list = find_heur_dissector_list(name);
364 if (!list) {
365 luaL_error(L, "Heuristic list '%s' does not exist", name);
366 return 0;
369 lua_pushboolean(L, dissector_try_heuristic(list, tvb->ws_tvb, pinfo->ws_pinfo, tree->tree, &entry, NULL));
371 WSLUA_RETURN(1); /* True if the packet was recognized by the sub-dissector (stop dissection here). */
374 WSLUA_CONSTRUCTOR DissectorTable_get (lua_State *L) {
376 Obtain a reference to an existing dissector table.
378 #define WSLUA_ARG_DissectorTable_get_TABLENAME 1 /* The short name of the table. */
379 const char* name = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_TABLENAME);
380 dissector_table_t table = find_dissector_table(name);
382 if (table) {
383 DissectorTable dt = (DissectorTable)g_malloc(sizeof(struct _wslua_distbl_t));
384 dt->table = table;
385 dt->heur_list = NULL;
386 dt->name = g_strdup(name);
387 dt->ui_name = NULL;
388 dt->created = false;
389 dt->expired = false;
391 pushDissectorTable(L, dt);
392 } else {
393 lua_pushnil(L);
396 WSLUA_RETURN(1); /* The <<lua_class_DissectorTable,`DissectorTable`>> reference if found, otherwise `nil`. */
399 WSLUA_METHOD DissectorTable_add (lua_State *L) {
401 Add a <<lua_class_Proto,`Proto`>> with a dissector function or a <<lua_class_Dissector,`Dissector`>> object to the dissector table.
403 #define WSLUA_ARG_DissectorTable_add_PATTERN 2 /* The pattern to match (either an integer, a
404 integer range or a string depending on the table's type). */
405 #define WSLUA_ARG_DissectorTable_add_DISSECTOR 3 /* The dissector to add (either a <<lua_class_Proto,`Proto`>> or a <<lua_class_Dissector,`Dissector`>>). */
407 DissectorTable dt = checkDissectorTable(L,1);
408 ftenum_t type;
409 Dissector handle;
411 if (!dt) return 0;
413 if( isProto(L,WSLUA_ARG_DissectorTable_add_DISSECTOR) ) {
414 Proto p;
415 p = checkProto(L,WSLUA_ARG_DissectorTable_add_DISSECTOR);
416 handle = p->handle;
418 if (! handle) {
419 WSLUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"a Protocol that does not have a dissector cannot be added to a table");
420 return 0;
423 } else if ( isDissector(L,WSLUA_ARG_DissectorTable_add_DISSECTOR) ) {
424 handle = toDissector(L,WSLUA_ARG_DissectorTable_add_DISSECTOR);
425 } else {
426 WSLUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"must be either Proto or Dissector");
427 return 0;
430 type = get_dissector_table_selector_type(dt->name);
432 if (type == FT_STRING) {
433 char* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN));
434 dissector_add_string(dt->name, pattern,handle);
435 g_free (pattern);
436 } else if (type == FT_GUID) {
437 /* Handle GUID type (assuming it is represented as a string in Lua) */
438 const char* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN);
439 fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL);
440 const e_guid_t* guid = fvalue_get_guid(fval);
441 guid_key gk = {*guid, 0};
442 /* The dcerpc.uuid table requires its own initializer */
443 if(strcmp(DCERPC_TABLE_NAME, dt->name) == 0) {
444 e_guid_t uuid;
445 memcpy(&uuid, guid, sizeof(e_guid_t));
446 dcerpc_init_from_handle(dissector_handle_get_protocol_index(handle), &uuid, 0, handle);
447 } else {
448 dissector_add_guid(dt->name, &gk, handle);
449 guids_add_uuid(guid, dissector_handle_get_protocol_short_name(handle));
451 } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
452 /* Either an integer or a range.
453 * For number literals, Lua only accepts "." as the decimal separator,
454 * but when converting strings to numbers, Lua will accept "." or the
455 * locale native separator, and when converting numbers to strings will
456 * use the locale native separator. (On Lua 5.2 and earlier, *only*
457 * the locale native separator may be accepted.) The behavior can be
458 * changed when compiling Lua, but generally isn't (and on UN*X we use
459 * system packages for Lua.)
461 * Some locales use "," as the decimal separator. range_convert_str
462 * expects "," to separate integers in ranges.
464 * We can either call setlocale(LC_NUMERIC, ...) to save, set, and
465 * restore the locale here (not thread safe), or try to work around it.
467 switch(lua_type(L, WSLUA_ARG_DissectorTable_add_PATTERN)) {
468 case LUA_TNUMBER:
470 /* Try to convert to an integer. Note that on Lua 5.3 and higher
471 * this fails for numbers that can't be converted exactly, unlike
472 * on Lua 5.2 where it simply casts. This can be changed at Lua
473 * compile time, but on UN*X systems we use system Lua packages.
475 uint32_t port = wslua_checkuint32(L, WSLUA_ARG_DissectorTable_add_PATTERN);
476 dissector_add_uint(dt->name, port, handle);
477 break;
480 case LUA_TSTRING:
482 /* Convert all strings to ranges without trying number conversion,
483 * so that on locales that use decimal commas "10,11" is a range
484 * not the number 10.11.
485 * Using a range works fine for numbers that are single integers,
486 * but note range_convert_str will reject strings like "10.0",
487 * whereas Lua checkinteger will convert it.
489 const char* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN);
490 range_t *range = NULL;
491 if (range_convert_str(NULL, &range, pattern, UINT32_MAX) == CVT_NO_ERROR) {
492 dissector_add_uint_range(dt->name, range, handle);
493 } else {
494 wmem_free (NULL, range);
495 WSLUA_ARG_ERROR(DissectorTable_add,PATTERN,"invalid integer or range");
496 return 0;
498 wmem_free (NULL, range);
499 break;
502 #if 0
503 /* Just don't allow UInt64 types, but if 64-bit integer tables get
504 * supported (#20207) we'll need something like: */
505 case LUA_TUSERDATA:
506 checkUInt64(L, checkUInt64(L, 1);
508 break;
509 #endif
511 default:
512 WSLUA_ARG_ERROR(DissectorTable_add,PATTERN,"invalid integer or range");
513 return 0;
515 } else {
516 luaL_error(L,"Strange type %d for a DissectorTable",type);
519 return 0;
522 WSLUA_METHOD DissectorTable_set (lua_State *L) {
523 /* Clear all existing dissectors from a table and add a new dissector or a range of new dissectors. */
524 #define WSLUA_ARG_DissectorTable_set_PATTERN 2 /* The pattern to match (either an integer, a integer range or a string depending on the table's type). */
525 #define WSLUA_ARG_DissectorTable_set_DISSECTOR 3 /* The dissector to add (either a <<lua_class_Proto,`Proto`>> or a <<lua_class_Dissector,`Dissector`>>). */
527 DissectorTable dt = checkDissectorTable(L,1);
528 ftenum_t type;
529 Dissector handle;
531 if (!dt) return 0;
533 if( isProto(L,WSLUA_ARG_DissectorTable_set_DISSECTOR) ) {
534 Proto p;
535 p = checkProto(L,WSLUA_ARG_DissectorTable_set_DISSECTOR);
536 handle = p->handle;
538 if (! handle) {
539 WSLUA_ARG_ERROR(DissectorTable_set,DISSECTOR,"a Protocol that does not have a dissector cannot be set to a table");
540 return 0;
543 } else if ( isDissector(L,WSLUA_ARG_DissectorTable_set_DISSECTOR) ) {
544 handle = toDissector(L,WSLUA_ARG_DissectorTable_set_DISSECTOR);
545 } else {
546 WSLUA_ARG_ERROR(DissectorTable_set,DISSECTOR,"must be either Proto or Dissector");
547 return 0;
550 type = get_dissector_table_selector_type(dt->name);
552 if (type == FT_STRING) {
553 const char* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN);
554 dissector_delete_all(dt->name, handle);
555 dissector_add_string(dt->name, pattern,handle);
556 } else if (type == FT_GUID) {
557 /* Handle GUID type (assuming it is represented as a string in Lua) */
558 const char* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN);
559 fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL);
560 const e_guid_t* guid = fvalue_get_guid(fval);
561 guid_key gk = {*guid, 0};
562 /* The dcerpc.uuid table requires its own initializer */
563 if(strcmp(DCERPC_TABLE_NAME, dt->name) == 0) {
564 e_guid_t uuid;
565 memcpy(&uuid, guid, sizeof(e_guid_t));
566 dcerpc_init_from_handle(dissector_handle_get_protocol_index(handle), &uuid, 0, handle);
567 } else {
568 dissector_add_guid(dt->name, &gk, handle);
569 guids_add_uuid(guid, dissector_handle_get_protocol_short_name(handle));
571 } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
572 /* Either an integer or a range. See discussion above in _add. */
573 switch(lua_type(L, WSLUA_ARG_DissectorTable_set_PATTERN)) {
575 case LUA_TNUMBER:
577 uint32_t port = wslua_checkuint32(L, WSLUA_ARG_DissectorTable_set_PATTERN);
578 dissector_delete_all(dt->name, handle);
579 dissector_add_uint(dt->name, port, handle);
580 break;
583 case LUA_TSTRING:
585 /* Convert all strings to ranges */
586 const char* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN);
587 range_t *range = NULL;
588 if (range_convert_str(NULL, &range, pattern, UINT32_MAX) == CVT_NO_ERROR) {
589 dissector_delete_all(dt->name, handle);
590 dissector_add_uint_range(dt->name, range, handle);
591 } else {
592 wmem_free (NULL, range);
593 WSLUA_ARG_ERROR(DissectorTable_set,PATTERN,"invalid integer or range");
594 return 0;
596 wmem_free (NULL, range);
597 break;
600 default:
601 WSLUA_ARG_ERROR(DissectorTable_set,PATTERN,"invalid integer or range");
602 return 0;
604 } else {
605 luaL_error(L,"Strange type %d for a DissectorTable",type);
608 return 0;
611 WSLUA_METHOD DissectorTable_remove (lua_State *L) {
613 Remove a dissector or a range of dissectors from a table.
615 #define WSLUA_ARG_DissectorTable_remove_PATTERN 2 /* The pattern to match (either an integer, a integer range or a string depending on the table's type). */
616 #define WSLUA_ARG_DissectorTable_remove_DISSECTOR 3 /* The dissector to remove (either a <<lua_class_Proto,`Proto`>> or a <<lua_class_Dissector,`Dissector`>>). */
617 DissectorTable dt = checkDissectorTable(L,1);
618 ftenum_t type;
619 Dissector handle;
621 if (!dt) return 0;
623 if( isProto(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR) ) {
624 Proto p;
625 p = checkProto(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR);
626 handle = p->handle;
628 } else if ( isDissector(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR) ) {
629 handle = toDissector(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR);
630 } else {
631 WSLUA_ARG_ERROR(DissectorTable_remove,DISSECTOR,"must be either Proto or Dissector");
632 return 0;
635 type = get_dissector_table_selector_type(dt->name);
637 if (type == FT_STRING) {
638 char* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN));
639 dissector_delete_string(dt->name, pattern,handle);
640 g_free (pattern);
641 } else if (type == FT_GUID) {
642 // Handle GUID type (assuming it is represented as a string in Lua)
643 const char* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN);
644 fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL);
645 const e_guid_t* guid = fvalue_get_guid(fval);
646 guid_key gk = {*guid, 0};
647 guids_delete_guid(guid);
648 dissector_delete_guid(dt->name, &gk, handle);
649 } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
650 /* Either an integer or a range. See discussion above in _add. */
651 switch(lua_type(L, WSLUA_ARG_DissectorTable_set_PATTERN)) {
653 case LUA_TNUMBER:
655 uint32_t port = wslua_checkuint32(L, WSLUA_ARG_DissectorTable_set_PATTERN);
656 dissector_delete_uint(dt->name, port, handle);
657 break;
660 case LUA_TSTRING:
662 /* Convert all strings to ranges */
663 const char* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN);
664 range_t *range = NULL;
665 if (range_convert_str(NULL, &range, pattern, UINT32_MAX) == CVT_NO_ERROR) {
666 dissector_delete_uint_range(dt->name, range, handle);
667 } else {
668 wmem_free (NULL, range);
669 WSLUA_ARG_ERROR(DissectorTable_remove,PATTERN,"invalid integer or range");
670 return 0;
672 wmem_free (NULL, range);
673 break;
676 default:
677 WSLUA_ARG_ERROR(DissectorTable_remove,PATTERN,"invalid integer or range");
678 return 0;
682 return 0;
685 WSLUA_METHOD DissectorTable_remove_all (lua_State *L) {
686 /* Remove all dissectors from a table. */
687 #define WSLUA_ARG_DissectorTable_remove_all_DISSECTOR 2 /* The dissector to remove (either a <<lua_class_Proto,`Proto`>> or a <<lua_class_Dissector,`Dissector`>>). */
688 DissectorTable dt = checkDissectorTable(L,1);
689 Dissector handle;
691 if (!dt) return 0;
693 if( isProto(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR) ) {
694 Proto p;
695 p = checkProto(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR);
696 handle = p->handle;
698 } else if ( isDissector(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR) ) {
699 handle = toDissector(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR);
700 } else {
701 WSLUA_ARG_ERROR(DissectorTable_remove_all,DISSECTOR,"must be either Proto or Dissector");
702 return 0;
705 dissector_delete_all (dt->name, handle);
707 return 0;
710 WSLUA_METHOD DissectorTable_try (lua_State *L) {
712 Try to call a dissector from a table.
714 #define WSLUA_ARG_DissectorTable_try_PATTERN 2 /* The pattern to be matched (either an integer or a string depending on the table's type). */
715 #define WSLUA_ARG_DissectorTable_try_TVB 3 /* The <<lua_class_Tvb,`Tvb`>> to dissect. */
716 #define WSLUA_ARG_DissectorTable_try_PINFO 4 /* The packet's <<lua_class_Pinfo,`Pinfo`>>. */
717 #define WSLUA_ARG_DissectorTable_try_TREE 5 /* The <<lua_class_TreeItem,`TreeItem`>> on which to add the protocol items. */
718 DissectorTable volatile dt = checkDissectorTable(L,1);
719 Tvb tvb = checkTvb(L,WSLUA_ARG_DissectorTable_try_TVB);
720 Pinfo pinfo = checkPinfo(L,WSLUA_ARG_DissectorTable_try_PINFO);
721 TreeItem ti = checkTreeItem(L,WSLUA_ARG_DissectorTable_try_TREE);
722 ftenum_t type;
723 bool handled = false;
724 const char *volatile error = NULL;
725 int len = 0;
727 if (! (dt && tvb && tvb->ws_tvb && pinfo && ti) ) return 0;
729 type = get_dissector_table_selector_type(dt->name);
731 TRY {
733 if (type == FT_STRING) {
734 const char* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_try_PATTERN);
736 len = dissector_try_string_with_data(dt->table,pattern,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree, true, NULL);
737 if (len > 0) {
738 handled = true;
740 } else if ( type == FT_GUID ) {
741 const char* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_try_PATTERN);
742 fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL);
743 const e_guid_t* guid = fvalue_get_guid(fval);
744 guid_key gk = {*guid, 0};
746 len = dissector_try_guid_with_data(dt->table, &gk,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree, true, NULL);
747 if (len > 0) {
748 handled = true;
750 } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
751 uint32_t port = wslua_checkuint32(L, WSLUA_ARG_DissectorTable_try_PATTERN);
753 len = dissector_try_uint(dt->table,port,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree);
754 if (len > 0) {
755 handled = true;
757 } else if ( type == FT_NONE ) {
758 len = dissector_try_payload_with_data(dt->table,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree, true, NULL);
759 if (len > 0) {
760 handled = true;
762 } else {
763 error = "No such type of dissector table";
766 if (!handled) {
767 len = call_data_dissector(tvb->ws_tvb, pinfo->ws_pinfo, ti->tree);
769 /* XXX Are we sure about this??? is this the right/only thing to catch */
770 } CATCH_NONFATAL_ERRORS {
771 show_exception(tvb->ws_tvb, pinfo->ws_pinfo, ti->tree, EXCEPT_CODE, GET_MESSAGE);
772 error = "Malformed frame";
773 } ENDTRY;
775 if (error) { WSLUA_ERROR(DissectorTable_try,error); }
777 lua_pushinteger(L,(lua_Integer)len);
778 WSLUA_RETURN(1); /* Number of bytes dissected. Note that some dissectors always return number of bytes in incoming buffer, so be aware. */
781 WSLUA_METHOD DissectorTable_get_dissector (lua_State *L) {
783 Try to obtain a dissector from a table.
785 #define WSLUA_ARG_DissectorTable_get_dissector_PATTERN 2 /* The pattern to be matched (either an integer or a string depending on the table's type). */
787 DissectorTable dt = checkDissectorTable(L,1);
788 ftenum_t type;
789 dissector_handle_t handle = NULL;
791 if (!dt) return 0;
793 type = get_dissector_table_selector_type(dt->name);
795 if (type == FT_STRING) {
796 const char* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_dissector_PATTERN);
797 handle = dissector_get_string_handle(dt->table,pattern);
798 } else if ( type == FT_GUID ) {
799 const char* guid_str = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_dissector_PATTERN);
800 fvalue_t* fval = fvalue_from_literal(type, guid_str, 0, NULL);
801 const e_guid_t* guid = fvalue_get_guid(fval);
802 guid_key gk = {*guid, 0};
803 handle = dissector_get_guid_handle(dt->table,&gk);
804 } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
805 uint32_t port = wslua_checkuint32(L, WSLUA_ARG_DissectorTable_get_dissector_PATTERN);
806 handle = dissector_get_uint_handle(dt->table,port);
809 if (handle) {
810 pushDissector(L,handle);
811 } else {
812 lua_pushnil(L);
815 WSLUA_RETURN(1); /* The <<lua_class_Dissector,`Dissector`>> handle if found, otherwise `nil` */
818 WSLUA_METHOD DissectorTable_add_for_decode_as (lua_State *L) {
820 Add the given <<lua_class_Proto,`Proto`>> to the “Decode as...” list for this DissectorTable.
821 The passed-in <<lua_class_Proto,`Proto`>> object's `dissector()` function is used for dissecting.
823 #define WSLUA_ARG_DissectorTable_add_for_decode_as_PROTO 2 /* The <<lua_class_Proto,`Proto`>> to add. */
824 DissectorTable dt = checkDissectorTable(L,1);
825 Proto proto = checkProto(L, WSLUA_ARG_DissectorTable_add_for_decode_as_PROTO);
826 dissector_handle_t handle = NULL;
828 if (! proto->handle) {
829 proto->handle = register_dissector(proto->loname, dissect_lua, proto->hfid);
832 handle = proto->handle;
834 dissector_add_for_decode_as(dt->name, handle);
836 return 0;
839 /* XXX It would be nice to iterate and print which dissectors it has */
840 WSLUA_METAMETHOD DissectorTable__tostring(lua_State* L) {
841 /* Gets some debug information about the <<lua_class_DissectorTable,`DissectorTable`>>. */
842 DissectorTable dt = checkDissectorTable(L,1);
843 GString* s;
844 ftenum_t type;
846 if (!dt) return 0;
848 type = get_dissector_table_selector_type(dt->name);
849 s = g_string_new("DissectorTable ");
851 switch(type) {
852 case FT_STRING:
854 g_string_append_printf(s,"%s String:\n",dt->name);
855 break;
857 case FT_UINT8:
858 case FT_UINT16:
859 case FT_UINT24:
860 case FT_UINT32:
862 int base = get_dissector_table_param(dt->name);
863 g_string_append_printf(s,"%s Integer(%i):\n",dt->name,base);
864 break;
866 case FT_GUID:
868 g_string_append_printf(s,"%s GUID:\n",dt->name);
869 break;
871 case FT_NONE:
873 g_string_append_printf(s,"%s only for Decode As:\n",dt->name);
874 break;
876 default:
877 luaL_error(L,"Strange table type");
880 lua_pushstring(L,s->str);
881 g_string_free(s,TRUE);
882 WSLUA_RETURN(1); /* A string of debug information about the <<lua_class_DissectorTable,`DissectorTable`>>. */
885 /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
886 static int DissectorTable__gc(lua_State* L) {
887 DissectorTable dt = toDissectorTable(L,1);
889 if (dt->created && !dt->expired) {
890 /* Created DissectorTable will pass GC two times */
891 dt->expired = true;
892 } else {
893 g_free((char *)dt->name);
894 g_free((char *)dt->ui_name);
895 g_free(dt);
898 return 0;
901 WSLUA_METHODS DissectorTable_methods[] = {
902 WSLUA_CLASS_FNREG(DissectorTable,new),
903 WSLUA_CLASS_FNREG(DissectorTable,heuristic_new),
904 WSLUA_CLASS_FNREG(DissectorTable,get),
905 WSLUA_CLASS_FNREG(DissectorTable,list),
906 WSLUA_CLASS_FNREG(DissectorTable,heuristic_list),
907 WSLUA_CLASS_FNREG(DissectorTable,try_heuristics),
908 WSLUA_CLASS_FNREG(DissectorTable,add),
909 WSLUA_CLASS_FNREG(DissectorTable,set),
910 WSLUA_CLASS_FNREG(DissectorTable,remove),
911 WSLUA_CLASS_FNREG(DissectorTable,remove_all),
912 WSLUA_CLASS_FNREG(DissectorTable,try),
913 WSLUA_CLASS_FNREG(DissectorTable,get_dissector),
914 WSLUA_CLASS_FNREG(DissectorTable,add_for_decode_as),
915 { NULL, NULL }
918 WSLUA_META DissectorTable_meta[] = {
919 WSLUA_CLASS_MTREG(DissectorTable,tostring),
920 { NULL, NULL }
923 int DissectorTable_register(lua_State* L) {
924 WSLUA_REGISTER_CLASS(DissectorTable);
926 lua_newtable (L);
927 dissectortable_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
929 return 0;
932 int wslua_deregister_dissector_tables(lua_State* L) {
933 /* for each registered DissectorTable do... */
934 lua_rawgeti(L, LUA_REGISTRYINDEX, dissectortable_table_ref);
935 for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
936 DissectorTable dt = checkDissectorTable(L, -1);
937 if (dt->created) {
938 if (dt->table) {
939 deregister_dissector_table(dt->name);
941 if (dt->heur_list) {
942 deregister_heur_dissector_list(dt->name);
947 lua_pop(L, 1); /* dissector_table_ref */
949 return 0;
954 * Editor modelines - https://www.wireshark.org/tools/modelines.html
956 * Local variables:
957 * c-basic-offset: 4
958 * tab-width: 8
959 * indent-tabs-mode: nil
960 * End:
962 * vi: set shiftwidth=4 tabstop=8 expandtab:
963 * :indentSize=4:tabSize=8:noTabs=true: