Add a inflateEnd() call to free up the stream in the re-init block.
[obnox/wireshark/wip.git] / epan / wslua / wslua_proto.c
1 /*
2  * lua_proto.c
3  *
4  * wireshark's interface to the Lua Programming Language
5  *
6  * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
7  * (c) 2007, Tamas Regos <tamas.regos@ericsson.com>
8  *
9  * $Id$
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 /* WSLUA_MODULE Proto functions for writing dissectors */
31
32 #include "wslua.h"
33
34 WSLUA_CLASS_DEFINE(Pref,NOP,NOP); /* A preference of a Protocol. */
35
36 static range_t* get_range(lua_State *L, int idx_r, int idx_m)
37 {
38   static range_t *ret;
39     range_convert_str(&ret,g_strdup(lua_tostring(L, idx_r)),(guint32)lua_tonumber(L, idx_m));
40   return ret;
41 }
42
43 static enum_val_t* get_enum(lua_State *L, int idx)
44 {
45   double seq;
46   const gchar *str1, *str2;
47   enum_val_t *ret, last = {NULL, NULL, -1};
48   GArray* es = g_array_new(TRUE,TRUE,sizeof(enum_val_t));
49
50   luaL_checktype(L, idx, LUA_TTABLE);
51   lua_pushnil(L);  /* first key */
52
53   while (lua_next(L, idx)) {
54     enum_val_t e = {NULL, NULL, -1};
55
56     luaL_checktype(L, -1, LUA_TTABLE);
57     lua_pushnil(L);
58     lua_next(L, -2);
59     if (! lua_isstring(L,-1)) {
60         luaL_argerror(L,idx,"First value of an enum table must be string");
61         g_array_free(es,TRUE);
62         return NULL;
63     }
64     str1 = lua_tostring(L, -1);
65     
66     lua_pop(L, 1);
67     lua_next(L, -2);
68     if (! lua_isstring(L,-1)) {
69         luaL_argerror(L,idx,"Second value of an enum table must be string");
70         g_array_free(es,TRUE);
71         return NULL;
72     }
73     str2 = lua_tostring(L, -1);
74     
75     lua_pop(L, 1);
76     lua_next(L, -2);
77     if (! lua_isnumber(L,-1)) {
78         luaL_argerror(L,idx,"Third value of an enum table must be an integer");
79         g_array_free(es,TRUE);
80         return NULL;
81     }
82     seq = lua_tonumber(L, -1);
83
84     e.name = g_strdup(str1);
85     e.description = g_strdup(str2);
86     e.value = (guint32)seq;
87     
88     g_array_append_val(es,e);
89     
90     lua_pop(L, 3);  /* removes 'value'; keeps 'key' for next iteration */
91   }
92   
93   g_array_append_val(es,last);
94   
95   ret = (enum_val_t*)es->data;
96
97   g_array_free(es,FALSE);
98
99   return ret;
100 }
101
102 static int new_pref(lua_State* L, pref_type_t type) {
103     const gchar* label = luaL_optstring(L,1,NULL);
104     const gchar* descr = luaL_optstring(L,3,"");
105     
106     Pref pref = g_malloc(sizeof(wslua_pref_t));
107     pref->name = NULL;
108     pref->label = label ? g_strdup(label) : NULL;
109     pref->desc = g_strdup(descr);
110     pref->type = type;
111     pref->next = NULL;
112     pref->proto = NULL;
113     
114     switch(type) {
115         case PREF_BOOL: {
116             gboolean def = lua_toboolean(L,2);
117             pref->value.b = def;
118             break;
119         }
120         case PREF_UINT: {
121             guint32 def = (guint32)luaL_optnumber(L,2,0);
122             pref->value.u = def;
123             break;
124         }
125         case PREF_STRING: {
126             gchar* def = g_strdup(luaL_optstring(L,2,""));
127             pref->value.s = def;
128             break;
129         }
130         case PREF_ENUM: {
131             guint32 def = (guint32)luaL_optnumber(L,2,0);
132             enum_val_t *enum_val = get_enum(L,4);
133             gboolean radio = lua_toboolean(L,5);
134             pref->value.e = def;
135             pref->info.enum_info.enumvals = enum_val;
136             pref->info.enum_info.radio_buttons = radio;
137             break;
138         }
139         case PREF_RANGE: {
140             range_t *range = get_range(L,4,5);
141             guint32 max = (guint32)luaL_optnumber(L,5,0);
142             pref->value.r = range;
143             pref->info.max_value = max;
144             break;
145         }
146         case PREF_STATIC_TEXT: {
147             /* This is just a static text. */
148             break;
149         }
150         default:
151             g_assert_not_reached();
152             break;
153
154     }
155
156     pushPref(L,pref);
157     return 1;
158     
159 }
160
161 WSLUA_CONSTRUCTOR Pref_bool(lua_State* L) {
162         /*
163          * Creates a boolean preference to be added to a Protocol's prefs table.
164          */
165 #define WSLUA_ARG_Pref_bool_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
166 #define WSLUA_ARG_Pref_bool_DEFAULT 2 /* The default value for this preference */
167 #define WSLUA_ARG_Pref_bool_DESCR 3 /* A description of what this preference is */
168     return new_pref(L,PREF_BOOL);
169 }
170
171 WSLUA_CONSTRUCTOR Pref_uint(lua_State* L) {
172         /*
173          * Creates an (unsigned) integer preference to be added to a Protocol's prefs table.
174          */
175 #define WSLUA_ARG_Pref_uint_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
176 #define WSLUA_ARG_Pref_uint_DEFAULT 2 /* The default value for this preference */
177 #define WSLUA_ARG_Pref_uint_DESCR 3 /* A description of what this preference is */
178     return new_pref(L,PREF_UINT);
179 }
180
181 WSLUA_CONSTRUCTOR Pref_string(lua_State* L) {
182         /*
183          * Creates a string preference to be added to a Protocol's prefs table.
184          */
185 #define WSLUA_ARG_Pref_string_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
186 #define WSLUA_ARG_Pref_string_DEFAULT 2 /* The default value for this preference */
187 #define WSLUA_ARG_Pref_string_DESCR 3 /* A description of what this preference is */
188     return new_pref(L,PREF_STRING);
189 }
190
191 WSLUA_CONSTRUCTOR Pref_enum(lua_State* L) {
192         /*
193          * Creates an enum preference to be added to a Protocol's prefs table.
194          */
195 #define WSLUA_ARG_Pref_enum_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
196 #define WSLUA_ARG_Pref_enum_DEFAULT 2 /* The default value for this preference */
197 #define WSLUA_ARG_Pref_enum_DESCR 3 /* A description of what this preference is */
198 #define WSLUA_ARG_Pref_enum_ENUM 4 /* enum */
199 #define WSLUA_ARG_Pref_enum_RADIO 5 /* radio_button or combobox */
200     return new_pref(L,PREF_ENUM);
201 }
202
203 WSLUA_CONSTRUCTOR Pref_range(lua_State* L) {
204         /*
205          * Creates a range preference to be added to a Protocol's prefs table.
206          */
207 #define WSLUA_ARG_Pref_enum_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
208 #define WSLUA_ARG_Pref_enum_DEFAULT 2 /* The default value for this preference */
209 #define WSLUA_ARG_Pref_enum_DESCR 3 /* A description of what this preference is */
210 #define WSLUA_ARG_Pref_enum_RANGE 4 /* The range */
211 #define WSLUA_ARG_Pref_enum_MAX 5 /* The maximum value */
212     return new_pref(L,PREF_RANGE);
213 }
214
215 WSLUA_CONSTRUCTOR Pref_stext(lua_State* L) {
216         /*
217          * Creates a static text preference to be added to a Protocol's prefs table.
218          */
219 #define WSLUA_ARG_Pref_enum_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
220 #define WSLUA_ARG_Pref_enum_TEXT 2 /* The static text */
221     return new_pref(L,PREF_STATIC_TEXT);
222 }
223
224 static int Pref_gc(lua_State* L) {
225     Pref pref = checkPref(L,1);
226     
227     if (pref && ! pref->name) {
228         if (pref->label) g_free(pref->label);
229         if (pref->desc) g_free(pref->desc);
230         if (pref->type == PREF_STRING) g_free((void*)pref->value.s);
231         g_free(pref);
232     }
233     
234     return 0;
235 }
236
237 WSLUA_METHODS Pref_methods[] = {
238     {"bool",   Pref_bool},
239     {"uint",   Pref_uint},
240     {"string", Pref_string},
241     {"enum",   Pref_enum},
242     {"range",  Pref_range},
243     {"statictext",  Pref_stext},
244     {0,0}
245 };
246
247 WSLUA_META Pref_meta[] = {
248     {"__gc",   Pref_gc},
249     {0,0}
250 };
251
252
253 WSLUA_REGISTER Pref_register(lua_State* L) {
254         WSLUA_REGISTER_CLASS(Pref);
255     return 1;
256 }
257
258 WSLUA_CLASS_DEFINE(Prefs,NOP,NOP); /* The table of preferences of a protocol */
259
260 WSLUA_METAMETHOD Prefs__newindex(lua_State* L) {
261         /* creates a new preference */
262 #define WSLUA_ARG_Prefs__newindex_NAME 2 /* The abbreviation of this preference */
263 #define WSLUA_ARG_Prefs__newindex_PREF 3 /* A valid but still unassigned Pref object */
264
265     Pref prefs = checkPrefs(L,1);
266     const gchar* name = luaL_checkstring(L,WSLUA_ARG_Prefs__newindex_NAME);
267     Pref pref = checkPref(L,WSLUA_ARG_Prefs__newindex_PREF);
268     Pref p;
269
270         if (! prefs ) return 0;
271
272         if (! name ) 
273                 WSLUA_ARG_ERROR(Prefs__newindex,NAME,"must be a string");
274
275         if (! pref )
276                 WSLUA_ARG_ERROR(Prefs__newindex,PREF,"must be a valid Pref");
277     
278     if (pref->name)
279         WSLUA_ARG_ERROR(Prefs__newindex,NAME,"cannot change existing preference");
280
281         if (pref->proto)
282                 WSLUA_ARG_ERROR(Prefs__newindex,PREF,"cannot be added to more than one protocol");
283
284     p = prefs;
285     
286     do {
287         if ( p->name && g_str_equal(p->name,name) ) {
288             luaL_error(L,"a preference named %s exists already",name);
289             return 0;
290         }
291         
292         if ( ! p->next) {
293             p->next = pref;
294             
295             pref->name = g_strdup(name);
296             
297             if (!pref->label)
298                 pref->label = g_strdup(name);
299
300             if (!prefs->proto->prefs_module) {
301                 prefs->proto->prefs_module = prefs_register_protocol(prefs->proto->hfid, NULL);
302    
303             }
304             
305             switch(pref->type) {
306                 case PREF_BOOL: 
307                     prefs_register_bool_preference(prefs->proto->prefs_module,
308                                                    pref->name,
309                                                    pref->label,
310                                                    pref->desc,
311                                                    &(pref->value.b));
312                     break;
313                 case PREF_UINT:
314                     prefs_register_uint_preference(prefs->proto->prefs_module,
315                                                    pref->name,
316                                                    pref->label,
317                                                    pref->desc,
318                                                    10,
319                                                    &(pref->value.u));
320                     break;
321                 case PREF_STRING:
322                     prefs_register_string_preference(prefs->proto->prefs_module, 
323                                                      pref->name,
324                                                      pref->label,
325                                                      pref->desc,
326                                                      &(pref->value.s));
327                     break;
328                 case PREF_ENUM:
329                     prefs_register_enum_preference(prefs->proto->prefs_module, 
330                                                      pref->name,
331                                                      pref->label,
332                                                      pref->desc,
333                                                      &(pref->value.e),
334                                                      pref->info.enum_info.enumvals,
335                                                      pref->info.enum_info.radio_buttons);
336                     break;
337                 case PREF_RANGE:
338                     prefs_register_range_preference(prefs->proto->prefs_module, 
339                                                      pref->name,
340                                                      pref->label,
341                                                      pref->desc,
342                                                      &(pref->value.r),
343                                                      pref->info.max_value);
344                     break;
345                 case PREF_STATIC_TEXT:
346                     prefs_register_static_text_preference(prefs->proto->prefs_module, 
347                                                      pref->name,
348                                                      pref->label,
349                                                      "This is just a static text");
350                     break;
351                 default:
352                     WSLUA_ERROR(Prefs__newindex,"unknow Pref type");
353             }
354             
355             pref->proto = p->proto;
356             
357             WSLUA_RETURN(0);
358         }
359     } while (( p = p->next ));
360
361         luaL_error(L,"this should not happen!");
362     
363     WSLUA_RETURN(0);
364 }
365
366 WSLUA_METAMETHOD Prefs__index(lua_State* L) {
367         /* get the value of a preference setting */
368 #define WSLUA_ARG_Prefs__index_NAME 2 /* The abbreviation of this preference  */
369
370     Pref prefs = checkPrefs(L,1);
371     const gchar* name = luaL_checkstring(L,2);
372     
373     if (! ( name && prefs ) ) return 0;
374     
375     prefs = prefs->next;
376     
377     do {
378         if ( g_str_equal(prefs->name,name) ) {
379             switch (prefs->type) {
380                 case PREF_BOOL: lua_pushboolean(L, prefs->value.b); break;
381                 case PREF_UINT: lua_pushnumber(L,(lua_Number)prefs->value.u); break;
382                 case PREF_STRING: lua_pushstring(L,prefs->value.s); break;
383                 case PREF_ENUM: lua_pushnumber(L,(lua_Number)prefs->value.e); break;
384                 case PREF_RANGE: lua_pushstring(L,range_convert_range(prefs->value.r)); break;
385                 default: WSLUA_ERROR(Prefs__index,"unknow Pref type");
386             }
387             WSLUA_RETURN(1); /* the current value of the preference */
388         }
389     } while (( prefs = prefs->next ));
390
391     WSLUA_ARG_ERROR(Prefs__index,NAME,"no preference named like this");
392     WSLUA_RETURN(0);
393 }
394
395 WSLUA_META Prefs_meta[] = {
396     {"__newindex",   Prefs__newindex},
397     {"__index",   Prefs__index},
398     {0,0}
399 };
400
401 WSLUA_REGISTER Prefs_register(lua_State* L) {
402         WSLUA_REGISTER_META(Prefs);
403     return 1;
404 }
405
406
407 WSLUA_CLASS_DEFINE(ProtoField,FAIL_ON_NULL("null ProtoField"),NOP);
408 /*
409  * A Protocol field (to be used when adding items to the dissection tree)
410  */
411
412 static const wslua_ft_types_t ftenums[] = {
413 {"FT_BOOLEAN",FT_BOOLEAN},
414 {"FT_UINT8",FT_UINT8},
415 {"FT_UINT16",FT_UINT16},
416 {"FT_UINT24",FT_UINT24},
417 {"FT_UINT32",FT_UINT32},
418 {"FT_UINT64",FT_UINT64},
419 {"FT_INT8",FT_INT8},
420 {"FT_INT16",FT_INT16},
421 {"FT_INT24",FT_INT24},
422 {"FT_INT32",FT_INT32},
423 {"FT_INT64",FT_INT64},
424 {"FT_FLOAT",FT_FLOAT},
425 {"FT_DOUBLE",FT_DOUBLE},
426 {"FT_STRING",FT_STRING},
427 {"FT_STRINGZ",FT_STRINGZ},
428 {"FT_ETHER",FT_ETHER},
429 {"FT_BYTES",FT_BYTES},
430 {"FT_UINT_BYTES",FT_UINT_BYTES},
431 {"FT_IPv4",FT_IPv4},
432 {"FT_IPv6",FT_IPv6},
433 {"FT_IPXNET",FT_IPXNET},
434 {"FT_FRAMENUM",FT_FRAMENUM},
435 {"FT_GUID",FT_GUID},
436 {"FT_OID",FT_OID},
437 {NULL,FT_NONE}
438 };
439
440 static enum ftenum get_ftenum(const gchar* type) {
441     const wslua_ft_types_t* ts;
442     for (ts = ftenums; ts->str; ts++) {
443         if ( g_str_equal(ts->str,type) ) {
444             return ts->id;
445         }
446     }
447     
448     return FT_NONE;
449 }
450
451 static const gchar* ftenum_to_string(enum ftenum ft) {
452     const wslua_ft_types_t* ts;
453     for (ts = ftenums; ts->str; ts++) {
454         if ( ts->id == ft ) {
455             return ts->str;
456         }
457     }
458     
459     return NULL;
460 }
461
462 struct base_display_string_t {
463     const gchar* str;
464     base_display_e base;
465 };
466
467 static const struct base_display_string_t base_displays[] = {
468         { "BASE_NONE", BASE_NONE},
469         {"BASE_DEC", BASE_DEC},
470         {"BASE_HEX", BASE_HEX},
471         {"BASE_OCT", BASE_OCT},
472         {"BASE_DEC_HEX", BASE_DEC_HEX},
473         {"BASE_HEX_DEC", BASE_HEX_DEC},
474         {NULL,0}
475 };
476
477 static const gchar* base_to_string(base_display_e base) {
478     const struct base_display_string_t* b;
479     for (b=base_displays;b->str;b++) {
480         if ( base == b->base)
481             return b->str;
482     }
483     return NULL;
484 }
485
486 static base_display_e string_to_base(const gchar* str) {
487     const struct base_display_string_t* b;
488     for (b=base_displays;b->str;b++) {
489         if ( g_str_equal(str,b->str))
490             return b->base;
491     }
492     return BASE_NONE;
493 }
494
495 static value_string* value_string_from_table(lua_State* L, int idx) {
496     GArray* vs = g_array_new(TRUE,TRUE,sizeof(value_string));
497     value_string* ret;
498     
499     if(lua_isnil(L,idx)) {
500             return NULL;
501     } else if (!lua_istable(L,idx)) {
502         luaL_argerror(L,idx,"must be a table");
503         g_array_free(vs,TRUE);
504         return NULL;
505     }
506     
507     lua_pushnil(L);
508     
509     while (lua_next(L, idx) != 0) {
510         value_string v = {0,NULL};
511         
512         if (! lua_isnumber(L,-2)) {
513             luaL_argerror(L,idx,"All keys of a table used as vaalue_string must be integers");
514             g_array_free(vs,TRUE);
515             return NULL;
516         }
517         
518         if (! lua_isstring(L,-1)) {
519             luaL_argerror(L,idx,"All values of a table used as vaalue_string must be strings");
520             g_array_free(vs,TRUE);
521             return NULL;
522         }
523         
524         v.value = (guint32)lua_tonumber(L,-2);
525         v.strptr = g_strdup(lua_tostring(L,-1));
526         
527         g_array_append_val(vs,v);
528         
529         lua_pop(L, 1);
530     }
531     
532     lua_pop(L, 1);
533     
534     ret = (value_string*)vs->data;
535     
536     g_array_free(vs,FALSE);
537
538     return ret;
539     
540 }    
541
542 WSLUA_CONSTRUCTOR ProtoField_new(lua_State* L) { /* Creates a new field to be used in a protocol. */
543 #define WSLUA_ARG_ProtoField_new_NAME 1 /* Actual name of the field (the string that appears in the tree).  */
544 #define WSLUA_ARG_ProtoField_new_ABBR 2 /* Filter name of the field (the string that is used in filters).  */
545 #define WSLUA_ARG_ProtoField_new_TYPE 3 /* Field Type (FT_*).  */
546 #define WSLUA_OPTARG_ProtoField_new_VALUESTRING 4 /* a ValueString object. */
547 #define WSLUA_OPTARG_ProtoField_new_BASE 5 /* The representation BASE_*. */
548 #define WSLUA_OPTARG_ProtoField_new_MASK 6 /* the bitmask to be used.  */
549 #define WSLUA_OPTARG_ProtoField_new_DESCR 7 /* The description of the field.  */
550         
551     ProtoField f = g_malloc(sizeof(wslua_field_t));
552     value_string* vs;
553     
554     /* will be using -2 as far as the field has not been added to an array then it will turn -1 */
555     f->hfid = -2;
556         f->ett = -1;
557     f->name = g_strdup(luaL_checkstring(L,WSLUA_ARG_ProtoField_new_NAME));
558     f->abbr = g_strdup(luaL_checkstring(L,WSLUA_ARG_ProtoField_new_ABBR));
559     f->type = get_ftenum(luaL_checkstring(L,WSLUA_ARG_ProtoField_new_TYPE));
560     
561         /*XXX do it better*/
562     if (f->type == FT_NONE) { 
563         WSLUA_ARG_ERROR(ProtoField_new,TYPE,"invalid FT_type");
564         return 0;
565     }
566     
567     if (! lua_isnil(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING) ) {
568         vs = value_string_from_table(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING);
569         
570         if (vs) {
571             f->vs = vs;
572         } else {
573             g_free(f);
574             return 0;
575         }
576         
577         
578     } else {
579         f->vs = NULL;
580     }
581     
582     /* XXX: need BASE_ERROR */
583     f->base = string_to_base(luaL_optstring(L, WSLUA_OPTARG_ProtoField_new_BASE, "BASE_NONE"));
584     f->mask = luaL_optint(L, WSLUA_OPTARG_ProtoField_new_MASK, 0x0);
585     f->blob = g_strdup(luaL_optstring(L,WSLUA_OPTARG_ProtoField_new_DESCR,""));
586     
587     pushProtoField(L,f);
588     
589     WSLUA_RETURN(1); /* The newly created ProtoField object */ 
590 }
591
592
593 static int ProtoField_integer(lua_State* L, enum ftenum type) {
594     ProtoField f = g_malloc(sizeof(wslua_field_t));
595         const gchar* abbr = luaL_checkstring(L,1);
596     const gchar* name = luaL_optstring(L,2,abbr);
597     base_display_e base = luaL_optint(L, 3, BASE_DEC);
598     value_string* vs = (lua_gettop(L) > 3) ? value_string_from_table(L,4) : NULL;
599     int mask = luaL_optint(L, 5, 0x0);
600     const gchar* blob = luaL_optstring(L,6,"");
601
602     if (base < BASE_DEC || base > BASE_HEX_DEC) {
603         luaL_argerror(L,2,"Base must be either BASE_DEC, BASE_HEX, BASE_OCT,"
604                       " BASE_DEC_HEX, BASE_DEC_HEX or BASE_HEX_DEC");
605         return 0;
606     }
607
608     f->hfid = -2;
609         f->ett = -1;
610     f->name = g_strdup(name);
611     f->abbr = g_strdup(abbr);
612     f->type = type;
613     f->vs = vs;
614     f->base = base;
615     f->mask = mask;
616     f->blob = g_strdup(blob);
617     
618     
619     pushProtoField(L,f);
620     
621     return 1;
622 }
623
624 #define PROTOFIELD_INTEGER(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_integer(L,FT); }
625 /* _WSLUA_CONSTRUCTOR_ ProtoField_uint8 */
626 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
627 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
628 /* WSLUA_OPTARG_Protofield_uint8_BASE one of base.DEC, base.HEX or base.OCT */
629 /* WSLUA_OPTARG_Protofield_uint8_VALUESTRING a table containing the text that corresponds to the values  */
630 /* WSLUA_OPTARG_Protofield_uint8_MASK integer mask of this field  */
631 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
632 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
633
634 /* _WSLUA_CONSTRUCTOR_ ProtoField_uint16 */
635 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
636 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
637 /* WSLUA_OPTARG_Protofield_uint8_BASE one of base.DEC, base.HEX or base.OCT */
638 /* WSLUA_OPTARG_Protofield_uint8_VALUESTRING a table containing the text that corresponds to the values  */
639 /* WSLUA_OPTARG_Protofield_uint8_MASK integer mask of this field  */
640 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
641 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
642
643 /* _WSLUA_CONSTRUCTOR_ ProtoField_uint24 */
644 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
645 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
646 /* WSLUA_OPTARG_Protofield_uint8_BASE one of base.DEC, base.HEX or base.OCT */
647 /* WSLUA_OPTARG_Protofield_uint8_VALUESTRING a table containing the text that corresponds to the values  */
648 /* WSLUA_OPTARG_Protofield_uint8_MASK integer mask of this field  */
649 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
650 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
651
652 /* _WSLUA_CONSTRUCTOR_ ProtoField_uint32 */
653 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
654 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
655 /* WSLUA_OPTARG_Protofield_uint8_BASE one of base.DEC, base.HEX or base.OCT */
656 /* WSLUA_OPTARG_Protofield_uint8_VALUESTRING a table containing the text that corresponds to the values  */
657 /* WSLUA_OPTARG_Protofield_uint8_MASK integer mask of this field  */
658 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
659 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
660
661 /* _WSLUA_CONSTRUCTOR_ ProtoField_uint64 */
662 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
663 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
664 /* WSLUA_OPTARG_Protofield_uint8_BASE one of base.DEC, base.HEX or base.OCT */
665 /* WSLUA_OPTARG_Protofield_uint8_VALUESTRING a table containing the text that corresponds to the values  */
666 /* WSLUA_OPTARG_Protofield_uint8_MASK integer mask of this field  */
667 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
668 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
669
670 /* _WSLUA_CONSTRUCTOR_ ProtoField_int8 */
671 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
672 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
673 /* WSLUA_OPTARG_Protofield_uint8_BASE one of base.DEC, base.HEX or base.OCT */
674 /* WSLUA_OPTARG_Protofield_uint8_VALUESTRING a table containing the text that corresponds to the values  */
675 /* WSLUA_OPTARG_Protofield_uint8_MASK integer mask of this field  */
676 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
677 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
678
679 /* _WSLUA_CONSTRUCTOR_ ProtoField_int16 */
680 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
681 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
682 /* WSLUA_OPTARG_Protofield_uint8_BASE one of base.DEC, base.HEX or base.OCT */
683 /* WSLUA_OPTARG_Protofield_uint8_VALUESTRING a table containing the text that corresponds to the values  */
684 /* WSLUA_OPTARG_Protofield_uint8_MASK integer mask of this field  */
685 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
686 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
687
688 /* _WSLUA_CONSTRUCTOR_ ProtoField_int24 */
689 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
690 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
691 /* WSLUA_OPTARG_Protofield_uint8_BASE one of base.DEC, base.HEX or base.OCT */
692 /* WSLUA_OPTARG_Protofield_uint8_VALUESTRING a table containing the text that corresponds to the values  */
693 /* WSLUA_OPTARG_Protofield_uint8_MASK integer mask of this field  */
694 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
695 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
696
697 /* _WSLUA_CONSTRUCTOR_ ProtoField_int32 */
698 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
699 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
700 /* WSLUA_OPTARG_Protofield_uint8_BASE one of base.DEC, base.HEX or base.OCT */
701 /* WSLUA_OPTARG_Protofield_uint8_VALUESTRING a table containing the text that corresponds to the values  */
702 /* WSLUA_OPTARG_Protofield_uint8_MASK integer mask of this field  */
703 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
704 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
705
706 /* _WSLUA_CONSTRUCTOR_ ProtoField_int64 */
707 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
708 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
709 /* WSLUA_OPTARG_Protofield_uint8_BASE one of base.DEC, base.HEX or base.OCT */
710 /* WSLUA_OPTARG_Protofield_uint8_VALUESTRING a table containing the text that corresponds to the values  */
711 /* WSLUA_OPTARG_Protofield_uint8_MASK integer mask of this field  */
712 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
713 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
714
715 /* _WSLUA_CONSTRUCTOR_ ProtoField_framenum a frame number (for hyperlinks between frames) */
716 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
717 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
718 /* WSLUA_OPTARG_Protofield_uint8_BASE one of base.DEC, base.HEX or base.OCT */
719 /* WSLUA_OPTARG_Protofield_uint8_VALUESTRING a table containing the text that corresponds to the values  */
720 /* WSLUA_OPTARG_Protofield_uint8_MASK integer mask of this field  */
721 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
722 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
723
724 PROTOFIELD_INTEGER(uint8,FT_UINT8)
725 PROTOFIELD_INTEGER(uint16,FT_UINT16)
726 PROTOFIELD_INTEGER(uint24,FT_UINT24)
727 PROTOFIELD_INTEGER(uint32,FT_UINT32)
728 PROTOFIELD_INTEGER(uint64,FT_UINT64)
729 PROTOFIELD_INTEGER(int8,FT_INT8)
730 PROTOFIELD_INTEGER(int16,FT_INT8)
731 PROTOFIELD_INTEGER(int24,FT_INT8)
732 PROTOFIELD_INTEGER(int32,FT_INT8)
733 PROTOFIELD_INTEGER(int64,FT_INT8)
734 PROTOFIELD_INTEGER(framenum,FT_FRAMENUM)
735
736 static int ProtoField_other(lua_State* L,enum ftenum type) {
737     ProtoField f = g_malloc(sizeof(wslua_field_t));
738     const gchar* abbr = luaL_checkstring(L,1);
739     const gchar* name = luaL_optstring(L,2,abbr);
740     const gchar* blob = luaL_optstring(L,3,"");
741     
742     f->hfid = -2;
743         f->ett = -1;
744     f->name = g_strdup(name);
745     f->abbr = g_strdup(abbr);
746     f->type = type;
747     f->vs = NULL;
748     f->base = ( type == FT_FLOAT || type == FT_DOUBLE) ? BASE_DEC : BASE_NONE;
749     f->mask = 0;
750     f->blob = g_strdup(blob);
751     
752     pushProtoField(L,f);
753     
754     return 1;
755 }
756
757 #define PROTOFIELD_OTHER(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_other(L,FT); }
758 /* _WSLUA_CONSTRUCTOR_ ProtoField_ipv4 */
759 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
760 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
761 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
762 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
763
764 /* _WSLUA_CONSTRUCTOR_ ProtoField_ipv6 */
765 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
766 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
767 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
768 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
769
770 /* _WSLUA_CONSTRUCTOR_ ProtoField_ether */
771 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
772 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
773 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
774 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
775
776 /* _WSLUA_CONSTRUCTOR_ ProtoField_float */
777 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
778 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
779 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
780 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
781
782 /* _WSLUA_CONSTRUCTOR_ ProtoField_double */
783 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
784 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
785 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
786 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
787
788 /* _WSLUA_CONSTRUCTOR_ ProtoField_string */
789 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
790 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
791 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
792 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
793
794 /* _WSLUA_CONSTRUCTOR_ ProtoField_strigz */
795 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
796 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
797 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
798 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
799
800 /* _WSLUA_CONSTRUCTOR_ ProtoField_bytes */
801 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
802 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
803 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
804 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
805
806 /* _WSLUA_CONSTRUCTOR_ ProtoField_ubytes */
807 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
808 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
809 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
810 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
811
812 /* _WSLUA_CONSTRUCTOR_ ProtoField_guid */
813 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
814 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
815 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
816 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
817
818 /* _WSLUA_CONSTRUCTOR_ ProtoField_oid */
819 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
820 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
821 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
822 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
823
824 /* _WSLUA_CONSTRUCTOR_ ProtoField_bool */
825 /* WSLUA_ARG_Protofield_uint8_ABBR abbreviated name of the field (the string used in filters)  */
826 /* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree)  */
827 /* WSLUA_OPTARG_Protofield_uint8_DESC description of the field  */
828 /* _WSLUA_RETURNS_ a protofield item to be added to a ProtoFieldArray */
829
830 PROTOFIELD_OTHER(ipv4,FT_IPv4)
831 PROTOFIELD_OTHER(ipv6,FT_IPv6)
832 PROTOFIELD_OTHER(ipx,FT_IPXNET)
833 PROTOFIELD_OTHER(ether,FT_ETHER)
834 PROTOFIELD_OTHER(float,FT_FLOAT)
835 PROTOFIELD_OTHER(double,FT_DOUBLE)
836 PROTOFIELD_OTHER(string,FT_STRING)
837 PROTOFIELD_OTHER(stringz,FT_STRINGZ)
838 PROTOFIELD_OTHER(bytes,FT_BYTES)
839 PROTOFIELD_OTHER(ubytes,FT_UINT_BYTES)
840 PROTOFIELD_OTHER(guid,FT_GUID)
841 PROTOFIELD_OTHER(oid,FT_OID)
842
843 /* XXX: T/F strings */
844 PROTOFIELD_OTHER(bool,FT_BOOLEAN)
845
846
847 WSLUA_METAMETHOD ProtoField_tostring(lua_State* L) {
848         /* Returns a string w/ info about a protofiled (for debugging purposes) */
849     ProtoField f = checkProtoField(L,1);
850     gchar* s = g_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);
851     
852     lua_pushstring(L,s);
853     g_free(s);
854     
855     return 1;
856 }
857
858 static int ProtoField_gc(lua_State* L) {
859     ProtoField f = checkProtoField(L,1);
860
861     /*
862      * A garbage collector for ProtoFields makes little sense.
863      * Even if This cannot be used anymore because it has gone out of scope, 
864      * we can destroy the ProtoField only if it is not part of a ProtoFieldArray,
865      * if it actualy belongs to one we need to preserve it as it is pointed by
866      * a field array that may be registered afterwards causing a crash or memory corruption.
867      */
868     
869     if (!f) {
870         luaL_argerror(L,1,"BUG: ProtoField_gc called for something not ProtoField");
871         /* g_assert() ?? */
872     } else if (f->hfid == -2) {
873         g_free(f->name);
874         g_free(f->abbr);
875         g_free(f->blob);
876         g_free(f);
877     }
878     
879     return 0;
880 }
881
882
883 static const luaL_reg ProtoField_methods[] = {
884     {"new",   ProtoField_new},
885     {"uint8",ProtoField_uint8},
886     {"uint16",ProtoField_uint16},
887     {"uint24",ProtoField_uint24},
888     {"uint32",ProtoField_uint32},
889     {"uint64",ProtoField_uint64},
890     {"int8",ProtoField_int8},
891     {"int16",ProtoField_int16},
892     {"int24",ProtoField_int24},
893     {"int32",ProtoField_int32},
894     {"int64",ProtoField_int64},
895     {"framenum",ProtoField_framenum},
896     {"ipv4",ProtoField_ipv4},
897     {"ipv6",ProtoField_ipv6},
898     {"ipx",ProtoField_ipx},
899     {"ether",ProtoField_ether},
900     {"bool",ProtoField_bool},
901     {"float",ProtoField_float},
902     {"double",ProtoField_double},
903     {"string",ProtoField_string},
904     {"stringz",ProtoField_stringz},
905     {"bytes",ProtoField_bytes},
906     {"ubytes",ProtoField_ubytes},
907     {"guid",ProtoField_guid},
908     {"oid",ProtoField_oid},
909     {0,0}
910 };
911
912 static const luaL_reg ProtoField_meta[] = {
913     {"__gc", ProtoField_gc },
914     {"__tostring", ProtoField_tostring },
915     {0, 0}
916 };
917
918 int ProtoField_register(lua_State* L) {
919     
920         WSLUA_REGISTER_CLASS(ProtoField);
921         
922     return 1;
923 }
924
925 WSLUA_CLASS_DEFINE(Proto,NOP,NOP);
926 /*
927   A new protocol in wireshark. Protocols have more uses, the main one is to dissect
928   a protocol. But they can be just dummies used to register preferences for
929   other purposes.
930  */
931
932 static int protocols_table_ref = LUA_NOREF;
933
934 WSLUA_CONSTRUCTOR Proto_new(lua_State* L) {
935 #define WSLUA_ARG_Proto_new_NAME 1 /* The name of the protocol */
936 #define WSLUA_ARG_Proto_new_DESC 1 /* A Long Text description of the protocol (usually lowercase) */
937     const gchar* name = luaL_checkstring(L,1);
938     const gchar* desc = luaL_checkstring(L,2);
939     
940     if ( name ) {
941                 gchar* loname = ep_strdup(name);
942                 g_strdown(loname);
943         if ( proto_get_id_by_filter_name(loname) > 0 ) { 
944             WSLUA_ARG_ERROR(Proto_new,NAME,"there cannot be two protocols with the same name");
945         } else {
946             Proto proto = g_malloc(sizeof(wslua_proto_t));
947                         gchar* loname = g_strdup(name);
948                         gchar* hiname = g_strdup(name);
949                         
950                         g_strdown(loname);
951                         g_strup(hiname);
952
953             proto->name = hiname;
954             proto->desc = g_strdup(desc);
955                         proto->hfid = proto_register_protocol(proto->desc,hiname,loname);
956                         proto->ett = -1;
957                         proto->is_postdissector = FALSE;
958                         
959                         lua_newtable (L);
960                         proto->fields = luaL_ref(L, LUA_REGISTRYINDEX);
961                         
962             proto->prefs.name = NULL;
963             proto->prefs.label = NULL;
964             proto->prefs.desc = NULL;
965             proto->prefs.value.u = 0;
966             proto->prefs.next = NULL;
967             proto->prefs.proto = proto;
968                         
969             proto->prefs_module = NULL;
970             proto->handle = NULL;
971                                 
972                         lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref);
973
974                         lua_pushstring(L,loname);
975                         pushProto(L,proto);
976
977                         lua_settable(L, -3);
978                         
979                         pushProto(L,proto);
980                         
981                         WSLUA_RETURN(1); /* The newly created protocol */
982         }
983      } else {
984         WSLUA_ARG_ERROR(Proto_new,NAME,"must be a string");
985      }
986
987         return 0;
988 }
989
990
991
992 static int Proto_tostring(lua_State* L) { 
993     Proto proto = checkProto(L,1);
994     gchar* s;
995     
996     if (!proto) return 0;
997     
998     s = g_strdup_printf("Proto: %s",proto->name);
999     lua_pushstring(L,s);
1000     g_free(s);
1001     
1002     return 1;
1003 }
1004
1005 WSLUA_FUNCTION wslua_register_postdissector(lua_State* L) {
1006         /* make a protocol (with a dissector) a postdissector. It will be called for every frame after dissection */
1007 #define WSLUA_ARG_register_postdissector_PROTO 1 /* the protocol to be used as postdissector */
1008     Proto proto = checkProto(L,1);
1009     if (!proto) return 0;
1010     
1011     if(!proto->is_postdissector) {
1012         if (! proto->handle) {
1013             proto->handle = new_create_dissector_handle(dissect_lua, proto->hfid);
1014         }
1015         
1016         register_postdissector(proto->handle);
1017     } else {
1018         luaL_argerror(L,1,"this protocol is already registered as postdissector");
1019     }
1020     
1021     return 0;
1022 }
1023
1024
1025 static int Proto_get_dissector(lua_State* L) { 
1026     Proto proto = toProto(L,1);
1027     
1028     if (proto->handle) {
1029         pushDissector(L,proto->handle);
1030         return 1;
1031     } else {
1032         luaL_error(L,"The protocol hasn't been registered yet");
1033         return 0;
1034     }
1035 }
1036
1037
1038 static int Proto_set_dissector(lua_State* L) { 
1039     Proto proto = toProto(L,1);
1040
1041         if (lua_isfunction(L,3)) {
1042         /* insert the dissector into the dissectors table */
1043                 gchar* loname = ep_strdup(proto->name);
1044                 g_strdown(loname);
1045
1046         lua_rawgeti(L, LUA_REGISTRYINDEX, lua_dissectors_table_ref);
1047         lua_replace(L, 1);
1048         lua_pushstring(L,proto->name);
1049         lua_replace(L, 2);
1050         lua_settable(L,1);
1051         
1052         proto->handle = new_create_dissector_handle(dissect_lua, proto->hfid);
1053         
1054         new_register_dissector(loname, dissect_lua, proto->hfid);
1055                 
1056         return 0;
1057     } else {
1058         luaL_argerror(L,3,"The dissector of a protocol must be a function");
1059         return 0;
1060     }
1061 }
1062
1063 static int Proto_get_prefs(lua_State* L) { 
1064     Proto proto = toProto(L,1);
1065     
1066     pushPrefs(L,&proto->prefs);
1067     return 1;
1068 }
1069
1070 static int Proto_set_init(lua_State* L) { 
1071     Proto proto = toProto(L,1);
1072     
1073     if (lua_isfunction(L,3)) {
1074         /* insert the dissector into the dissectors table */
1075         lua_pushstring(L, WSLUA_INIT_ROUTINES);
1076         lua_gettable(L, LUA_GLOBALSINDEX);
1077         lua_replace(L, 1);
1078         lua_pushstring(L,proto->name);
1079         lua_replace(L, 2);
1080         lua_settable(L,1);
1081         
1082         return 0;
1083     }  else {
1084         luaL_argerror(L,3,"The initializer of a protocol must be a function");
1085         return 0;
1086     } 
1087 }
1088
1089 static int Proto_get_name(lua_State* L) { 
1090     Proto proto = toProto(L,1);
1091
1092     lua_pushstring(L,proto->name);
1093     return 1;
1094 }
1095
1096
1097 static int Proto_get_fields(lua_State* L) { 
1098     Proto proto = toProto(L,1);
1099     lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields);
1100     return 1;
1101 }
1102
1103 void wslua_print_stack(char* s, lua_State* L) {
1104         int i;
1105         
1106         for (i=1;i<=lua_gettop(L);i++) {
1107                 printf("%s-%i: %s\n",s,i,lua_typename (L,lua_type(L, i)));
1108         }
1109         printf("\n");
1110 }
1111
1112 static int Proto_set_fields(lua_State* L) {
1113     Proto proto = toProto(L,1);
1114 #define FIELDS_TABLE 2
1115 #define NEW_TABLE 3
1116 #define NEW_FIELD 3
1117
1118         lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields);
1119         lua_replace(L,FIELDS_TABLE);
1120
1121
1122         if( lua_istable(L,NEW_TABLE)) {
1123                 for (lua_pushnil(L); lua_next(L, NEW_TABLE); ) {
1124                         if (isProtoField(L,5)) {
1125                                 luaL_ref(L,FIELDS_TABLE);
1126                         } else if (! lua_isnil(L,5) ) {
1127                                 return luaL_error(L,"only ProtoFields should be in the table");
1128                         }
1129                 }
1130         } else if (isProtoField(L,NEW_FIELD)){
1131                 lua_pushvalue(L, NEW_FIELD);
1132                 luaL_ref(L,FIELDS_TABLE);
1133
1134         } else {
1135                 return luaL_error(L,"either a ProtoField or an array of protofields");
1136         }
1137         
1138         lua_pushvalue(L, 3);
1139         
1140     return 1;
1141 }
1142
1143
1144
1145 typedef struct {
1146     gchar* name;
1147     lua_CFunction get;
1148     lua_CFunction set;
1149 } proto_actions_t;
1150
1151 static const proto_actions_t proto_actions[] = {
1152         /* WSLUA_ATTRIBUTE Proto_dissector RW the protocol's dissector, a function you define */
1153     {"dissector",Proto_get_dissector, Proto_set_dissector},
1154
1155         /* WSLUA_ATTRIBUTE Proto_fields RO the Fields Table of this dissector */
1156     {"fields" ,Proto_get_fields, Proto_set_fields},
1157         
1158         /* WSLUA_ATTRIBUTE Proto_get_prefs RO the preferences of this dissector */
1159     {"prefs",Proto_get_prefs,NULL},
1160
1161         /* WSLUA_ATTRIBUTE Proto_init WO the init routine of this dissector, a function you define */
1162     {"init",NULL,Proto_set_init},
1163
1164         /* WSLUA_ATTRIBUTE Proto_name RO the name given to this dissector */
1165     {"name",Proto_get_name,NULL},
1166     {NULL,NULL,NULL}
1167 };
1168
1169 static int Proto_index(lua_State* L) {
1170     Proto proto = checkProto(L,1);
1171     const gchar* name = luaL_checkstring(L,2);
1172     const proto_actions_t* pa;
1173     
1174     if (! (proto && name) ) return 0;
1175     
1176     for (pa = proto_actions; pa->name; pa++) {
1177         if ( g_str_equal(name,pa->name) ) {
1178             if (pa->get) {
1179                 return pa->get(L);
1180             } else {
1181                 luaL_error(L,"You cannot get the `%s' attribute of a protocol",name);
1182                 return 0;
1183             }
1184         }
1185     }
1186
1187     luaL_error(L,"A protocol doesn't have a `%s' attribute",name);
1188     return 0;
1189 }
1190
1191
1192 static int Proto_newindex(lua_State* L) {
1193     Proto proto = checkProto(L,1);
1194     const gchar* name = luaL_checkstring(L,2);
1195     const proto_actions_t* pa;
1196     
1197     if (! (proto && name) ) return 0;
1198     
1199     for (pa = proto_actions; pa->name; pa++) {
1200         if ( g_str_equal(name,pa->name) ) {
1201             if (pa->set) {
1202                 return pa->set(L);
1203             } else {
1204                 luaL_error(L,"You cannot set the `%s' attribute of a protocol",name);
1205                 return 0;
1206             }
1207         }
1208     }
1209     
1210     luaL_error(L,"A protocol doesn't have a `%s' attribute",name);
1211     return 0;
1212 }
1213
1214 static const luaL_reg Proto_meta[] = {
1215     {"__tostring", Proto_tostring},
1216     {"__index", Proto_index},
1217     {"__newindex", Proto_newindex},
1218     {0, 0}
1219 };
1220
1221 int Proto_register(lua_State* L) {
1222
1223         WSLUA_REGISTER_META(Proto);
1224
1225         lua_newtable(L);
1226         protocols_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1227                                 
1228     lua_pushstring(L, "Proto");
1229     lua_pushcfunction(L, Proto_new);
1230     lua_settable(L, LUA_GLOBALSINDEX);
1231     
1232     Pref_register(L);
1233     Prefs_register(L);
1234     
1235     return 1;
1236 }
1237
1238 int Proto_commit(lua_State* L) {
1239         lua_settop(L,0);
1240         lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref);
1241         
1242         for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 2)) {
1243                 GArray* hfa = g_array_new(TRUE,TRUE,sizeof(hf_register_info));
1244                 GArray* etta = g_array_new(TRUE,TRUE,sizeof(gint*));
1245                 Proto proto;
1246                 const gchar* proto_name;
1247                 proto_name = lua_tostring(L,2);
1248                 proto = checkProto(L,3);
1249                 
1250                 lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields);
1251
1252                 for (lua_pushnil(L); lua_next(L, 4); lua_pop(L, 1)) {
1253                         ProtoField f = checkProtoField(L,6);
1254                         hf_register_info hfri = { &(f->hfid), {f->name,f->abbr,f->type,f->base,VALS(f->vs),f->mask,f->blob,HFILL}};
1255                         gint* ettp = &(f->ett);
1256
1257                         if (f->hfid != -2) {
1258                                 return luaL_error(L,"fields can be registered only once");
1259                         }
1260                         
1261                         f->hfid = -1;
1262                         g_array_append_val(hfa,hfri);
1263                         g_array_append_val(etta,ettp);
1264                 }
1265                 
1266                 proto_register_field_array(proto->hfid,(hf_register_info*)hfa->data,hfa->len);
1267                 proto_register_subtree_array((gint**)etta->data,etta->len);
1268                 
1269                 g_array_free(hfa,FALSE);
1270                 g_array_free(etta,FALSE);
1271         }
1272         
1273         return 0;
1274 }
1275
1276
1277
1278 WSLUA_CLASS_DEFINE(Dissector,NOP,NOP);
1279 /*
1280    A refererence to a dissector, used to call a dissector against a packet or a part of it.
1281  */
1282
1283
1284 WSLUA_CONSTRUCTOR Dissector_get (lua_State *L) {
1285         /*
1286          *  Obtains a dissector reference by name
1287          */
1288 #define WSLUA_ARG_Dissector_get_NAME 1 /* The name of the dissector */
1289     const gchar* name = luaL_checkstring(L,1);
1290     Dissector d;
1291     
1292     if (!name)
1293         WSLUA_ARG_ERROR(Dissector_get,NAME,"must be a string");
1294     
1295     if ((d = find_dissector(name))) {
1296         pushDissector(L, d);
1297         WSLUA_RETURN(1); /* The Dissector reference */
1298     } else
1299         WSLUA_ARG_ERROR(Dissector_get,NAME,"No such dissector");
1300     
1301 }
1302
1303 WSLUA_METHOD Dissector_call(lua_State* L) {
1304         /*
1305          *  Calls a dissector against a given packet (or part of it)
1306          */
1307 #define WSLUA_ARG_Dissector_call_TVB 2 /* The buffer to dissect */
1308 #define WSLUA_ARG_Dissector_call_PINFO 3 /* The packet info */
1309 #define WSLUA_ARG_Dissector_call_TREE 4 /* The tree on which to add the protocol items */
1310         
1311     Dissector d = checkDissector(L,1);
1312     Tvb tvb = checkTvb(L,WSLUA_ARG_Dissector_call_TVB);
1313     Pinfo pinfo = checkPinfo(L,WSLUA_ARG_Dissector_call_PINFO);
1314     TreeItem ti = checkTreeItem(L,WSLUA_ARG_Dissector_call_TREE);
1315     char* error = NULL;
1316         
1317     if (! ( d && tvb && pinfo) ) return 0;
1318     
1319     TRY {
1320         call_dissector(d, tvb, pinfo, ti->tree);
1321                 /* XXX Are we sure about this??? is this the right/only thing to catch */
1322     } CATCH(ReportedBoundsError) {
1323         proto_tree_add_protocol_format(lua_tree->tree, lua_malformed, lua_tvb, 0, 0, "[Malformed Frame: Packet Length]" );
1324         error = "malformed frame";
1325     } ENDTRY;
1326
1327      if (error) { WSLUA_ERROR(Dissector_call,error); }
1328
1329     return 0;
1330 }
1331
1332
1333 WSLUA_METAMETHOD Dissector_tostring(lua_State* L) {
1334     Dissector d = checkDissector(L,1);
1335     if (!d) return 0;
1336     lua_pushstring(L,dissector_handle_get_short_name(d));
1337     return 1;
1338 }
1339
1340 static const luaL_reg Dissector_methods[] = {
1341     {"get", Dissector_get },
1342     {"call", Dissector_call },
1343     {0,0}
1344 };
1345
1346 static const luaL_reg Dissector_meta[] = {
1347     {"__tostring", Dissector_tostring},
1348     {0, 0}
1349 };
1350
1351 int Dissector_register(lua_State* L) {
1352         WSLUA_REGISTER_CLASS(Dissector);
1353     return 1;
1354 }
1355
1356
1357 WSLUA_CLASS_DEFINE(DissectorTable,NOP,NOP);
1358 /*
1359  A table of subdissectors of a particular protocol (e.g. TCP subdissectors like http, smtp, sip are added to table "tcp.port").
1360  Useful to add more dissectors to a table so that they appear in the Decode As... dialog. 
1361  */
1362
1363 WSLUA_CONSTRUCTOR DissectorTable_new (lua_State *L) {
1364         /*
1365          Creates a new DissectorTable for your dissector's use .
1366          */
1367 #define WSLUA_ARG_DissectorTable_new_TABLENAME 1 /* The short name of the table. */
1368 #define WSLUA_OPTARG_DissectorTable_new_UINAME 2 /* The name of the table in the User Interface (defaults to the name given). */
1369 #define WSLUA_OPTARG_DissectorTable_new_TYPE 3 /* either FT_UINT* or FT_STRING (defaults to FT_UINT32) */
1370     gchar* name = (void*)luaL_checkstring(L,WSLUA_ARG_DissectorTable_new_TABLENAME);
1371     gchar* ui_name = (void*)luaL_optstring(L,WSLUA_OPTARG_DissectorTable_new_UINAME,name);
1372     enum ftenum type = luaL_optint(L,WSLUA_OPTARG_DissectorTable_new_TYPE,FT_UINT32);
1373     base_display_e base = luaL_optint(L,4,BASE_DEC);
1374     
1375     if(!(name && ui_name)) return 0;
1376     
1377     name = g_strdup(name);
1378     ui_name = g_strdup(ui_name);
1379     
1380     switch(type) {
1381         case FT_STRING:
1382             base = BASE_NONE;
1383         case FT_UINT8:
1384         case FT_UINT16:
1385         case FT_UINT24:
1386         case FT_UINT32:
1387         {
1388             DissectorTable dt = g_malloc(sizeof(struct _wslua_distbl_t));
1389             
1390             dt->table = register_dissector_table(name, ui_name, type, base);
1391             dt->name = name;
1392             pushDissectorTable(L, dt);
1393         }
1394             WSLUA_RETURN(1); /* The newly created DissectorTable */
1395         default:
1396             WSLUA_OPTARG_ERROR(DissectorTable_new,TYPE,"must be FTUINT* or FT_STRING");
1397     }
1398         return 0;    
1399 }
1400
1401 WSLUA_CONSTRUCTOR DissectorTable_get (lua_State *L) {
1402         /*
1403          Obtain a reference to an existing dissector table.
1404          */
1405 #define WSLUA_ARG_DissectorTable_get_TABLENAME 1 /* The short name of the table. */
1406     const gchar* name = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_TABLENAME);
1407     dissector_table_t table;
1408     
1409     if(!name) return 0;
1410     
1411     table = find_dissector_table(name);
1412     
1413     if (table) {
1414         DissectorTable dt = g_malloc(sizeof(struct _wslua_distbl_t));
1415         dt->table = table;
1416         dt->name = g_strdup(name);
1417         
1418         pushDissectorTable(L, dt);
1419         
1420                 WSLUA_RETURN(1); /* The DissectorTable */
1421     } else
1422         WSLUA_ARG_ERROR(DissectorTable_get,TABLENAME,"no such dissector_table");
1423     
1424 }
1425
1426
1427 WSLUA_METHOD DissectorTable_add (lua_State *L) {
1428         /*
1429          Add a dissector to a table.
1430          */
1431 #define WSLUA_ARG_DissectorTable_add_PATTERN 2 /* The pattern to match (either an integer or a string depending on the table's type). */
1432 #define WSLUA_ARG_DissectorTable_add_DISSECTOR 3 /* The dissector to add (either an Proto or a Dissector). */
1433         
1434     DissectorTable dt = checkDissectorTable(L,1);
1435     ftenum_t type;
1436     Dissector handle;
1437
1438     if (!dt) return 0;
1439
1440     if( isProto(L,WSLUA_ARG_DissectorTable_add_DISSECTOR) ) {
1441         Proto p;
1442         p = toProto(L,WSLUA_ARG_DissectorTable_add_DISSECTOR);
1443         handle = p->handle;
1444         
1445         if (! handle)
1446             WSLUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"a Protocol that does not have a dissector cannot be added to a table");
1447         
1448     } else if ( isDissector(L,WSLUA_ARG_DissectorTable_add_DISSECTOR) ) {
1449         handle = toDissector(L,WSLUA_ARG_DissectorTable_add_DISSECTOR);
1450     } else
1451                 WSLUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"must be either Proto or Dissector");
1452     
1453     type = get_dissector_table_selector_type(dt->name);
1454     
1455     if (type == FT_STRING) {
1456         gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN));
1457         dissector_add_string(dt->name, pattern,handle);
1458     } else if ( type == FT_UINT32 || type == FT_UINT16 || type ==  FT_UINT8 || type ==  FT_UINT24 ) {
1459         int port = luaL_checkint(L, WSLUA_ARG_DissectorTable_add_PATTERN);
1460         dissector_add(dt->name, port, handle);
1461     } else {
1462         luaL_error(L,"Strange type %d for a DissectorTable",type);
1463     }
1464     
1465     return 0;
1466 }
1467
1468 WSLUA_METHOD DissectorTable_remove (lua_State *L) {
1469         /*
1470          Remove a dissector from a table
1471          */
1472 #define WSLUA_ARG_DissectorTable_remove_PATTERN 2 /* The pattern to match (either an integer or a string depending on the table's type). */
1473 #define WSLUA_ARG_DissectorTable_remove_DISSECTOR 3 /* The dissector to add (either an Proto or a Dissector). */
1474     DissectorTable dt = checkDissectorTable(L,1);
1475     ftenum_t type;
1476     Dissector handle;
1477     
1478     if (!dt) return 0;
1479     
1480     if( isProto(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR) ) {
1481         Proto p;
1482         p = toProto(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR);
1483         handle = p->handle;
1484         
1485     } else if ( isDissector(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR) ) {
1486         handle = toDissector(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR);
1487         } else
1488                 WSLUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"must be either Proto or Dissector");
1489     
1490     type = get_dissector_table_selector_type(dt->name);
1491     
1492     if (type == FT_STRING) {
1493         gchar* pattern = g_strdup(luaL_checkstring(L,2));
1494         dissector_delete_string(dt->name, pattern,handle);
1495     } else if ( type == FT_UINT32 || type == FT_UINT16 || type ==  FT_UINT8 || type ==  FT_UINT24 ) {
1496         int port = luaL_checkint(L, 2);
1497         dissector_delete(dt->name, port, handle);
1498     }
1499     
1500     return 0;
1501 }
1502
1503
1504 WSLUA_METHOD DissectorTable_try (lua_State *L) {
1505         /*
1506          Try to call a dissector from a table
1507          */
1508 #define WSLUA_ARG_DissectorTable_try_PATTERN 2 /* The pattern to be matched (either an integer or a string depending on the table's type). */
1509 #define WSLUA_ARG_DissectorTable_try_TVB 3 /* The buffer to dissect */
1510 #define WSLUA_ARG_DissectorTable_try_PINFO 4 /* The packet info */
1511 #define WSLUA_ARG_DissectorTable_try_TREE 5 /* The tree on which to add the protocol items */
1512     DissectorTable dt = checkDissectorTable(L,1);
1513     Tvb tvb = checkTvb(L,3);
1514     Pinfo pinfo = checkPinfo(L,4);
1515     TreeItem ti = checkTreeItem(L,5);
1516     ftenum_t type;
1517     gchar* error = NULL;
1518         
1519     if (! (dt && tvb && pinfo && ti) ) return 0;
1520     
1521     type = get_dissector_table_selector_type(dt->name);
1522     
1523         TRY {
1524                 
1525                 if (type == FT_STRING) {
1526                         const gchar* pattern = luaL_checkstring(L,2);
1527                         
1528                         if (!pattern) return 0;
1529                         
1530                         if (dissector_try_string(dt->table,pattern,tvb,pinfo,ti->tree))
1531                                 return 0;
1532                         
1533                 } else if ( type == FT_UINT32 || type == FT_UINT16 || type ==  FT_UINT8 || type ==  FT_UINT24 ) {
1534                         int port = luaL_checkint(L, 2);
1535                 
1536                         if (dissector_try_port(dt->table,port,tvb,pinfo,ti->tree)) 
1537                                 return 0;
1538                         
1539                 } else {
1540                         luaL_error(L,"No such type of dissector_table");
1541                 }
1542                 
1543                 call_dissector(lua_data_handle,tvb,pinfo,ti->tree);
1544         
1545                 /* XXX Are we sure about this??? is this the right/only thing to catch */
1546         } CATCH(ReportedBoundsError) {
1547                 proto_tree_add_protocol_format(lua_tree->tree, lua_malformed, lua_tvb, 0, 0, "[Malformed Frame: Packet Length]" );
1548                 error = "malformed frame";
1549         } ENDTRY;
1550
1551         if (error) { WSLUA_ERROR(DissectorTable_try,error); }
1552
1553         return 0;
1554         
1555 }
1556
1557 WSLUA_METHOD DissectorTable_get_dissector (lua_State *L) {
1558         /*
1559          Try to obtain a dissector from a table.
1560          */
1561 #define WSLUA_ARG_DissectorTable_try_PATTERN 2 /* The pattern to be matched (either an integer or a string depending on the table's type). */
1562
1563     DissectorTable dt = checkDissectorTable(L,1);
1564     ftenum_t type;
1565     dissector_handle_t handle = lua_data_handle;
1566     
1567     if (!dt) return 0;
1568     
1569     type = get_dissector_table_selector_type(dt->name);
1570     
1571     if (type == FT_STRING) {
1572         const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_try_PATTERN);
1573                 
1574                 if (!pattern) WSLUA_ARG_ERROR(DissectorTable_try,PATTERN,"must be a string");
1575                 
1576         handle = dissector_get_string_handle(dt->table,pattern);
1577     } else if ( type == FT_UINT32 || type == FT_UINT16 || type ==  FT_UINT8 || type ==  FT_UINT24 ) {
1578         int port = luaL_checkint(L, WSLUA_ARG_DissectorTable_try_PATTERN);
1579         handle = dissector_get_port_handle(dt->table,port);
1580     }
1581     
1582         if (handle) {
1583                 pushDissector(L,handle);
1584                 WSLUA_RETURN(1); /* The dissector handle if found */
1585         } else {
1586                 lua_pushnil(L);
1587                 WSLUA_RETURN(1); /* nil if not found */
1588         }
1589 }
1590
1591
1592 WSLUA_METAMETHOD DissectorTable_tostring(lua_State* L) {
1593 /**/
1594         /* XXX It would be nice to iterate and print which dissectors it has */
1595     DissectorTable dt = checkDissectorTable(L,1);
1596     GString* s;
1597     ftenum_t type;
1598     
1599     if (!dt) return 0;
1600     
1601     type =  get_dissector_table_selector_type(dt->name);
1602     s = g_string_new("DissectorTable ");
1603     
1604     switch(type) {
1605         case FT_STRING:
1606         {
1607             g_string_sprintfa(s,"%s String:\n",dt->name);
1608             break;
1609         }
1610         case FT_UINT8:
1611         case FT_UINT16:
1612         case FT_UINT24:
1613         case FT_UINT32:
1614         {
1615             int base = get_dissector_table_base(dt->name);
1616             g_string_sprintfa(s,"%s Integer(%i):\n",dt->name,base);
1617             break;
1618         }
1619         default:
1620             luaL_error(L,"Strange table type");
1621     }            
1622     
1623     lua_pushstring(L,s->str);
1624     g_string_free(s,TRUE);
1625     return 1;
1626 }
1627
1628 static const luaL_reg DissectorTable_methods[] = {
1629     {"new", DissectorTable_new },
1630     {"get", DissectorTable_get },
1631     {"add", DissectorTable_add },
1632     {"remove", DissectorTable_remove },
1633     {"try", DissectorTable_try },
1634     {"get_dissector", DissectorTable_get_dissector },
1635     {0,0}
1636 };
1637
1638 static const luaL_reg DissectorTable_meta[] = {
1639     {"__tostring", DissectorTable_tostring},
1640     {0, 0}
1641 };
1642
1643 int DissectorTable_register(lua_State* L) {
1644         WSLUA_REGISTER_CLASS(DissectorTable);
1645     return 1;
1646 }
1647
1648
1649
1650