/* * lua_proto.c * * wireshark's interface to the Lua Programming Language * * (c) 2006, Luis E. Garcia Ontanon * (c) 2007, Tamas Regos * * $Id$ * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include /* WSLUA_MODULE Proto Functions for writing dissectors */ #include "wslua.h" #include #include WSLUA_CLASS_DEFINE(Pref,NOP,NOP); /* A preference of a Protocol. */ static range_t* get_range(lua_State *L, int idx_r, int idx_m); static enum_val_t* get_enum(lua_State *L, int idx) { double seq; const gchar *str1, *str2; enum_val_t *ret, last = {NULL, NULL, -1}; GArray* es = g_array_new(TRUE,TRUE,sizeof(enum_val_t)); luaL_checktype(L, idx, LUA_TTABLE); lua_pushnil(L); /* first key */ while (lua_next(L, idx)) { enum_val_t e = {NULL, NULL, -1}; luaL_checktype(L, -1, LUA_TTABLE); lua_pushnil(L); lua_next(L, -2); if (! lua_isstring(L,-1)) { luaL_argerror(L,idx,"First value of an enum table must be string"); g_array_free(es,TRUE); return NULL; } str1 = lua_tostring(L, -1); lua_pop(L, 1); lua_next(L, -2); if (! lua_isstring(L,-1)) { luaL_argerror(L,idx,"Second value of an enum table must be string"); g_array_free(es,TRUE); return NULL; } str2 = lua_tostring(L, -1); lua_pop(L, 1); lua_next(L, -2); if (! lua_isnumber(L,-1)) { luaL_argerror(L,idx,"Third value of an enum table must be an integer"); g_array_free(es,TRUE); return NULL; } seq = lua_tonumber(L, -1); e.name = g_strdup(str1); e.description = g_strdup(str2); e.value = (guint32)seq; g_array_append_val(es,e); lua_pop(L, 3); /* removes 'value'; keeps 'key' for next iteration */ } g_array_append_val(es,last); ret = (enum_val_t*)es->data; g_array_free(es,FALSE); return ret; } static int new_pref(lua_State* L, pref_type_t type) { const gchar* label = luaL_optstring(L,1,NULL); const gchar* descr = luaL_optstring(L,3,""); Pref pref = (wslua_pref_t *)g_malloc(sizeof(wslua_pref_t)); pref->name = NULL; pref->label = label ? g_strdup(label) : NULL; pref->desc = g_strdup(descr); pref->type = type; pref->next = NULL; pref->proto = NULL; switch(type) { case PREF_BOOL: { gboolean def = lua_toboolean(L,2); pref->value.b = def; break; } case PREF_UINT: { guint32 def = (guint32)luaL_optnumber(L,2,0); pref->value.u = def; break; } case PREF_STRING: { gchar* def = g_strdup(luaL_optstring(L,2,"")); pref->value.s = def; break; } case PREF_ENUM: { guint32 def = (guint32)luaL_optnumber(L,2,0); enum_val_t *enum_val = get_enum(L,4); gboolean radio = lua_toboolean(L,5); pref->value.e = def; pref->info.enum_info.enumvals = enum_val; pref->info.enum_info.radio_buttons = radio; break; } case PREF_RANGE: { range_t *range = get_range(L,2,4); guint32 max = (guint32)luaL_optnumber(L,4,0); pref->value.r = range; pref->info.max_value = max; break; } case PREF_STATIC_TEXT: { /* This is just a static text. */ break; } default: g_assert_not_reached(); break; } pushPref(L,pref); return 1; } WSLUA_CONSTRUCTOR Pref_bool(lua_State* L) { /* Creates a boolean preference to be added to a Protocol's prefs table. */ #define WSLUA_ARG_Pref_bool_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */ #define WSLUA_ARG_Pref_bool_DEFAULT 2 /* The default value for this preference */ #define WSLUA_ARG_Pref_bool_DESCR 3 /* A description of what this preference is */ return new_pref(L,PREF_BOOL); } WSLUA_CONSTRUCTOR Pref_uint(lua_State* L) { /* Creates an (unsigned) integer preference to be added to a Protocol's prefs table. */ #define WSLUA_ARG_Pref_uint_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */ #define WSLUA_ARG_Pref_uint_DEFAULT 2 /* The default value for this preference */ #define WSLUA_ARG_Pref_uint_DESCR 3 /* A description of what this preference is */ return new_pref(L,PREF_UINT); } WSLUA_CONSTRUCTOR Pref_string(lua_State* L) { /* Creates a string preference to be added to a Protocol's prefs table. */ #define WSLUA_ARG_Pref_string_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */ #define WSLUA_ARG_Pref_string_DEFAULT 2 /* The default value for this preference */ #define WSLUA_ARG_Pref_string_DESCR 3 /* A description of what this preference is */ return new_pref(L,PREF_STRING); } WSLUA_CONSTRUCTOR Pref_enum(lua_State* L) { /* Creates an enum preference to be added to a Protocol's prefs table. */ #define WSLUA_ARG_Pref_enum_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */ #define WSLUA_ARG_Pref_enum_DEFAULT 2 /* The default value for this preference */ #define WSLUA_ARG_Pref_enum_DESCR 3 /* A description of what this preference is */ #define WSLUA_ARG_Pref_enum_ENUM 4 /* A enum table */ #define WSLUA_ARG_Pref_enum_RADIO 5 /* Radio button (true) or Combobox (false) */ return new_pref(L,PREF_ENUM); } WSLUA_CONSTRUCTOR Pref_range(lua_State* L) { /* Creates a range preference to be added to a Protocol's prefs table. */ #define WSLUA_ARG_Pref_range_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */ #define WSLUA_ARG_Pref_range_DEFAULT 2 /* The default value for this preference, e.g., "53", "10-30", or "10-30,53,55,100-120" */ #define WSLUA_ARG_Pref_range_DESCR 3 /* A description of what this preference is */ #define WSLUA_ARG_Pref_range_MAX 4 /* The maximum value */ return new_pref(L,PREF_RANGE); } WSLUA_CONSTRUCTOR Pref_statictext(lua_State* L) { /* Creates a static text preference to be added to a Protocol's prefs table. */ #define WSLUA_ARG_Pref_statictext_LABEL 1 /* The static text */ #define WSLUA_ARG_Pref_statictext_DESCR 2 /* The static text description */ return new_pref(L,PREF_STATIC_TEXT); } static range_t* get_range(lua_State *L, int idx_r, int idx_m) { static range_t *ret = NULL; gchar *pattern = g_strdup(luaL_checkstring(L, idx_r)); switch (range_convert_str(&ret, pattern, (guint32)lua_tonumber(L, idx_m))) { case CVT_NO_ERROR: break; case CVT_SYNTAX_ERROR: WSLUA_ARG_ERROR(Pref_range,DEFAULT,"syntax error in default range"); break; case CVT_NUMBER_TOO_BIG: WSLUA_ARG_ERROR(Pref_range,DEFAULT,"value too large in default range"); break; default: WSLUA_ARG_ERROR(Pref_range,DEFAULT,"unknown error in default range"); break; } g_free (pattern); return ret; } /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ static int Pref__gc(lua_State* L) { Pref pref = checkPref(L,1); if (pref && ! pref->name) { g_free(pref->label); g_free(pref->desc); if (pref->type == PREF_STRING) g_free((void*)pref->value.s); g_free(pref); } return 0; } WSLUA_METHODS Pref_methods[] = { WSLUA_CLASS_FNREG(Pref,bool), WSLUA_CLASS_FNREG(Pref,uint), WSLUA_CLASS_FNREG(Pref,string), WSLUA_CLASS_FNREG(Pref,enum), WSLUA_CLASS_FNREG(Pref,range), WSLUA_CLASS_FNREG(Pref,statictext), { NULL, NULL } }; WSLUA_META Pref_meta[] = { { NULL, NULL } }; WSLUA_REGISTER Pref_register(lua_State* L) { WSLUA_REGISTER_CLASS(Pref); return 0; } WSLUA_CLASS_DEFINE(Prefs,NOP,NOP); /* The table of preferences of a protocol */ WSLUA_METAMETHOD Prefs__newindex(lua_State* L) { /* Creates a new preference */ #define WSLUA_ARG_Prefs__newindex_NAME 2 /* The abbreviation of this preference */ #define WSLUA_ARG_Prefs__newindex_PREF 3 /* A valid but still unassigned Pref object */ Pref prefs_p = checkPrefs(L,1); const gchar* name = luaL_checkstring(L,WSLUA_ARG_Prefs__newindex_NAME); Pref pref = checkPref(L,WSLUA_ARG_Prefs__newindex_PREF); Pref p; const gchar *c; if (! prefs_p ) return 0; if (! name ) WSLUA_ARG_ERROR(Prefs__newindex,NAME,"must be a string"); if (! pref ) WSLUA_ARG_ERROR(Prefs__newindex,PREF,"must be a valid Pref"); if (pref->name) WSLUA_ARG_ERROR(Prefs__newindex,NAME,"cannot change existing preference"); if (pref->proto) WSLUA_ARG_ERROR(Prefs__newindex,PREF,"cannot be added to more than one protocol"); p = prefs_p; do { if ( p->name && g_str_equal(p->name,name) ) { luaL_error(L,"a preference named %s exists already",name); return 0; } /* * Make sure that only lower-case ASCII letters, numbers, * underscores, and dots appear in the preference name. */ for (c = name; *c != '\0'; c++) { if (!isascii((guchar)*c) || (!islower((guchar)*c) && !isdigit((guchar)*c) && *c != '_' && *c != '.')) { luaL_error(L,"illegal preference name \"%s\", only lower-case ASCII letters, numbers, underscores and dots may be used",name); return 0; } } if ( ! p->next) { p->next = pref; pref->name = g_strdup(name); if (!pref->label) pref->label = g_strdup(name); if (!prefs_p->proto->prefs_module) { prefs_p->proto->prefs_module = prefs_register_protocol(prefs_p->proto->hfid, wslua_prefs_changed); } switch(pref->type) { case PREF_BOOL: prefs_register_bool_preference(prefs_p->proto->prefs_module, pref->name, pref->label, pref->desc, &(pref->value.b)); break; case PREF_UINT: prefs_register_uint_preference(prefs_p->proto->prefs_module, pref->name, pref->label, pref->desc, 10, &(pref->value.u)); break; case PREF_STRING: prefs_register_string_preference(prefs_p->proto->prefs_module, pref->name, pref->label, pref->desc, &(pref->value.s)); break; case PREF_ENUM: prefs_register_enum_preference(prefs_p->proto->prefs_module, pref->name, pref->label, pref->desc, &(pref->value.e), pref->info.enum_info.enumvals, pref->info.enum_info.radio_buttons); break; case PREF_RANGE: prefs_register_range_preference(prefs_p->proto->prefs_module, pref->name, pref->label, pref->desc, &(pref->value.r), pref->info.max_value); break; case PREF_STATIC_TEXT: prefs_register_static_text_preference(prefs_p->proto->prefs_module, pref->name, pref->label, pref->desc); break; default: WSLUA_ERROR(Prefs__newindex,"Unknow Pref type"); } pref->proto = p->proto; WSLUA_RETURN(0); } } while (( p = p->next )); luaL_error(L,"this should not happen!"); WSLUA_RETURN(0); } WSLUA_METAMETHOD Prefs__index(lua_State* L) { /* Get the value of a preference setting */ #define WSLUA_ARG_Prefs__index_NAME 2 /* The abbreviation of this preference */ Pref prefs_p = checkPrefs(L,1); const gchar* name = luaL_checkstring(L,WSLUA_ARG_Prefs__index_NAME); if (! ( name && prefs_p ) ) return 0; prefs_p = prefs_p->next; do { if ( g_str_equal(prefs_p->name,name) ) { switch (prefs_p->type) { case PREF_BOOL: lua_pushboolean(L, prefs_p->value.b); break; case PREF_UINT: lua_pushnumber(L,(lua_Number)prefs_p->value.u); break; case PREF_STRING: lua_pushstring(L,prefs_p->value.s); break; case PREF_ENUM: lua_pushnumber(L,(lua_Number)prefs_p->value.e); break; case PREF_RANGE: lua_pushstring(L,range_convert_range(prefs_p->value.r)); break; default: WSLUA_ERROR(Prefs__index,"Unknow Pref type"); } WSLUA_RETURN(1); /* The current value of the preference */ } } while (( prefs_p = prefs_p->next )); WSLUA_ARG_ERROR(Prefs__index,NAME,"no preference named like this"); } /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ static int Prefs__gc(lua_State* L _U_) { /* do NOT free Prefs, it's never free'd */ return 0; } WSLUA_META Prefs_meta[] = { WSLUA_CLASS_MTREG(Prefs,newindex), WSLUA_CLASS_MTREG(Prefs,index), { NULL, NULL } }; WSLUA_REGISTER Prefs_register(lua_State* L) { WSLUA_REGISTER_META(Prefs); return 0; } WSLUA_CLASS_DEFINE(ProtoField,FAIL_ON_NULL("null ProtoField"),NOP); /* A Protocol field (to be used when adding items to the dissection tree) */ static const wslua_ft_types_t ftenums[] = { {"ftypes.BOOLEAN", FT_BOOLEAN}, {"ftypes.UINT8", FT_UINT8}, {"ftypes.UINT16", FT_UINT16}, {"ftypes.UINT24", FT_UINT24}, {"ftypes.UINT32", FT_UINT32}, {"ftypes.UINT64", FT_UINT64}, {"ftypes.INT8", FT_INT8}, {"ftypes.INT16", FT_INT16}, {"ftypes.INT24", FT_INT24}, {"ftypes.INT32", FT_INT32}, {"ftypes.INT64", FT_INT64}, {"ftypes.FLOAT", FT_FLOAT}, {"ftypes.DOUBLE", FT_DOUBLE}, {"ftypes.ABSOLUTE_TIME", FT_ABSOLUTE_TIME}, {"ftypes.RELATIVE_TIME", FT_RELATIVE_TIME}, {"ftypes.STRING", FT_STRING}, {"ftypes.STRINGZ", FT_STRINGZ}, {"ftypes.ETHER", FT_ETHER}, {"ftypes.BYTES", FT_BYTES}, {"ftypes.UINT_BYTES", FT_UINT_BYTES}, {"ftypes.IPv4", FT_IPv4}, {"ftypes.IPv6", FT_IPv6}, {"ftypes.IPXNET", FT_IPXNET}, {"ftypes.FRAMENUM", FT_FRAMENUM}, {"ftypes.GUID", FT_GUID}, {"ftypes.OID", FT_OID}, {"ftypes.SYSTEM_ID", FT_SYSTEM_ID}, {"ftypes.REL_OID", FT_REL_OID}, {NULL, FT_NONE} }; static enum ftenum get_ftenum(const gchar* type) { const wslua_ft_types_t* ts; for (ts = ftenums; ts->str; ts++) { if ( g_str_equal(ts->str,type) ) { return ts->id; } } return FT_NONE; } static const gchar* ftenum_to_string(enum ftenum ft) { const wslua_ft_types_t* ts; for (ts = ftenums; ts->str; ts++) { if ( ts->id == ft ) { return ts->str; } } return NULL; } struct field_display_string_t { const gchar* str; unsigned base; }; static const struct field_display_string_t base_displays[] = { {"base.NONE", BASE_NONE}, {"base.DEC", BASE_DEC}, {"base.HEX", BASE_HEX}, {"base.OCT", BASE_OCT}, {"base.DEC_HEX", BASE_DEC_HEX}, {"base.HEX_DEC", BASE_HEX_DEC}, /* for FT_BOOLEAN, how wide the parent bitfield is */ {"8",8}, {"16",16}, {"24",24}, {"32",32}, /* for FT_ABSOLUTE_TIME use values in absolute_time_display_e */ {"LOCAL", ABSOLUTE_TIME_LOCAL}, {"UTC", ABSOLUTE_TIME_UTC}, {"DOY_UTC", ABSOLUTE_TIME_DOY_UTC}, {NULL,0} }; static const gchar* base_to_string(unsigned base) { const struct field_display_string_t* b; for (b=base_displays;b->str;b++) { if ( base == b->base) return b->str; } return NULL; } static unsigned string_to_base(const gchar* str) { const struct field_display_string_t* b; for (b=base_displays;b->str;b++) { if ( g_str_equal(str,b->str)) return b->base; } return BASE_NONE; } static value_string* value_string_from_table(lua_State* L, int idx) { GArray* vs = g_array_new(TRUE,TRUE,sizeof(value_string)); value_string* ret; if(lua_isnil(L,idx)) { return NULL; } else if (!lua_istable(L,idx)) { luaL_argerror(L,idx,"must be a table"); g_array_free(vs,TRUE); return NULL; } lua_pushnil(L); while (lua_next(L, idx) != 0) { value_string v = {0,NULL}; if (! lua_isnumber(L,-2)) { luaL_argerror(L,idx,"All keys of a table used as value_string must be integers"); g_array_free(vs,TRUE); return NULL; } if (! lua_isstring(L,-1)) { luaL_argerror(L,idx,"All values of a table used as value_string must be strings"); g_array_free(vs,TRUE); return NULL; } v.value = (guint32)lua_tonumber(L,-2); v.strptr = g_strdup(lua_tostring(L,-1)); g_array_append_val(vs,v); lua_pop(L, 1); } ret = (value_string*)vs->data; g_array_free(vs,FALSE); return ret; } static val64_string* val64_string_from_table(lua_State* L, int idx) { GArray* vs = g_array_new(TRUE,TRUE,sizeof(val64_string)); val64_string* ret; if(lua_isnil(L,idx)) { return NULL; } else if (!lua_istable(L,idx)) { luaL_argerror(L,idx,"must be a table"); g_array_free(vs,TRUE); return NULL; } lua_pushnil(L); while (lua_next(L, idx) != 0) { val64_string v = {0,NULL}; if (! lua_isnumber(L,-2)) { luaL_argerror(L,idx,"All keys of a table used as value string must be integers"); g_array_free(vs,TRUE); return NULL; } if (! lua_isstring(L,-1)) { luaL_argerror(L,idx,"All values of a table used as value string must be strings"); g_array_free(vs,TRUE); return NULL; } v.value = (guint64)lua_tonumber(L, -2); v.strptr = g_strdup(lua_tostring(L,-1)); g_array_append_val(vs,v); lua_pop(L, 1); } ret = (val64_string*)vs->data; g_array_free(vs,FALSE); return ret; } static true_false_string* true_false_string_from_table(lua_State* L, int idx) { GArray* tfs = g_array_new(TRUE,TRUE,sizeof(true_false_string)); true_false_string* ret; true_false_string tf = { "True", "False" }; if (lua_isnil(L,idx)) { return NULL; } else if (!lua_istable(L,idx)) { luaL_argerror(L,idx,"must be a table"); g_array_free(tfs,TRUE); return NULL; } lua_pushnil(L); while (lua_next(L, idx)) { if (! lua_isnumber(L,-2)) { luaL_argerror(L,idx,"All keys of a table used as true_false_string must be integers"); g_array_free(tfs,TRUE); return NULL; } if (! lua_isstring(L,-1)) { luaL_argerror(L,idx,"All values of a table used as true_false_string must be strings"); g_array_free(tfs,TRUE); return NULL; } /* arrays in LUA start with index number 1 */ if ((guint32)lua_tonumber(L,-2) == 1) tf.true_string = g_strdup(lua_tostring(L,-1)); if ((guint32)lua_tonumber(L,-2) == 2) tf.false_string = g_strdup(lua_tostring(L,-1)); lua_pop(L, 1); } g_array_append_val(tfs,tf); ret = (true_false_string*)tfs->data; g_array_free(tfs,FALSE); return ret; } static const gchar* check_field_name(lua_State* L, const int abbr_idx, const enum ftenum type) { const gchar* abbr = luaL_checkstring(L,abbr_idx); const header_field_info* hfinfo = NULL; if (!abbr[0]) { luaL_argerror(L, abbr_idx, "Empty field name abbreviation"); return NULL; } if (proto_check_field_name(abbr)) { luaL_argerror(L, abbr_idx, "Invalid char in abbrev"); return NULL; } hfinfo = proto_registrar_get_byname(abbr); if (hfinfo && !ftype_similar_types(type, hfinfo->type)) { luaL_argerror(L, abbr_idx, "A field of an incompatible ftype with this abbrev already exists"); return NULL; } return abbr; } WSLUA_CONSTRUCTOR ProtoField_new(lua_State* L) { /* Creates a new field to be used in a protocol. */ #define WSLUA_ARG_ProtoField_new_NAME 1 /* Actual name of the field (the string that appears in the tree). */ #define WSLUA_ARG_ProtoField_new_ABBR 2 /* Filter name of the field (the string that is used in filters). */ #define WSLUA_ARG_ProtoField_new_TYPE 3 /* Field Type: one of ftypes.BOOLEAN, ftypes.UINT8, ftypes.UINT16, ftypes.UINT24, ftypes.UINT32, ftypes.UINT64, ftypes.INT8, ftypes.INT16 ftypes.INT24, ftypes.INT32, ftypes.INT64, ftypes.FLOAT, ftypes.DOUBLE, ftypes.ABSOLUTE_TIME ftypes.RELATIVE_TIME, ftypes.STRING, ftypes.STRINGZ, ftypes.UINT_STRING, ftypes.ETHER, ftypes.BYTES ftypes.UINT_BYTES, ftypes.IPv4, ftypes.IPv6, ftypes.IPXNET, ftypes.FRAMENUM, ftypes.PCRE, ftypes.GUID ftypes.OID, ftypes.EUI64 */ #define WSLUA_OPTARG_ProtoField_new_VALUESTRING 4 /* A table containing the text that corresponds to the values */ #define WSLUA_OPTARG_ProtoField_new_BASE 5 /* The representation: one of base.NONE, base.DEC, base.HEX, base.OCT, base.DEC_HEX, base.HEX_DEC */ #define WSLUA_OPTARG_ProtoField_new_MASK 6 /* The bitmask to be used. */ #define WSLUA_OPTARG_ProtoField_new_DESCR 7 /* The description of the field. */ ProtoField f; int nargs = lua_gettop(L); const gchar* name = luaL_checkstring(L,WSLUA_ARG_ProtoField_new_NAME); const gchar* abbr = NULL; enum ftenum type; value_string *vs32 = NULL; val64_string *vs64 = NULL; true_false_string *tfs = NULL; unsigned base; guint32 mask = (guint32)luaL_optnumber(L, WSLUA_OPTARG_ProtoField_new_MASK, 0x0); const gchar *blob = luaL_optstring(L,WSLUA_OPTARG_ProtoField_new_DESCR,NULL); if (lua_isnumber(L,WSLUA_ARG_ProtoField_new_TYPE)) { type = (enum ftenum)luaL_checkint(L,WSLUA_ARG_ProtoField_new_TYPE); } else { type = get_ftenum(luaL_checkstring(L,WSLUA_ARG_ProtoField_new_TYPE)); } abbr = check_field_name(L,WSLUA_ARG_ProtoField_new_ABBR,type); if (lua_isnumber(L, WSLUA_OPTARG_ProtoField_new_BASE)) { base = luaL_optint(L, WSLUA_OPTARG_ProtoField_new_BASE, BASE_NONE); } else { base = string_to_base(luaL_optstring(L, WSLUA_OPTARG_ProtoField_new_BASE, "BASE_NONE")); } switch (type) { case FT_FRAMENUM: if (base != BASE_NONE) { WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"FRAMENUM must use base.NONE"); } if (mask) { WSLUA_OPTARG_ERROR(ProtoField_new,MASK,"FRAMENUM can not have a bitmask"); } break; case FT_UINT8: case FT_UINT16: case FT_UINT24: case FT_UINT32: case FT_UINT64: case FT_INT8: case FT_INT16: case FT_INT24: case FT_INT32: case FT_INT64: if (base == BASE_NONE) { base = BASE_DEC; /* Default base for integer */ } else if (base < BASE_DEC || base > BASE_HEX_DEC) { WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be either base.DEC, base.HEX, base.OCT," " base.DEC_HEX, base.DEC_HEX or base.HEX_DEC"); } if ((base == BASE_HEX || base == BASE_OCT) && (type == FT_INT8 || type == FT_INT16 || type == FT_INT24 || type == FT_INT32 || type == FT_INT64)) { WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"This type does not display as hexadecimal"); } if (nargs >= WSLUA_OPTARG_ProtoField_new_VALUESTRING && !lua_isnil(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING)) { if (type == FT_UINT64 || type == FT_INT64) { vs64 = val64_string_from_table(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING); } else { vs32 = value_string_from_table(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING); } } break; case FT_BOOLEAN: if (mask == 0x0 && base != BASE_NONE) { WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be base.NONE if bitmask is zero."); } if (mask != 0x0 && (base < 1 || base > 64)) { WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be between 1 and 64 if bitmask is non-zero."); } if (nargs >= WSLUA_OPTARG_ProtoField_new_VALUESTRING && !lua_isnil(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING)) { tfs = true_false_string_from_table(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING); } break; case FT_ABSOLUTE_TIME: if (base == BASE_NONE) { base = ABSOLUTE_TIME_LOCAL; /* Default base for FT_ABSOLUTE_TIME */ } else if (base < ABSOLUTE_TIME_LOCAL || base > ABSOLUTE_TIME_DOY_UTC) { WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be either LOCAL, UTC, or DOY_UTC"); } if (mask) { WSLUA_OPTARG_ERROR(ProtoField_new,MASK,"ABSOLUTE_TIME can not have a bitmask"); } break; case FT_IPv4: case FT_IPv6: case FT_IPXNET: case FT_ETHER: case FT_FLOAT: case FT_DOUBLE: case FT_RELATIVE_TIME: case FT_STRING: case FT_STRINGZ: case FT_BYTES: case FT_UINT_BYTES: case FT_GUID: case FT_OID: case FT_SYSTEM_ID: case FT_REL_OID: if (base != BASE_NONE) { WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be base.NONE"); } if (mask) { WSLUA_OPTARG_ERROR(ProtoField_new,MASK,"This type can not have a bitmask"); } break; case FT_NONE: default: WSLUA_ARG_ERROR(ProtoField_new,TYPE,"Invalid field type"); } f = g_new(wslua_field_t,1); f->hfid = -2; f->ett = -1; f->name = g_strdup(name); f->abbr = g_strdup(abbr); f->type = type; f->base = base; if (tfs) { f->vs = TFS(tfs); } else if (vs32) { f->vs = VALS(vs32); } else if (vs64) { /* Indicate that we are using val64_string */ f->base |= BASE_VAL64_STRING; f->vs = VALS(vs64); } else { f->vs = NULL; } f->mask = mask; if (blob && strcmp(blob, f->name) != 0) { f->blob = g_strdup(blob); } else { f->blob = NULL; } pushProtoField(L,f); WSLUA_RETURN(1); /* The newly created ProtoField object */ } static int ProtoField_integer(lua_State* L, enum ftenum type) { ProtoField f; const gchar* abbr = check_field_name(L,1,type); const gchar* name = luaL_optstring(L,2,abbr); unsigned base = luaL_optint(L, 3, BASE_DEC); value_string* vs32 = NULL; val64_string* vs64 = NULL; guint32 mask = (guint32)luaL_optnumber(L,5,0); const gchar* blob = luaL_optstring(L,6,NULL); if (lua_gettop(L) > 3) { if (type == FT_UINT64 || type == FT_INT64) { vs64 = val64_string_from_table(L,4); } else { vs32 = value_string_from_table(L,4); } } if (type == FT_FRAMENUM) { if (base != BASE_NONE) luaL_argerror(L, 3, "ftypes.FRAMENUMs must use base.NONE"); else if (mask) luaL_argerror(L, 3, "ftypes.FRAMENUMs can not have a bitmask"); } else if (base < BASE_DEC || base > BASE_HEX_DEC) { luaL_argerror(L, 3, "Base must be either base.DEC, base.HEX, base.OCT," " base.DEC_HEX, base.DEC_HEX or base.HEX_DEC"); return 0; } else if ((base == BASE_HEX || base == BASE_OCT) && (type == FT_INT8 || type == FT_INT16 || type == FT_INT24 || type == FT_INT32 || type == FT_INT64)) { luaL_argerror(L, 3, "This type does not display as hexadecimal"); return 0; } f = g_new(wslua_field_t,1); f->hfid = -2; f->ett = -1; f->name = g_strdup(name); f->abbr = g_strdup(abbr); f->type = type; f->base = base; if (vs64) { /* Indicate that we are using val64_string */ f->base |= BASE_VAL64_STRING; f->vs = VALS(vs64); } else { f->vs = VALS(vs32); } f->mask = mask; if (blob && strcmp(blob, f->name) != 0) { f->blob = g_strdup(blob); } else { f->blob = NULL; } pushProtoField(L,f); return 1; } #define PROTOFIELD_INTEGER(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_integer(L,FT); } /* _WSLUA_CONSTRUCTOR_ ProtoField_uint8 */ /* WSLUA_ARG_Protofield_uint8_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_uint8_BASE One of base.DEC, base.HEX or base.OCT */ /* WSLUA_OPTARG_Protofield_uint8_VALUESTRING A table containing the text that corresponds to the values */ /* WSLUA_OPTARG_Protofield_uint8_MASK Integer mask of this field */ /* WSLUA_OPTARG_Protofield_uint8_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_uint16 */ /* WSLUA_ARG_Protofield_uint16_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_uint16_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_uint16_BASE One of base.DEC, base.HEX or base.OCT */ /* WSLUA_OPTARG_Protofield_uint16_VALUESTRING A table containing the text that corresponds to the values */ /* WSLUA_OPTARG_Protofield_uint16_MASK Integer mask of this field */ /* WSLUA_OPTARG_Protofield_uint16_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_uint24 */ /* WSLUA_ARG_Protofield_uint24_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_uint24_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_uint24_BASE One of base.DEC, base.HEX or base.OCT */ /* WSLUA_OPTARG_Protofield_uint24_VALUESTRING A table containing the text that corresponds to the values */ /* WSLUA_OPTARG_Protofield_uint24_MASK Integer mask of this field */ /* WSLUA_OPTARG_Protofield_uint24_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_uint32 */ /* WSLUA_ARG_Protofield_uint32_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_uint32_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_uint32_BASE One of base.DEC, base.HEX or base.OCT */ /* WSLUA_OPTARG_Protofield_uint32_VALUESTRING A table containing the text that corresponds to the values */ /* WSLUA_OPTARG_Protofield_uint32_MASK Integer mask of this field */ /* WSLUA_OPTARG_Protofield_uint32_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_uint64 */ /* WSLUA_ARG_Protofield_uint64_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_uint64_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_uint64_BASE One of base.DEC, base.HEX or base.OCT */ /* WSLUA_OPTARG_Protofield_uint64_VALUESTRING A table containing the text that corresponds to the values */ /* WSLUA_OPTARG_Protofield_uint64_MASK Integer mask of this field */ /* WSLUA_OPTARG_Protofield_uint64_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_int8 */ /* WSLUA_ARG_Protofield_int8_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_int8_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_int8_BASE One of base.DEC, base.HEX or base.OCT */ /* WSLUA_OPTARG_Protofield_int8_VALUESTRING A table containing the text that corresponds to the values */ /* WSLUA_OPTARG_Protofield_int8_MASK Integer mask of this field */ /* WSLUA_OPTARG_Protofield_int8_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_int16 */ /* WSLUA_ARG_Protofield_int16_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_int16_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_int16_BASE One of base.DEC, base.HEX or base.OCT */ /* WSLUA_OPTARG_Protofield_int16_VALUESTRING A table containing the text that corresponds to the values */ /* WSLUA_OPTARG_Protofield_int16_MASK Integer mask of this field */ /* WSLUA_OPTARG_Protofield_int16_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_int24 */ /* WSLUA_ARG_Protofield_int24_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_int24_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_int24_BASE One of base.DEC, base.HEX or base.OCT */ /* WSLUA_OPTARG_Protofield_int24_VALUESTRING A table containing the text that corresponds to the values */ /* WSLUA_OPTARG_Protofield_int24_MASK Integer mask of this field */ /* WSLUA_OPTARG_Protofield_int24_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_int32 */ /* WSLUA_ARG_Protofield_int32_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_int32_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_int32_BASE One of base.DEC, base.HEX or base.OCT */ /* WSLUA_OPTARG_Protofield_int32_VALUESTRING A table containing the text that corresponds to the values */ /* WSLUA_OPTARG_Protofield_int32_MASK Integer mask of this field */ /* WSLUA_OPTARG_Protofield_int32_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_int64 */ /* WSLUA_ARG_Protofield_int64_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_int64_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_int64_BASE One of base.DEC, base.HEX or base.OCT */ /* WSLUA_OPTARG_Protofield_int64_VALUESTRING A table containing the text that corresponds to the values */ /* WSLUA_OPTARG_Protofield_int64_MASK Integer mask of this field */ /* WSLUA_OPTARG_Protofield_int64_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_framenum A frame number (for hyperlinks between frames) */ /* WSLUA_ARG_Protofield_framenum_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_framenum_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_framenum_BASE One of base.DEC, base.HEX or base.OCT */ /* WSLUA_OPTARG_Protofield_framenum_VALUESTRING A table containing the text that corresponds to the values */ /* WSLUA_OPTARG_Protofield_framenum_MASK Integer mask of this field */ /* WSLUA_OPTARG_Protofield_framenum_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ PROTOFIELD_INTEGER(uint8,FT_UINT8) PROTOFIELD_INTEGER(uint16,FT_UINT16) PROTOFIELD_INTEGER(uint24,FT_UINT24) PROTOFIELD_INTEGER(uint32,FT_UINT32) PROTOFIELD_INTEGER(uint64,FT_UINT64) PROTOFIELD_INTEGER(int8,FT_INT8) PROTOFIELD_INTEGER(int16,FT_INT16) PROTOFIELD_INTEGER(int24,FT_INT24) PROTOFIELD_INTEGER(int32,FT_INT32) PROTOFIELD_INTEGER(int64,FT_INT64) PROTOFIELD_INTEGER(framenum,FT_FRAMENUM) static int ProtoField_boolean(lua_State* L, enum ftenum type) { ProtoField f; const gchar* abbr = check_field_name(L,1,type); const gchar* name = luaL_optstring(L,2,abbr); unsigned base = luaL_optint(L, 3, BASE_NONE); true_false_string* tfs = NULL; guint32 mask = (guint32)luaL_optnumber(L,5,0); const gchar* blob = luaL_optstring(L,6,NULL); if (mask == 0x0 && base != BASE_NONE) { luaL_argerror(L,2,"Fieldbase (fielddisplay) must be base.NONE" " if bitmask is zero."); return 0; } if (mask != 0x0 && (base < 1 || base > 64)) { luaL_argerror(L,2,"Fieldbase (fielddisplay) must be between 1 and 64" " if bitmask is non-zero."); return 0; } if (lua_gettop(L) > 3 && !lua_isnil(L,4)) { tfs = true_false_string_from_table(L,4); } f = g_new(wslua_field_t,1); f->hfid = -2; f->ett = -1; f->name = g_strdup(name); f->abbr = g_strdup(abbr); f->type = type; f->vs = TFS(tfs); f->base = base; f->mask = mask; if (blob && strcmp(blob, f->name) != 0) { f->blob = g_strdup(blob); } else { f->blob = NULL; } pushProtoField(L,f); return 1; } #define PROTOFIELD_BOOL(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_boolean(L,FT); } /* _WSLUA_CONSTRUCTOR_ ProtoField_bool */ /* WSLUA_ARG_Protofield_bool_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_bool_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_bool_DISPLAY how wide the parent bitfield is (base.NONE is used for NULL-value) */ /* WSLUA_OPTARG_Protofield_bool_VALUESTRING A table containing the text that corresponds to the values */ /* WSLUA_OPTARG_Protofield_bool_MASK Integer mask of this field */ /* WSLUA_OPTARG_Protofield_bool_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* XXX: T/F strings */ PROTOFIELD_BOOL(bool,FT_BOOLEAN) static int ProtoField_time(lua_State* L,enum ftenum type) { ProtoField f; const gchar* abbr = NULL; const gchar* name = luaL_optstring(L,2,abbr); unsigned base = luaL_optint(L,3,ABSOLUTE_TIME_LOCAL); const gchar* blob = NULL; if (type == FT_ABSOLUTE_TIME) { abbr = check_field_name(L,1,type); blob = luaL_optstring(L,4,NULL); if (base < ABSOLUTE_TIME_LOCAL || base > ABSOLUTE_TIME_DOY_UTC) { luaL_argerror(L, 3, "Base must be either LOCAL, UTC, or DOY_UTC"); return 0; } } else { abbr = check_field_name(L,1,type); blob = luaL_optstring(L,3,NULL); } f = g_new(wslua_field_t,1); f->hfid = -2; f->ett = -1; f->name = g_strdup(name); f->abbr = g_strdup(abbr); f->type = type; f->vs = NULL; f->base = base; f->mask = 0; if (blob && strcmp(blob, f->name) != 0) { f->blob = g_strdup(blob); } else { f->blob = NULL; } pushProtoField(L,f); return 1; } #define PROTOFIELD_TIME(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_time(L,FT); } /* _WSLUA_CONSTRUCTOR_ ProtoField_absolute_time */ /* WSLUA_ARG_Protofield_absolute_time_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_absolute_time_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_absolute_time_BASE One of base.LOCAL, base.UTC or base.DOY_UTC */ /* WSLUA_OPTARG_Protofield_absolute_time_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_relative_time */ /* WSLUA_ARG_Protofield_relative_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_relative_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_relative_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ PROTOFIELD_TIME(absolute_time,FT_ABSOLUTE_TIME) static int ProtoField_other(lua_State* L,enum ftenum type) { ProtoField f; const gchar* abbr = check_field_name(L,1,type); const gchar* name = luaL_optstring(L,2,abbr); const gchar* blob = luaL_optstring(L,3,NULL); f = g_new(wslua_field_t,1); f->hfid = -2; f->ett = -1; f->name = g_strdup(name); f->abbr = g_strdup(abbr); f->type = type; f->vs = NULL; f->base = BASE_NONE; f->mask = 0; if (blob && strcmp(blob, f->name) != 0) { f->blob = g_strdup(blob); } else { f->blob = NULL; } pushProtoField(L,f); return 1; } #define PROTOFIELD_OTHER(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_other(L,FT); } /* _WSLUA_CONSTRUCTOR_ ProtoField_ipv4 */ /* WSLUA_ARG_Protofield_ipv4_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_ipv4_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_ipv4_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_ipv6 */ /* WSLUA_ARG_Protofield_ipv6_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_ipv6_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_ipv6_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_ether */ /* WSLUA_ARG_Protofield_ether_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_ether_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_ether_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_float */ /* WSLUA_ARG_Protofield_float_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_float_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_float_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_double */ /* WSLUA_ARG_Protofield_double_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_double_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_double_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_string */ /* WSLUA_ARG_Protofield_string_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_string_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_string_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_stringz */ /* WSLUA_ARG_Protofield_stringz_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_stringz_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_stringz_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_bytes */ /* WSLUA_ARG_Protofield_bytes_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_bytes_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_bytes_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_ubytes */ /* WSLUA_ARG_Protofield_ubytes_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_ubytes_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_ubytes_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_guid */ /* WSLUA_ARG_Protofield_guid_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_guid_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_guid_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_oid */ /* WSLUA_ARG_Protofield_oid_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_oid_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_oid_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ /* _WSLUA_CONSTRUCTOR_ ProtoField_bool */ /* WSLUA_ARG_Protofield_bool_ABBR Abbreviated name of the field (the string used in filters) */ /* WSLUA_OPTARG_Protofield_bool_NAME Actual name of the field (the string that appears in the tree) */ /* WSLUA_OPTARG_Protofield_bool_DESC Description of the field */ /* _WSLUA_RETURNS_ A protofield item to be added to a ProtoFieldArray */ PROTOFIELD_OTHER(ipv4,FT_IPv4) PROTOFIELD_OTHER(ipv6,FT_IPv6) PROTOFIELD_OTHER(ipx,FT_IPXNET) PROTOFIELD_OTHER(ether,FT_ETHER) PROTOFIELD_OTHER(float,FT_FLOAT) PROTOFIELD_OTHER(double,FT_DOUBLE) PROTOFIELD_OTHER(relative_time,FT_RELATIVE_TIME) PROTOFIELD_OTHER(string,FT_STRING) PROTOFIELD_OTHER(stringz,FT_STRINGZ) PROTOFIELD_OTHER(bytes,FT_BYTES) PROTOFIELD_OTHER(ubytes,FT_UINT_BYTES) PROTOFIELD_OTHER(guid,FT_GUID) PROTOFIELD_OTHER(oid,FT_OID) PROTOFIELD_OTHER(rel_oid,FT_REL_OID) PROTOFIELD_OTHER(systemid,FT_SYSTEM_ID) WSLUA_METAMETHOD ProtoField__tostring(lua_State* L) { /* Returns a string with info about a protofield (for debugging purposes) */ ProtoField f = checkProtoField(L,1); gchar* s = (gchar *)ep_strdup_printf("ProtoField(%i): %s %s %s %s %p %.8x %s",f->hfid,f->name,f->abbr,ftenum_to_string(f->type),base_to_string(f->base),f->vs,f->mask,f->blob); lua_pushstring(L,s); return 1; } static int ProtoField__gc(lua_State* L) { ProtoField f = checkProtoField(L,1); /* * A garbage collector for ProtoFields makes little sense. * Even if This cannot be used anymore because it has gone out of scope, * we can destroy the ProtoField only if it is not part of a ProtoFieldArray, * if it actualy belongs to one we need to preserve it as it is pointed by * a field array that may be registered afterwards causing a crash or memory corruption. */ if (!f) { luaL_argerror(L,1,"BUG: ProtoField_gc called for something not ProtoField"); /* g_assert() ?? */ } else if (f->hfid == -2) { g_free(f->name); g_free(f->abbr); g_free(f->blob); g_free(f); } return 0; } WSLUA_METHODS ProtoField_methods[] = { WSLUA_CLASS_FNREG(ProtoField,new), WSLUA_CLASS_FNREG(ProtoField,uint8), WSLUA_CLASS_FNREG(ProtoField,uint16), WSLUA_CLASS_FNREG(ProtoField,uint24), WSLUA_CLASS_FNREG(ProtoField,uint32), WSLUA_CLASS_FNREG(ProtoField,uint64), WSLUA_CLASS_FNREG(ProtoField,int8), WSLUA_CLASS_FNREG(ProtoField,int16), WSLUA_CLASS_FNREG(ProtoField,int24), WSLUA_CLASS_FNREG(ProtoField,int32), WSLUA_CLASS_FNREG(ProtoField,int64), WSLUA_CLASS_FNREG(ProtoField,framenum), WSLUA_CLASS_FNREG(ProtoField,ipv4), WSLUA_CLASS_FNREG(ProtoField,ipv6), WSLUA_CLASS_FNREG(ProtoField,ipx), WSLUA_CLASS_FNREG(ProtoField,ether), WSLUA_CLASS_FNREG(ProtoField,bool), WSLUA_CLASS_FNREG(ProtoField,float), WSLUA_CLASS_FNREG(ProtoField,double), WSLUA_CLASS_FNREG(ProtoField,absolute_time), WSLUA_CLASS_FNREG(ProtoField,relative_time), WSLUA_CLASS_FNREG(ProtoField,string), WSLUA_CLASS_FNREG(ProtoField,stringz), WSLUA_CLASS_FNREG(ProtoField,bytes), WSLUA_CLASS_FNREG(ProtoField,ubytes), WSLUA_CLASS_FNREG(ProtoField,guid), WSLUA_CLASS_FNREG(ProtoField,oid), WSLUA_CLASS_FNREG(ProtoField,rel_oid), WSLUA_CLASS_FNREG(ProtoField,systemid), { NULL, NULL } }; WSLUA_META ProtoField_meta[] = { WSLUA_CLASS_MTREG(ProtoField,tostring), { NULL, NULL } }; int ProtoField_register(lua_State* L) { WSLUA_REGISTER_CLASS(ProtoField); return 0; } WSLUA_CLASS_DEFINE(Proto,FAIL_ON_NULL("Proto"),NOP); /* A new protocol in wireshark. Protocols have more uses, the main one is to dissect a protocol. But they can be just dummies used to register preferences for other purposes. */ static int protocols_table_ref = LUA_NOREF; WSLUA_CONSTRUCTOR Proto_new(lua_State* L) { #define WSLUA_ARG_Proto_new_NAME 1 /* The name of the protocol */ #define WSLUA_ARG_Proto_new_DESC 2 /* A Long Text description of the protocol (usually lowercase) */ const gchar* name = luaL_checkstring(L,WSLUA_ARG_Proto_new_NAME); const gchar* desc = luaL_checkstring(L,WSLUA_ARG_Proto_new_DESC); /* TODO: should really make a common function for all of wslua that does checkstring and non-empty at same time */ if (!name[0] || !desc[0]) luaL_argerror(L,WSLUA_ARG_Proto_new_NAME,"must not be an empty string"); if ( name ) { gchar* loname_a; int proto_id; loname_a = g_ascii_strdown(name, -1); proto_id = proto_get_id_by_filter_name(loname_a); g_free(loname_a); if ( proto_id > 0 ) { WSLUA_ARG_ERROR(Proto_new,NAME,"there cannot be two protocols with the same name"); } else { Proto proto = (wslua_proto_t *)g_malloc(sizeof(wslua_proto_t)); gchar* loname = g_ascii_strdown(name, -1); gchar* hiname = g_ascii_strup(name, -1); proto->name = hiname; proto->desc = g_strdup(desc); proto->hfid = proto_register_protocol(proto->desc,hiname,loname); proto->ett = -1; proto->is_postdissector = FALSE; lua_newtable (L); proto->fields = luaL_ref(L, LUA_REGISTRYINDEX); proto->prefs.name = NULL; proto->prefs.label = NULL; proto->prefs.desc = NULL; proto->prefs.value.u = 0; proto->prefs.next = NULL; proto->prefs.proto = proto; proto->prefs_module = NULL; proto->handle = NULL; lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref); lua_pushstring(L,loname); pushProto(L,proto); lua_settable(L, -3); pushProto(L,proto); WSLUA_RETURN(1); /* The newly created protocol */ } } else WSLUA_ARG_ERROR(Proto_new,NAME,"must be a string"); return 0; } WSLUA_METAMETHOD Proto__call(lua_State* L) { /* Creates a Proto object */ #define WSLUA_ARG_Proto__call_NAME 1 /* The name of the protocol */ #define WSLUA_ARG_Proto__call_DESC 2 /* A Long Text description of the protocol (usually lowercase) */ lua_remove(L,1); /* remove the table */ WSLUA_RETURN(Proto_new(L)); /* The new Proto object. */ } static int Proto__tostring(lua_State* L) { Proto proto = checkProto(L,1); gchar* s; if (!proto) return 0; s = ep_strdup_printf("Proto: %s",proto->name); lua_pushstring(L,s); return 1; } WSLUA_FUNCTION wslua_register_postdissector(lua_State* L) { /* Make a protocol (with a dissector) a postdissector. It will be called for every frame after dissection */ #define WSLUA_ARG_register_postdissector_PROTO 1 /* the protocol to be used as postdissector */ Proto proto = checkProto(L,WSLUA_ARG_register_postdissector_PROTO); if (!proto) return 0; if(!proto->is_postdissector) { if (! proto->handle) { proto->handle = new_create_dissector_handle(dissect_lua, proto->hfid); } register_postdissector(proto->handle); } else { luaL_argerror(L,1,"this protocol is already registered as postdissector"); } return 0; } /* WSLUA_ATTRIBUTE Proto_dissector RW The protocol's dissector, a function you define. The called dissector function will be given three arguments of (1) a Tvb object, (2) a Pinfo object, and (3) a TreeItem object. */ static int Proto_get_dissector(lua_State* L) { Proto proto = checkProto(L,1); if (proto->handle) { pushDissector(L,proto->handle); return 1; } else { luaL_error(L,"The protocol hasn't been registered yet"); return 0; } } static int Proto_set_dissector(lua_State* L) { Proto proto = checkProto(L,1); if (lua_isfunction(L,2)) { /* insert the dissector into the dissectors table */ gchar* loname = g_ascii_strdown(proto->name, -1); lua_rawgeti(L, LUA_REGISTRYINDEX, lua_dissectors_table_ref); lua_replace(L, 1); lua_pushstring(L,proto->name); lua_insert(L, 2); /* function is now at 3 */ lua_settable(L,1); proto->handle = new_create_dissector_handle(dissect_lua, proto->hfid); new_register_dissector(loname, dissect_lua, proto->hfid); } else { luaL_argerror(L,2,"The dissector of a protocol must be a function"); } return 0; } /* WSLUA_ATTRIBUTE Proto_prefs RO The preferences of this dissector */ static int Proto_get_prefs(lua_State* L) { Proto proto = checkProto(L,1); pushPrefs(L,&proto->prefs); return 1; } /* WSLUA_ATTRIBUTE Proto_prefs_changed WO The preferences changed routine of this dissector, a function you define. */ static int Proto_set_prefs_changed(lua_State* L) { Proto proto = checkProto(L,1); if (lua_isfunction(L,2)) { /* insert the prefs changed callback into the prefs_changed table */ lua_getglobal(L, WSLUA_PREFS_CHANGED); lua_replace(L, 1); lua_pushstring(L,proto->name); lua_insert(L, 2); /* function is now at 3 */ lua_settable(L,1); } else { luaL_argerror(L,2,"The prefs of a protocol must be a function"); } return 0; } /* WSLUA_ATTRIBUTE Proto_init WO The init routine of this dissector, a function you define. The called init function is passed no arguments. */ static int Proto_set_init(lua_State* L) { Proto proto = checkProto(L,1); if (lua_isfunction(L,2)) { /* insert the init routine into the init_routines table */ lua_getglobal(L, WSLUA_INIT_ROUTINES); lua_replace(L, 1); lua_pushstring(L,proto->name); lua_insert(L, 2); /* function is now at 3 */ lua_settable(L,1); } else { luaL_argerror(L,2,"The initializer of a protocol must be a function"); } return 0; } /* WSLUA_ATTRIBUTE Proto_name RO The name given to this dissector */ WSLUA_ATTRIBUTE_STRING_GETTER(Proto,name); /* WSLUA_ATTRIBUTE Proto_description RO The description given to this dissector */ WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(Proto,description,desc); /* WSLUA_ATTRIBUTE Proto_fields RW The Fields Table of this dissector */ static int Proto_get_fields(lua_State* L) { Proto proto = checkProto(L,1); lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields); return 1; } static int Proto_set_fields(lua_State* L) { Proto proto = checkProto(L,1); #define FIELDS_TABLE 2 #define NEW_TABLE 3 #define NEW_FIELD 3 lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields); lua_insert(L,FIELDS_TABLE); if( lua_istable(L,NEW_TABLE)) { for (lua_pushnil(L); lua_next(L, NEW_TABLE); ) { if (isProtoField(L,5)) { luaL_ref(L,FIELDS_TABLE); } else if (! lua_isnil(L,5) ) { return luaL_error(L,"only ProtoFields should be in the table"); } } } else if (isProtoField(L,NEW_FIELD)){ lua_pushvalue(L, NEW_FIELD); luaL_ref(L,FIELDS_TABLE); } else { return luaL_error(L,"either a ProtoField or an array of protofields"); } lua_pushvalue(L, 3); return 1; } /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ static int Proto__gc(lua_State* L _U_) { /* do NOT free Proto, it's never free'd */ return 0; } /* This table is ultimately registered as a sub-table of the class' metatable, * and if __index/__newindex is invoked then it calls the appropriate function * from this table for getting/setting the members. */ WSLUA_ATTRIBUTES Proto_attributes[] = { WSLUA_ATTRIBUTE_RWREG(Proto,dissector), WSLUA_ATTRIBUTE_RWREG(Proto,fields), WSLUA_ATTRIBUTE_ROREG(Proto,prefs), WSLUA_ATTRIBUTE_WOREG(Proto,prefs_changed), WSLUA_ATTRIBUTE_WOREG(Proto,init), WSLUA_ATTRIBUTE_ROREG(Proto,name), WSLUA_ATTRIBUTE_ROREG(Proto,description), { NULL, NULL, NULL } }; WSLUA_METHODS Proto_methods[] = { WSLUA_CLASS_FNREG(Proto,new), { NULL, NULL } }; WSLUA_META Proto_meta[] = { WSLUA_CLASS_MTREG(Proto,tostring), WSLUA_CLASS_MTREG(Proto,call), { NULL, NULL } }; int Proto_register(lua_State* L) { WSLUA_REGISTER_CLASS(Proto); WSLUA_REGISTER_ATTRIBUTES(Proto); lua_newtable(L); protocols_table_ref = luaL_ref(L, LUA_REGISTRYINDEX); return 0; } /** * Query field abbr that is defined and bound to a Proto in lua. * They are not registered untill the end of the initialization. */ int wslua_is_field_available(lua_State* L, const char* field_abbr) { lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref); lua_pushnil(L); while (lua_next(L, -2)) { Proto proto; proto = checkProto(L, -1); lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields); lua_pushnil(L); while (lua_next(L, -2)) { ProtoField f = checkProtoField(L, -1); if (strcmp(field_abbr, f->abbr) == 0) { /* found! */ lua_pop(L, 6); return 1; } lua_pop(L, 1); /* table value */ } lua_pop(L, 2); /* proto->fields and table value */ } lua_pop(L, 1); /* protocols_table_ref */ return 0; } int Proto_commit(lua_State* L) { lua_settop(L,0); lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref); for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 2)) { GArray* hfa = g_array_new(TRUE,TRUE,sizeof(hf_register_info)); GArray* etta = g_array_new(TRUE,TRUE,sizeof(gint*)); Proto proto; /* const gchar* proto_name = lua_tostring(L,2); */ proto = checkProto(L,3); lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields); for (lua_pushnil(L); lua_next(L, 4); lua_pop(L, 1)) { ProtoField f = checkProtoField(L,6); hf_register_info hfri = { &(f->hfid), {f->name,f->abbr,f->type,f->base,VALS(f->vs),f->mask,f->blob,HFILL}}; gint* ettp = &(f->ett); if (f->hfid != -2) { return luaL_error(L,"fields can be registered only once"); } f->hfid = -1; g_array_append_val(hfa,hfri); g_array_append_val(etta,ettp); } proto_register_field_array(proto->hfid,(hf_register_info*)hfa->data,hfa->len); proto_register_subtree_array((gint**)etta->data,etta->len); g_array_free(hfa,FALSE); g_array_free(etta,FALSE); } lua_pop(L,1); /* pop the protocols_table_ref */ return 0; } WSLUA_CLASS_DEFINE(Dissector,NOP,NOP); /* A refererence to a dissector, used to call a dissector against a packet or a part of it. */ WSLUA_CONSTRUCTOR Dissector_get (lua_State *L) { /* Obtains a dissector reference by name */ #define WSLUA_ARG_Dissector_get_NAME 1 /* The name of the dissector */ const gchar* name = luaL_checkstring(L,WSLUA_ARG_Dissector_get_NAME); Dissector d; if (!name) WSLUA_ARG_ERROR(Dissector_get,NAME,"must be a string"); if ((d = find_dissector(name))) { pushDissector(L, d); WSLUA_RETURN(1); /* The Dissector reference */ } else WSLUA_ARG_ERROR(Dissector_get,NAME,"No such dissector"); } WSLUA_METHOD Dissector_call(lua_State* L) { /* Calls a dissector against a given packet (or part of it) */ #define WSLUA_ARG_Dissector_call_TVB 2 /* The buffer to dissect */ #define WSLUA_ARG_Dissector_call_PINFO 3 /* The packet info */ #define WSLUA_ARG_Dissector_call_TREE 4 /* The tree on which to add the protocol items */ Dissector d = checkDissector(L,1); Tvb tvb = checkTvb(L,WSLUA_ARG_Dissector_call_TVB); Pinfo pinfo = checkPinfo(L,WSLUA_ARG_Dissector_call_PINFO); TreeItem ti = checkTreeItem(L,WSLUA_ARG_Dissector_call_TREE); const char *volatile error = NULL; if (! ( d && tvb && pinfo) ) return 0; TRY { call_dissector(d, tvb->ws_tvb, pinfo->ws_pinfo, ti->tree); /* XXX Are we sure about this??? is this the right/only thing to catch */ } CATCH_NONFATAL_ERRORS { show_exception(tvb->ws_tvb, pinfo->ws_pinfo, ti->tree, EXCEPT_CODE, GET_MESSAGE); error = "Malformed frame"; } ENDTRY; if (error) { WSLUA_ERROR(Dissector_call,error); } return 0; } WSLUA_METAMETHOD Dissector__tostring(lua_State* L) { /* Gets the Dissector's protocol short name */ Dissector d = checkDissector(L,1); if (!d) return 0; lua_pushstring(L,dissector_handle_get_short_name(d)); WSLUA_RETURN(1); /* A string of the protocol's short name */ } /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ static int Dissector__gc(lua_State* L _U_) { /* do NOT free Dissector */ return 0; } WSLUA_METHODS Dissector_methods[] = { WSLUA_CLASS_FNREG(Dissector,get), WSLUA_CLASS_FNREG(Dissector,call), { NULL, NULL } }; WSLUA_META Dissector_meta[] = { WSLUA_CLASS_MTREG(Dissector,tostring), { NULL, NULL } }; int Dissector_register(lua_State* L) { WSLUA_REGISTER_CLASS(Dissector); return 0; } WSLUA_CLASS_DEFINE(DissectorTable,NOP,NOP); /* A table of subdissectors of a particular protocol (e.g. TCP subdissectors like http, smtp, sip are added to table "tcp.port"). Useful to add more dissectors to a table so that they appear in the Decode As... dialog. */ WSLUA_CONSTRUCTOR DissectorTable_new (lua_State *L) { /* Creates a new DissectorTable for your dissector's use. */ #define WSLUA_ARG_DissectorTable_new_TABLENAME 1 /* The short name of the table. */ #define WSLUA_OPTARG_DissectorTable_new_UINAME 2 /* The name of the table in the User Interface (defaults to the name given). */ #define WSLUA_OPTARG_DissectorTable_new_TYPE 3 /* Either ftypes.UINT{8,16,24,32} or ftypes.STRING (defaults to ftypes.UINT32) */ #define WSLUA_OPTARG_DissectorTable_new_BASE 4 /* Either base.NONE, base.DEC, base.HEX, base.OCT, base.DEC_HEX or base.HEX_DEC (defaults to base.DEC) */ const gchar* name = (const gchar*)luaL_checkstring(L,WSLUA_ARG_DissectorTable_new_TABLENAME); const gchar* ui_name = (const gchar*)luaL_optstring(L,WSLUA_OPTARG_DissectorTable_new_UINAME,name); enum ftenum type = (enum ftenum)luaL_optint(L,WSLUA_OPTARG_DissectorTable_new_TYPE,FT_UINT32); unsigned base = (unsigned)luaL_optint(L,WSLUA_OPTARG_DissectorTable_new_BASE,BASE_DEC); if(!(name && ui_name)) return 0; switch(type) { case FT_STRING: base = BASE_NONE; /* fallthrough */ case FT_UINT8: case FT_UINT16: case FT_UINT24: case FT_UINT32: { DissectorTable dt = (DissectorTable)g_malloc(sizeof(struct _wslua_distbl_t)); name = g_strdup(name); ui_name = g_strdup(ui_name); dt->table = register_dissector_table(name, ui_name, type, base); dt->name = name; pushDissectorTable(L, dt); } WSLUA_RETURN(1); /* The newly created DissectorTable */ default: WSLUA_OPTARG_ERROR(DissectorTable_new,TYPE,"must be ftypes.UINT{8,16,24,32} or ftypes.STRING"); } return 0; } WSLUA_CONSTRUCTOR DissectorTable_get (lua_State *L) { /* Obtain a reference to an existing dissector table. */ #define WSLUA_ARG_DissectorTable_get_TABLENAME 1 /* The short name of the table. */ const gchar* name = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_TABLENAME); dissector_table_t table; if(!name) return 0; table = find_dissector_table(name); if (table) { DissectorTable dt = (DissectorTable)g_malloc(sizeof(struct _wslua_distbl_t)); dt->table = table; dt->name = g_strdup(name); pushDissectorTable(L, dt); WSLUA_RETURN(1); /* The DissectorTable */ } else WSLUA_ARG_ERROR(DissectorTable_get,TABLENAME,"no such dissector_table"); } WSLUA_METHOD DissectorTable_add (lua_State *L) { /* Add a dissector or a range of dissectors to a table. */ #define WSLUA_ARG_DissectorTable_add_PATTERN 2 /* The pattern to match (either an integer, a integer range or a string depending on the table's type). */ #define WSLUA_ARG_DissectorTable_add_DISSECTOR 3 /* The dissector to add (either an Proto or a Dissector). */ DissectorTable dt = checkDissectorTable(L,1); ftenum_t type; Dissector handle; if (!dt) return 0; if( isProto(L,WSLUA_ARG_DissectorTable_add_DISSECTOR) ) { Proto p; p = checkProto(L,WSLUA_ARG_DissectorTable_add_DISSECTOR); handle = p->handle; if (! handle) WSLUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"a Protocol that does not have a dissector cannot be added to a table"); } else if ( isDissector(L,WSLUA_ARG_DissectorTable_add_DISSECTOR) ) { handle = toDissector(L,WSLUA_ARG_DissectorTable_add_DISSECTOR); } else WSLUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"must be either Proto or Dissector"); type = get_dissector_table_selector_type(dt->name); if (type == FT_STRING) { gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN)); dissector_add_string(dt->name, pattern,handle); g_free (pattern); } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { if (lua_isnumber(L, WSLUA_ARG_DissectorTable_add_PATTERN)) { int port = luaL_checkint(L, WSLUA_ARG_DissectorTable_add_PATTERN); dissector_add_uint(dt->name, port, handle); } else { /* Not a number, try as range */ gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN)); range_t *range; if (range_convert_str(&range, pattern, G_MAXUINT32) == CVT_NO_ERROR) dissector_add_uint_range(dt->name, range, handle); else WSLUA_ARG_ERROR(DissectorTable_add,PATTERN,"invalid integer or range"); g_free (pattern); } } else { luaL_error(L,"Strange type %d for a DissectorTable",type); } return 0; } WSLUA_METHOD DissectorTable_set (lua_State *L) { /* Remove existing dissectors from a table and add a new or a range of new dissectors. */ #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). */ #define WSLUA_ARG_DissectorTable_set_DISSECTOR 3 /* The dissector to add (either an Proto or a Dissector). */ DissectorTable dt = checkDissectorTable(L,1); ftenum_t type; Dissector handle; if (!dt) return 0; if( isProto(L,WSLUA_ARG_DissectorTable_set_DISSECTOR) ) { Proto p; p = checkProto(L,WSLUA_ARG_DissectorTable_set_DISSECTOR); handle = p->handle; if (! handle) WSLUA_ARG_ERROR(DissectorTable_set,DISSECTOR,"a Protocol that does not have a dissector cannot be set to a table"); } else if ( isDissector(L,WSLUA_ARG_DissectorTable_set_DISSECTOR) ) { handle = toDissector(L,WSLUA_ARG_DissectorTable_set_DISSECTOR); } else WSLUA_ARG_ERROR(DissectorTable_set,DISSECTOR,"must be either Proto or Dissector"); type = get_dissector_table_selector_type(dt->name); if (type == FT_STRING) { gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN)); dissector_delete_all(dt->name, handle); dissector_add_string(dt->name, pattern,handle); g_free (pattern); } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { if (lua_isnumber(L, WSLUA_ARG_DissectorTable_set_PATTERN)) { int port = luaL_checkint(L, WSLUA_ARG_DissectorTable_set_PATTERN); dissector_delete_all(dt->name, handle); dissector_add_uint(dt->name, port, handle); } else { /* Not a number, try as range */ gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN)); range_t *range; if (range_convert_str(&range, pattern, G_MAXUINT32) == CVT_NO_ERROR) { dissector_delete_all(dt->name, handle); dissector_add_uint_range(dt->name, range, handle); } else { WSLUA_ARG_ERROR(DissectorTable_set,PATTERN,"invalid integer or range"); } g_free (pattern); } } else { luaL_error(L,"Strange type %d for a DissectorTable",type); } return 0; } WSLUA_METHOD DissectorTable_remove (lua_State *L) { /* Remove a dissector or a range of dissectors from a table */ #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). */ #define WSLUA_ARG_DissectorTable_remove_DISSECTOR 3 /* The dissector to remove (either an Proto or a Dissector). */ DissectorTable dt = checkDissectorTable(L,1); ftenum_t type; Dissector handle; if (!dt) return 0; if( isProto(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR) ) { Proto p; p = checkProto(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR); handle = p->handle; } else if ( isDissector(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR) ) { handle = toDissector(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR); } else WSLUA_ARG_ERROR(DissectorTable_remove,DISSECTOR,"must be either Proto or Dissector"); type = get_dissector_table_selector_type(dt->name); if (type == FT_STRING) { gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN)); dissector_delete_string(dt->name, pattern,handle); g_free (pattern); } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { if (lua_isnumber(L, WSLUA_ARG_DissectorTable_remove_PATTERN)) { int port = luaL_checkint(L, WSLUA_ARG_DissectorTable_remove_PATTERN); dissector_delete_uint(dt->name, port, handle); } else { /* Not a number, try as range */ gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN)); range_t *range; if (range_convert_str(&range, pattern, G_MAXUINT32) == CVT_NO_ERROR) dissector_delete_uint_range(dt->name, range, handle); else WSLUA_ARG_ERROR(DissectorTable_remove,PATTERN,"invalid integer or range"); g_free (pattern); } } return 0; } WSLUA_METHOD DissectorTable_remove_all (lua_State *L) { /* Remove all dissectors from a table */ #define WSLUA_ARG_DissectorTable_remove_all_DISSECTOR 2 /* The dissector to add (either an Proto or a Dissector). */ DissectorTable dt = checkDissectorTable(L,1); Dissector handle; if (!dt) return 0; if( isProto(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR) ) { Proto p; p = checkProto(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR); handle = p->handle; } else if ( isDissector(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR) ) { handle = toDissector(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR); } else WSLUA_ARG_ERROR(DissectorTable_remove_all,DISSECTOR,"must be either Proto or Dissector"); dissector_delete_all (dt->name, handle); return 0; } WSLUA_METHOD DissectorTable_try (lua_State *L) { /* Try to call a dissector from a table */ #define WSLUA_ARG_DissectorTable_try_PATTERN 2 /* The pattern to be matched (either an integer or a string depending on the table's type). */ #define WSLUA_ARG_DissectorTable_try_TVB 3 /* The buffer to dissect */ #define WSLUA_ARG_DissectorTable_try_PINFO 4 /* The packet info */ #define WSLUA_ARG_DissectorTable_try_TREE 5 /* The tree on which to add the protocol items */ DissectorTable dt = checkDissectorTable(L,1); Tvb tvb = checkTvb(L,WSLUA_ARG_DissectorTable_try_TVB); Pinfo pinfo = checkPinfo(L,WSLUA_ARG_DissectorTable_try_PINFO); TreeItem ti = checkTreeItem(L,WSLUA_ARG_DissectorTable_try_TREE); ftenum_t type; gboolean handled = FALSE; const gchar *volatile error = NULL; if (! (dt && tvb && tvb->ws_tvb && pinfo && ti) ) return 0; type = get_dissector_table_selector_type(dt->name); TRY { if (type == FT_STRING) { const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_try_PATTERN); if (!pattern) handled = TRUE; else if (dissector_try_string(dt->table,pattern,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree, NULL)) handled = TRUE; } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { int port = luaL_checkint(L, WSLUA_ARG_DissectorTable_try_PATTERN); if (dissector_try_uint(dt->table,port,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree)) handled = TRUE; } else { luaL_error(L,"No such type of dissector_table"); } if (!handled) call_dissector(lua_data_handle,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree); /* XXX Are we sure about this??? is this the right/only thing to catch */ } CATCH_NONFATAL_ERRORS { show_exception(tvb->ws_tvb, pinfo->ws_pinfo, ti->tree, EXCEPT_CODE, GET_MESSAGE); error = "Malformed frame"; } ENDTRY; if (error) { WSLUA_ERROR(DissectorTable_try,error); } return 0; } WSLUA_METHOD DissectorTable_get_dissector (lua_State *L) { /* Try to obtain a dissector from a table. */ #define WSLUA_ARG_DissectorTable_try_PATTERN 2 /* The pattern to be matched (either an integer or a string depending on the table's type). */ DissectorTable dt = checkDissectorTable(L,1); ftenum_t type; dissector_handle_t handle = lua_data_handle; if (!dt) return 0; type = get_dissector_table_selector_type(dt->name); if (type == FT_STRING) { const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_try_PATTERN); if (!pattern) WSLUA_ARG_ERROR(DissectorTable_try,PATTERN,"must be a string"); handle = dissector_get_string_handle(dt->table,pattern); } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { int port = luaL_checkint(L, WSLUA_ARG_DissectorTable_try_PATTERN); handle = dissector_get_uint_handle(dt->table,port); } if (handle) { pushDissector(L,handle); WSLUA_RETURN(1); /* The dissector handle if found */ } else { lua_pushnil(L); WSLUA_RETURN(1); /* nil if not found */ } } /* XXX It would be nice to iterate and print which dissectors it has */ WSLUA_METAMETHOD DissectorTable__tostring(lua_State* L) { /* Gets some debug information about the DissectorTable */ DissectorTable dt = checkDissectorTable(L,1); GString* s; ftenum_t type; if (!dt) return 0; type = get_dissector_table_selector_type(dt->name); s = g_string_new("DissectorTable "); switch(type) { case FT_STRING: { g_string_append_printf(s,"%s String:\n",dt->name); break; } case FT_UINT8: case FT_UINT16: case FT_UINT24: case FT_UINT32: { int base = get_dissector_table_base(dt->name); g_string_append_printf(s,"%s Integer(%i):\n",dt->name,base); break; } default: luaL_error(L,"Strange table type"); } lua_pushstring(L,s->str); g_string_free(s,TRUE); WSLUA_RETURN(1); /* A string of debug information about the DissectorTable */ } /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ static int DissectorTable__gc(lua_State* L _U_) { /* do NOT free DissectorTable */ return 0; } WSLUA_METHODS DissectorTable_methods[] = { WSLUA_CLASS_FNREG(DissectorTable,new), WSLUA_CLASS_FNREG(DissectorTable,get), WSLUA_CLASS_FNREG(DissectorTable,add), WSLUA_CLASS_FNREG(DissectorTable,set), WSLUA_CLASS_FNREG(DissectorTable,remove), WSLUA_CLASS_FNREG(DissectorTable,remove_all), WSLUA_CLASS_FNREG(DissectorTable,try), WSLUA_CLASS_FNREG(DissectorTable,get_dissector), { NULL, NULL } }; WSLUA_META DissectorTable_meta[] = { WSLUA_CLASS_MTREG(DissectorTable,tostring), { NULL, NULL } }; int DissectorTable_register(lua_State* L) { WSLUA_REGISTER_CLASS(DissectorTable); return 0; }