d6d3a8decfcfbf468355d52abf41ad2eaac6c971
[obnox/wireshark/wip.git] / plugins / lua / elua_proto.c
1 /*
2  * lua_proto.c
3  *
4  * Ethereal's interface to the Lua Programming Language
5  *
6  * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
7  *
8  * $Id$
9  *
10  * Wireshark - Network traffic analyzer
11  * By Gerald Combs <gerald@wireshark.org>
12  * Copyright 1998 Gerald Combs
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #include "elua.h"
30
31 ELUA_CLASS_DEFINE(Pref,NOP) /* A preference of a Protocol. */
32
33 static int new_pref(lua_State* L, pref_type_t type) {
34     const gchar* label = luaL_optstring(L,1,NULL);
35     const gchar* descr = luaL_optstring(L,3,"");
36     
37     Pref pref = g_malloc(sizeof(eth_pref_t));
38     pref->name = NULL;
39     pref->label = label ? g_strdup(label) : NULL;
40     pref->desc = g_strdup(descr);
41     pref->type = type;
42     pref->next = NULL;
43     pref->proto = NULL;
44     
45     switch(type) {
46         case PREF_BOOL: {
47             gboolean def = lua_toboolean(L,2);
48             pref->value.b = def;
49             break;
50         }
51         case PREF_UINT: {
52             guint32 def = (guint32)luaL_optnumber(L,2,0);
53             pref->value.u = def;
54             break;
55         }
56         case PREF_STRING: {
57             gchar* def = g_strdup(luaL_optstring(L,2,""));
58             pref->value.s = def;
59             break;
60         }
61         default:
62             g_assert_not_reached();
63             break;
64
65     }
66
67     pushPref(L,pref);
68     return 1;
69     
70 }
71
72 ELUA_CONSTRUCTOR Pref_bool(lua_State* L) {
73         /*
74          * Creates a boolean preference to be added to a Protocol's prefs table.
75          */
76 #define ELUA_ATTR_Pref_bool_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
77 #define ELUA_ATTR_Pref_bool_DEFAULT 2 /* The default value for this preference */
78 #define ELUA_ATTR_Pref_bool_DESCR 3 /* A description of what this preference is */
79     return new_pref(L,PREF_BOOL);
80 }
81
82 ELUA_CONSTRUCTOR Pref_uint(lua_State* L) {
83         /*
84          * Creates an (unsigned) integer preference to be added to a Protocol's prefs table.
85          */
86 #define ELUA_ATTR_Pref_uint_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
87 #define ELUA_ATTR_Pref_uint_DEFAULT 2 /* The default value for this preference */
88 #define ELUA_ATTR_Pref_uint_DESCR 3 /* A description of what this preference is */
89     return new_pref(L,PREF_UINT);
90 }
91
92 ELUA_CONSTRUCTOR Pref_string(lua_State* L) {
93         /*
94          * Creates a string preference to be added to a Protocol's prefs table.
95          */
96 #define ELUA_ATTR_Pref_string_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
97 #define ELUA_ATTR_Pref_string_DEFAULT 2 /* The default value for this preference */
98 #define ELUA_ATTR_Pref_string_DESCR 3 /* A description of what this preference is */
99     return new_pref(L,PREF_STRING);
100 }
101
102 static int Pref_gc(lua_State* L) {
103     Pref pref = checkPref(L,1);
104     
105     if (pref && ! pref->name) {
106         if (pref->label) g_free(pref->label);
107         if (pref->desc) g_free(pref->desc);
108         if (pref->type == PREF_STRING) g_free((void*)pref->value.s);
109         g_free(pref);
110     }
111     
112     return 0;
113 }
114
115 ELUA_METHODS Pref_methods[] = {
116     {"bool",   Pref_bool},
117     {"uint",   Pref_uint},
118     {"string",   Pref_string},
119     {0,0}
120 };
121
122 ELUA_META Pref_meta[] = {
123     {"__gc",   Pref_gc},
124     {0,0}
125 };
126
127
128 ELUA_REGISTER Pref_register(lua_State* L) {
129         ELUA_REGISTER_CLASS(Pref);
130     return 1;
131 }
132
133 ELUA_CLASS_DEFINE(Prefs,NOP) /* The table of preferences of a protocol */
134
135 ELUA_METAMETHOD Prefs__newindex(lua_State* L) {
136         /* creates a new preference */
137 #define ELUA_ARG_Prefs__newindex_NAME 2 /* The abbreviation of this preference */
138 #define ELUA_ARG_Prefs__newindex_PREF 3 /* A valid still unassigned Pref object */
139
140     Pref prefs = checkPrefs(L,1);
141     const gchar* name = luaL_checkstring(L,ELUA_ARG_Prefs__newindex_NAME);
142     Pref pref = checkPref(L,ELUA_ARG_Prefs__newindex_PREF);
143     Pref p;
144
145         if (! prefs ) return 0;
146
147         if (! name ) 
148                 ELUA_ARG_ERROR(Prefs__newindex,NAME,"must be a string");
149
150         if (! pref )
151                 ELUA_ARG_ERROR(Prefs__newindex,PREF,"must be a valid Pref");
152     
153     if (pref->name)
154         ELUA_ARG_ERROR(Prefs__newindex,NAME,"cannot change existing preference");
155
156         if (pref->proto)
157                 ELUA_ARG_ERROR(Prefs__newindex,PREF,"cannot be added to more than one protocol");
158
159     p = prefs;
160     
161     do {
162         if ( p->name && g_str_equal(p->name,name) ) {
163             luaL_error(L,"a preference named %s exists already",name);
164             return 0;
165         }
166         
167         if ( ! p->next) {
168             p->next = pref;
169             
170             pref->name = g_strdup(name);
171             
172             if (!pref->label)
173                 pref->label = g_strdup(name);
174
175             if (!prefs->proto->prefs_module) {
176                 prefs->proto->prefs_module = prefs_register_protocol(prefs->proto->hfid, NULL);
177    
178             }
179             
180             switch(pref->type) {
181                 case PREF_BOOL: 
182                     prefs_register_bool_preference(prefs->proto->prefs_module,
183                                                    pref->name,
184                                                    pref->label,
185                                                    pref->desc,
186                                                    &(pref->value.b));
187                     break;
188                 case PREF_UINT:
189                     prefs_register_uint_preference(prefs->proto->prefs_module,
190                                                    pref->name,
191                                                    pref->label,
192                                                    pref->desc,
193                                                    10,
194                                                    &(pref->value.u));
195                     break;
196                 case PREF_STRING:
197                     prefs_register_string_preference(prefs->proto->prefs_module, 
198                                                      pref->name,
199                                                      pref->label,
200                                                      pref->desc,
201                                                      &(pref->value.s));
202                     break;
203                 default:
204                     ELUA_ERROR(Prefs__newindex,"unknow Pref type");
205             }
206             
207             pref->proto = p->proto;
208             
209             ELUA_RETURN(0);
210         }
211     } while (( p = p->next ));
212
213         luaL_error(L,"this should not happen!");
214     
215     ELUA_RETURN(0);
216 }
217
218 ELUA_METAMETHOD Prefs__index(lua_State* L) {
219         /* get the value of a preference setting */
220 #define ELUA_ARG_Prefs__index_NAME 2 /* The abbreviation of this preference  */
221
222     Pref prefs = checkPrefs(L,1);
223     const gchar* name = luaL_checkstring(L,2);
224     
225     if (! ( name && prefs ) ) return 0;
226     
227     prefs = prefs->next;
228     
229     do {
230         if ( g_str_equal(prefs->name,name) ) {
231             switch (prefs->type) {
232                 case PREF_BOOL: lua_pushboolean(L, prefs->value.b); break;
233                 case PREF_UINT: lua_pushnumber(L,(lua_Number)prefs->value.u); break;
234                 case PREF_STRING: lua_pushstring(L,prefs->value.s); break;
235                 default: ELUA_ERROR(Prefs__index,"unknow Pref type");
236             }
237             ELUA_RETURN(1); /* the current value of the preference */
238         }
239     } while (( prefs = prefs->next ));
240
241     ELUA_ARG_ERROR(Prefs__index,NAME,"no preference named like this");
242     ELUA_RETURN(0);
243 }
244
245 ELUA_META Prefs_meta[] = {
246     {"__newindex",   Prefs__newindex},
247     {"__index",   Prefs__index},
248     {0,0}
249 };
250
251 ELUA_REGISTER Prefs_register(lua_State* L) {
252         ELUA_REGISTER_META(Prefs);
253     return 1;
254 }
255
256
257 ELUA_CLASS_DEFINE(ProtoField,FAIL_ON_NULL("null ProtoField"))
258 /*
259  * A Protocol field (to be used when adding items to the dissection tree)
260  */
261
262 static const eth_ft_types_t ftenums[] = {
263 {"FT_BOOLEAN",FT_BOOLEAN},
264 {"FT_UINT8",FT_UINT8},
265 {"FT_UINT16",FT_UINT16},
266 {"FT_UINT24",FT_UINT24},
267 {"FT_UINT32",FT_UINT32},
268 {"FT_UINT64",FT_UINT64},
269 {"FT_INT8",FT_INT8},
270 {"FT_INT16",FT_INT16},
271 {"FT_INT24",FT_INT24},
272 {"FT_INT32",FT_INT32},
273 {"FT_INT64",FT_INT64},
274 {"FT_FLOAT",FT_FLOAT},
275 {"FT_DOUBLE",FT_DOUBLE},
276 {"FT_STRING",FT_STRING},
277 {"FT_STRINGZ",FT_STRINGZ},
278 {"FT_ETHER",FT_ETHER},
279 {"FT_BYTES",FT_BYTES},
280 {"FT_UINT_BYTES",FT_UINT_BYTES},
281 {"FT_IPv4",FT_IPv4},
282 {"FT_IPv6",FT_IPv6},
283 {"FT_IPXNET",FT_IPXNET},
284 {"FT_FRAMENUM",FT_FRAMENUM},
285 {"FT_GUID",FT_GUID},
286 {"FT_OID",FT_OID},
287 {NULL,FT_NONE}
288 };
289
290 #if 0
291 static enum ftenum get_ftenum(const gchar* type) {
292     const eth_ft_types_t* ts;
293     for (ts = ftenums; ts->str; ts++) {
294         if ( g_str_equal(ts->str,type) ) {
295             return ts->id;
296         }
297     }
298     
299     return FT_NONE;
300 }
301 #endif
302
303 static const gchar* ftenum_to_string(enum ftenum ft) {
304     const eth_ft_types_t* ts;
305     for (ts = ftenums; ts->str; ts++) {
306         if ( ts->id == ft ) {
307             return ts->str;
308         }
309     }
310     
311     return NULL;
312 }
313
314 struct base_display_string_t {
315     const gchar* str;
316     base_display_e base;
317 };
318
319 static const struct base_display_string_t base_displays[] = {
320         { "BASE_NONE", BASE_NONE},
321         {"BASE_DEC", BASE_DEC},
322         {"BASE_HEX", BASE_HEX},
323         {"BASE_OCT", BASE_OCT},
324         {"BASE_DEC_HEX", BASE_DEC_HEX},
325         {"BASE_HEX_DEC", BASE_HEX_DEC},
326         {NULL,0}
327 };
328
329 static const gchar* base_to_string(base_display_e base) {
330     const struct base_display_string_t* b;
331     for (b=base_displays;b->str;b++) {
332         if ( base == b->base)
333             return b->str;
334     }
335     return NULL;
336 }
337
338 #if 0
339 static base_display_e string_to_base(const gchar* str) {
340     const struct base_display_string_t* b;
341     for (b=base_displays;b->str;b++) {
342         if ( g_str_equal(str,b->str))
343             return b->base;
344     }
345     return BASE_NONE;
346 }
347 #endif
348
349 static value_string* value_string_from_table(lua_State* L, int idx) {
350     GArray* vs = g_array_new(TRUE,TRUE,sizeof(value_string));
351     value_string* ret;
352     
353     if(lua_isnil(L,idx)) {
354             return NULL;
355     } else if (!lua_istable(L,idx)) {
356         luaL_argerror(L,idx,"must be a table");
357         g_array_free(vs,TRUE);
358         return NULL;
359     }
360     
361     lua_pushnil(L);
362     
363     while (lua_next(L, idx) != 0) {
364         value_string v = {0,NULL};
365         
366         if (! lua_isnumber(L,-2)) {
367             luaL_argerror(L,idx,"All keys of a table used as vaalue_string must be integers");
368             g_array_free(vs,TRUE);
369             return NULL;
370         }
371         
372         if (! lua_isstring(L,-1)) {
373             luaL_argerror(L,idx,"All values of a table used as vaalue_string must be strings");
374             g_array_free(vs,TRUE);
375             return NULL;
376         }
377         
378         v.value = (guint32)lua_tonumber(L,-2);
379         v.strptr = g_strdup(lua_tostring(L,-1));
380         
381         g_array_append_val(vs,v);
382         
383         lua_pop(L, 1);
384     }
385     
386     lua_pop(L, 1);
387     
388     ret = (value_string*)vs->data;
389     
390     g_array_free(vs,FALSE);
391
392     return ret;
393     
394 }    
395
396 ELUA_CONSTRUCTOR ProtoField_new(lua_State* L) { /* Creates a new field to be used in a protocol. */
397 #define ELUA_ARG_ProtoField_new_NAME 1 /* Actual name of the field (the string that appears in the tree).  */
398 #define ELUA_ARG_ProtoField_new_ABBR 2 /* Filter name of the field (the string that is used in filters).  */
399 #define ELUA_ARG_ProtoField_new_TYPE 3 /* Field Type (FT_*).  */
400 #define ELUA_OPTARG_ProtoField_new_VALUESTRING 3 /* a ValueString object. */
401 #define ELUA_OPTARG_ProtoField_new_BASE 4 /* The representation BASE_*. */
402 #define ELUA_OPTARG_ProtoField_new_MASK 5 /* the bitmask to be used.  */
403 #define ELUA_OPTARG_ProtoField_new_DESCR 6 /* The description of the field.  */
404         
405     ProtoField f = g_malloc(sizeof(eth_field_t));
406     value_string* vs;
407     
408     /* will be using -2 as far as the field has not been added to an array then it will turn -1 */
409     f->hfid = -2;
410         f->ett = -1;
411     f->name = g_strdup(luaL_checkstring(L,ELUA_ARG_ProtoField_new_NAME));
412     f->abbr = g_strdup(luaL_checkstring(L,ELUA_ARG_ProtoField_new_ABBR));
413     f->type = luaL_checkint(L,ELUA_ARG_ProtoField_new_TYPE);
414     
415         /*XXX do it better*/
416     if (f->type == FT_NONE) { 
417         ELUA_ARG_ERROR(ProtoField_new,TYPE,"invalid FT_type");
418         return 0;
419     }
420     
421     if (! lua_isnil(L,4) ) {
422         vs = value_string_from_table(L,4);
423         
424         if (vs) {
425             f->vs = vs;
426         } else {
427             g_free(f);
428             return 0;
429         }
430         
431         
432     } else {
433         f->vs = NULL;
434     }
435     
436     /* XXX: need BASE_ERROR */
437     f->base = luaL_optint(L, ELUA_OPTARG_ProtoField_new_BASE, BASE_NONE);
438     f->mask = luaL_optint(L, ELUA_OPTARG_ProtoField_new_MASK, 0x0);
439     f->blob = g_strdup(luaL_optstring(L,ELUA_OPTARG_ProtoField_new_DESCR,""));
440     
441     pushProtoField(L,f);
442     
443     ELUA_RETURN(1); /* The newly created ProtoField object */ 
444 }
445
446
447 static int ProtoField_integer(lua_State* L, enum ftenum type) {
448     ProtoField f = g_malloc(sizeof(eth_field_t));
449         const gchar* abbr = luaL_checkstring(L,1);
450     const gchar* name = luaL_optstring(L,2,abbr);
451     base_display_e base = luaL_optint(L, 3, BASE_DEC);
452     value_string* vs = (lua_gettop(L) > 3) ? value_string_from_table(L,4) : NULL;
453     int mask = luaL_optint(L, 5, 0x0);
454     const gchar* blob = luaL_optstring(L,6,"");
455
456     if (base < BASE_DEC || base > BASE_HEX_DEC) {
457         luaL_argerror(L,2,"Base must be either BASE_DEC, BASE_HEX, BASE_OCT,"
458                       " BASE_DEC_HEX, BASE_DEC_HEX or BASE_HEX_DEC");
459         return 0;
460     }
461
462     f->hfid = -2;
463         f->ett = -1;
464     f->name = g_strdup(name);
465     f->abbr = g_strdup(abbr);
466     f->type = type;
467     f->vs = vs;
468     f->base = base;
469     f->mask = mask;
470     f->blob = g_strdup(blob);
471     
472     
473     pushProtoField(L,f);
474     
475     return 1;
476 }
477
478 #define PROTOFIELD_INTEGER(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_integer(L,FT); }
479 /* ELUA_SECTION Protofield integer constructors */
480 /* ELUA_TEXT integer type ProtoField constructors use the following arguments */
481 /* ELUA_ARG_DESC Protofield_integer ABBR abbreviated name of the field (the string used in filters)  */
482 /* ELUA_OPTARG_DESC Protofield_integer NAME Actual name of the field (the string that appears in the tree)  */
483 /* ELUA_ARGDESC Protofield_integer DESC description of the field  */
484 /* _ELUA_RETURNS_ Protofield_integer a protofiled item to be added to a ProtoFieldArray */
485 /* _ELUA_CONSTRUCTOR_ ProtoField_uint8 */
486 /* _ELUA_CONSTRUCTOR_ ProtoField_uint16 */
487 /* _ELUA_CONSTRUCTOR_ ProtoField_uint24 */
488 /* _ELUA_CONSTRUCTOR_ ProtoField_uint32 */
489 /* _ELUA_CONSTRUCTOR_ ProtoField_uint64 */
490 /* _ELUA_CONSTRUCTOR_ ProtoField_int8 */
491 /* _ELUA_CONSTRUCTOR_ ProtoField_int16 */
492 /* _ELUA_CONSTRUCTOR_ ProtoField_int24 */
493 /* _ELUA_CONSTRUCTOR_ ProtoField_int32 */
494 /* _ELUA_CONSTRUCTOR_ ProtoField_int64 */
495 /* _ELUA_CONSTRUCTOR_ ProtoField_framenum */
496 PROTOFIELD_INTEGER(uint8,FT_UINT8)
497 PROTOFIELD_INTEGER(uint16,FT_UINT16)
498 PROTOFIELD_INTEGER(uint24,FT_UINT24)
499 PROTOFIELD_INTEGER(uint32,FT_UINT32)
500 PROTOFIELD_INTEGER(uint64,FT_UINT64)
501 PROTOFIELD_INTEGER(int8,FT_INT8)
502 PROTOFIELD_INTEGER(int16,FT_INT8)
503 PROTOFIELD_INTEGER(int24,FT_INT8)
504 PROTOFIELD_INTEGER(int32,FT_INT8)
505 PROTOFIELD_INTEGER(int64,FT_INT8)
506 PROTOFIELD_INTEGER(framenum,FT_FRAMENUM)
507
508 static int ProtoField_other(lua_State* L,enum ftenum type) {
509     ProtoField f = g_malloc(sizeof(eth_field_t));
510     const gchar* abbr = luaL_checkstring(L,1);
511     const gchar* name = luaL_optstring(L,2,abbr);
512     const gchar* blob = luaL_optstring(L,3,"");
513     
514     f->hfid = -2;
515         f->ett = -1;
516     f->name = g_strdup(name);
517     f->abbr = g_strdup(abbr);
518     f->type = type;
519     f->vs = NULL;
520     f->base = ( type == FT_FLOAT || type == FT_DOUBLE) ? BASE_DEC : BASE_NONE;
521     f->mask = 0;
522     f->blob = g_strdup(blob);
523     
524     pushProtoField(L,f);
525     
526     return 1;
527 }
528
529 #define PROTOFIELD_OTHER(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_other(L,FT); }
530 /* ELUA_SECTION Protofield integer constructors */
531 /* ELUA_TEXT integer type ProtoField constructors use the following arguments */
532 /* ELUA_ARG_DESC Protofield_integer ABBR abbreviated name of the field (the string used in filters)  */
533 /* ELUA_OPTARG_DESC Protofield_integer NAME Actual name of the field (the string that appears in the tree)  */
534 /* ELUA_ARGDESC Protofield_integer DESC : description of the field  */
535 /* _ELUA_RETURNS_ Protofield non integer : a protofiled item to be added to a ProtoFieldArray */
536 /* _ELUA_CONSTRUCTOR_ ProtoField_ipv4 */
537 /* _ELUA_CONSTRUCTOR_ ProtoField_ipv6 */
538 /* _ELUA_CONSTRUCTOR_ ProtoField_ether */
539 /* _ELUA_CONSTRUCTOR_ ProtoField_float */
540 /* _ELUA_CONSTRUCTOR_ ProtoField_double */
541 /* _ELUA_CONSTRUCTOR_ ProtoField_string */
542 /* _ELUA_CONSTRUCTOR_ ProtoField_strigz */
543 /* _ELUA_CONSTRUCTOR_ ProtoField_bytes */
544 /* _ELUA_CONSTRUCTOR_ ProtoField_ubytes */
545 /* _ELUA_CONSTRUCTOR_ ProtoField_guid */
546 /* _ELUA_CONSTRUCTOR_ ProtoField_oid */
547 /* _ELUA_CONSTRUCTOR_ ProtoField_bool */
548 PROTOFIELD_OTHER(ipv4,FT_IPv4)
549 PROTOFIELD_OTHER(ipv6,FT_IPv6)
550 PROTOFIELD_OTHER(ipx,FT_IPXNET)
551 PROTOFIELD_OTHER(ether,FT_ETHER)
552 PROTOFIELD_OTHER(float,FT_FLOAT)
553 PROTOFIELD_OTHER(double,FT_DOUBLE)
554 PROTOFIELD_OTHER(string,FT_STRING)
555 PROTOFIELD_OTHER(stringz,FT_STRINGZ)
556 PROTOFIELD_OTHER(bytes,FT_BYTES)
557 PROTOFIELD_OTHER(ubytes,FT_UINT_BYTES)
558 PROTOFIELD_OTHER(guid,FT_GUID)
559 PROTOFIELD_OTHER(oid,FT_OID)
560
561 /* XXX: T/F strings */
562 PROTOFIELD_OTHER(bool,FT_BOOLEAN)
563
564
565 static int ProtoField_tostring(lua_State* L) {
566     ProtoField f = checkProtoField(L,1);
567     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);
568     
569     lua_pushstring(L,s);
570     g_free(s);
571     
572     return 1;
573 }
574
575 static int ProtoField_gc(lua_State* L) {
576     ProtoField f = checkProtoField(L,1);
577
578     /*
579      * A garbage collector for ProtoFields makes little sense.
580      * Even if This cannot be used anymore because it has gone out of scope, 
581      * we can destroy the ProtoField only if it is not part of a ProtoFieldArray,
582      * if it actualy belongs to one we need to preserve it as it is pointed by
583      * a field array that may be registered afterwards causing a crash or memory corruption.
584      */
585     
586     if (!f) {
587         luaL_argerror(L,1,"BUG: ProtoField_gc called for something not ProtoField");
588         /* g_assert() ?? */
589     } else if (f->hfid == -2) {
590         g_free(f->name);
591         g_free(f->abbr);
592         g_free(f->blob);
593         g_free(f);
594     }
595     
596     return 0;
597 }
598
599
600 static const luaL_reg ProtoField_methods[] = {
601     {"new",   ProtoField_new},
602     {"uint8",ProtoField_uint8},
603     {"uint16",ProtoField_uint16},
604     {"uint24",ProtoField_uint24},
605     {"uint32",ProtoField_uint32},
606     {"uint64",ProtoField_uint64},
607     {"int8",ProtoField_int8},
608     {"int16",ProtoField_int16},
609     {"int24",ProtoField_int24},
610     {"int32",ProtoField_int32},
611     {"int64",ProtoField_int64},
612     {"framenum",ProtoField_framenum},
613     {"ipv4",ProtoField_ipv4},
614     {"ipv6",ProtoField_ipv6},
615     {"ipx",ProtoField_ipx},
616     {"ether",ProtoField_ether},
617     {"bool",ProtoField_bool},
618     {"float",ProtoField_float},
619     {"double",ProtoField_double},
620     {"string",ProtoField_string},
621     {"stringz",ProtoField_stringz},
622     {"bytes",ProtoField_bytes},
623     {"ubytes",ProtoField_ubytes},
624     {"guid",ProtoField_guid},
625     {"oid",ProtoField_oid},
626     {0,0}
627 };
628
629 static const luaL_reg ProtoField_meta[] = {
630     {"__gc", ProtoField_gc },
631     {"__tostring", ProtoField_tostring },
632     {0, 0}
633 };
634
635 int ProtoField_register(lua_State* L) {
636     
637         ELUA_REGISTER_CLASS(ProtoField);
638         
639     return 1;
640 }
641
642 ELUA_CLASS_DEFINE(Proto,NOP)
643 /*
644   A new protocol in wireshark. Protocols have more uses, the main one is to dissect
645   a protocol. But they can be just dummies used to register preferences for
646   other purposes.
647  */
648
649 static int protocols_table_ref = LUA_NOREF;
650
651 ELUA_CONSTRUCTOR Proto_new(lua_State* L) {
652 #define ELUA_ARG_Proto_new_NAME 1 /* The name of the protocol */
653 #define ELUA_ARG_Proto_new_DESC 1 /* A Long Text description of the protocol (usually lowercase) */
654     const gchar* name = luaL_checkstring(L,1);
655     const gchar* desc = luaL_checkstring(L,2);
656     
657     if ( name ) {
658                 gchar* loname = ep_strdup(name);
659                 g_strdown(loname);
660         if ( proto_get_id_by_filter_name(loname) > 0 ) { 
661             ELUA_ARG_ERROR(Proto_new,NAME,"there cannot be two protocols with the same name");
662         } else {
663             Proto proto = g_malloc(sizeof(eth_proto_t));
664                         gchar* loname = g_strdup(name);
665                         gchar* hiname = g_strdup(name);
666                         
667                         g_strdown(loname);
668                         g_strup(hiname);
669
670             proto->name = hiname;
671             proto->desc = g_strdup(desc);
672                         proto->hfid = proto_register_protocol(proto->desc,hiname,loname);
673                         proto->ett = -1;
674                         proto->is_postdissector = FALSE;
675                         
676                         lua_newtable (L);
677                         proto->fields = luaL_ref(L, LUA_REGISTRYINDEX);
678                         
679             proto->prefs.name = NULL;
680             proto->prefs.label = NULL;
681             proto->prefs.desc = NULL;
682             proto->prefs.value.u = 0;
683             proto->prefs.next = NULL;
684             proto->prefs.proto = proto;
685                         
686             proto->prefs_module = NULL;
687             proto->handle = NULL;
688                                 
689                         lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref);
690
691                         lua_pushstring(L,loname);
692                         pushProto(L,proto);
693
694                         lua_settable(L, -3);
695                         
696                         pushProto(L,proto);
697                         
698                         ELUA_RETURN(1); /* The newly created protocol */
699         }
700      } else {
701         ELUA_ARG_ERROR(Proto_new,NAME,"must be a string");
702      }
703
704         return 0;
705 }
706
707
708
709 static int Proto_tostring(lua_State* L) { 
710     Proto proto = checkProto(L,1);
711     gchar* s;
712     
713     if (!proto) return 0;
714     
715     s = g_strdup_printf("Proto: %s",proto->name);
716     lua_pushstring(L,s);
717     g_free(s);
718     
719     return 1;
720 }
721
722 ELUA_FUNCTION elua_register_postdissector(lua_State* L) { 
723     Proto proto = checkProto(L,1);
724     if (!proto) return 0;
725     
726     if(!proto->is_postdissector) {
727         if (! proto->handle) {
728             proto->handle = create_dissector_handle(dissect_lua, proto->hfid);
729         }
730         
731         register_postdissector(proto->handle);
732     } else {
733         luaL_argerror(L,1,"this protocol is already registered as postdissector");
734     }
735     
736     return 0;
737 }
738
739
740 static int Proto_get_dissector(lua_State* L) { 
741     Proto proto = toProto(L,1);
742     
743     if (proto->handle) {
744         pushDissector(L,proto->handle);
745         return 1;
746     } else {
747         luaL_error(L,"The protocol hasn't been registered yet");
748         return 0;
749     }
750 }
751
752
753 static int Proto_set_dissector(lua_State* L) { 
754     Proto proto = toProto(L,1);
755
756         if (lua_isfunction(L,3)) {
757         /* insert the dissector into the dissectors table */
758        
759         lua_rawgeti(L, LUA_REGISTRYINDEX, lua_dissectors_table_ref);
760         lua_replace(L, 1);
761         lua_pushstring(L,proto->name);
762         lua_replace(L, 2);
763         lua_settable(L,1);
764         
765         proto->handle = create_dissector_handle(dissect_lua, proto->hfid);
766         
767         return 0;
768     } else {
769         luaL_argerror(L,3,"The dissector of a protocol must be a function");
770         return 0;
771     }
772 }
773
774 static int Proto_get_prefs(lua_State* L) { 
775     Proto proto = toProto(L,1);
776     
777     pushPrefs(L,&proto->prefs);
778     return 1;
779 }
780
781 static int Proto_set_init(lua_State* L) { 
782     Proto proto = toProto(L,1);
783     
784     if (lua_isfunction(L,3)) {
785         /* insert the dissector into the dissectors table */
786         lua_pushstring(L, ELUA_INIT_ROUTINES);
787         lua_gettable(L, LUA_GLOBALSINDEX);
788         lua_replace(L, 1);
789         lua_pushstring(L,proto->name);
790         lua_replace(L, 2);
791         lua_settable(L,1);
792         
793         return 0;
794     }  else {
795         luaL_argerror(L,3,"The initializer of a protocol must be a function");
796         return 0;
797     } 
798 }
799
800 static int Proto_get_name(lua_State* L) { 
801     Proto proto = toProto(L,1);
802
803     lua_pushstring(L,proto->name);
804     return 1;
805 }
806
807
808 static int Proto_get_fields(lua_State* L) { 
809     Proto proto = toProto(L,1);
810     lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields);
811     return 1;
812 }
813
814 void elua_print_stack(char* s, lua_State* L) {
815         int i;
816         
817         for (i=1;i<=lua_gettop(L);i++) {
818                 printf("%s-%i: %s\n",s,i,lua_typename (L,lua_type(L, i)));
819         }
820         printf("\n");
821 }
822
823 static int Proto_set_fields(lua_State* L) {
824     Proto proto = toProto(L,1);
825 #define FIELDS_TABLE 2
826 #define NEW_TABLE 3
827 #define NEW_FIELD 3
828
829         lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields);
830         lua_replace(L,FIELDS_TABLE);
831
832
833         if( lua_istable(L,NEW_TABLE)) {
834                 for (lua_pushnil(L); lua_next(L, NEW_TABLE); ) {
835                         if (isProtoField(L,5)) {
836                                 luaL_ref(L,FIELDS_TABLE);
837                         } else if (! lua_isnil(L,5) ) {
838                                 return luaL_error(L,"only ProtoFields should be in the table");
839                         }
840                 }
841         } else if (isProtoField(L,NEW_FIELD)){
842                 lua_pushvalue(L, NEW_FIELD);
843                 luaL_ref(L,FIELDS_TABLE);
844
845         } else {
846                 return luaL_error(L,"either a ProtoField or an array of protofields");
847         }
848         
849         lua_pushvalue(L, 3);
850         
851     return 1;
852 }
853
854
855
856 typedef struct {
857     gchar* name;
858     lua_CFunction get;
859     lua_CFunction set;
860 } proto_actions_t;
861
862 static const proto_actions_t proto_actions[] = {
863         /* ELUA_ATTRIBUTE Pinfo_dissector RW the protocol's dissector, a function you define */
864     {"dissector",Proto_get_dissector, Proto_set_dissector},
865
866         /* ELUA_ATTRIBUTE Pinfo_fields RO the Fields Table of this dissector */
867     {"fields" ,Proto_get_fields, Proto_set_fields},
868         
869         /* ELUA_ATTRIBUTE Proto_get_prefs RO the preferences of this dissector */
870     {"prefs",Proto_get_prefs,NULL},
871
872         /* ELUA_ATTRIBUTE Proto_init WO the init routine of this dissector, a function you define */
873     {"init",NULL,Proto_set_init},
874
875         /* ELUA_ATTRIBUTE Proto_init RO the name given to this dissector */
876     {"name",Proto_get_name,NULL},
877     {NULL,NULL,NULL}
878 };
879
880 static int Proto_index(lua_State* L) {
881     Proto proto = checkProto(L,1);
882     const gchar* name = luaL_checkstring(L,2);
883     const proto_actions_t* pa;
884     
885     if (! (proto && name) ) return 0;
886     
887     for (pa = proto_actions; pa->name; pa++) {
888         if ( g_str_equal(name,pa->name) ) {
889             if (pa->get) {
890                 return pa->get(L);
891             } else {
892                 luaL_error(L,"You cannot get the `%s' attribute of a protocol",name);
893                 return 0;
894             }
895         }
896     }
897
898     luaL_error(L,"A protocol doesn't have a `%s' attribute",name);
899     return 0;
900 }
901
902
903 static int Proto_newindex(lua_State* L) {
904     Proto proto = checkProto(L,1);
905     const gchar* name = luaL_checkstring(L,2);
906     const proto_actions_t* pa;
907     
908     if (! (proto && name) ) return 0;
909     
910     for (pa = proto_actions; pa->name; pa++) {
911         if ( g_str_equal(name,pa->name) ) {
912             if (pa->set) {
913                 return pa->set(L);
914             } else {
915                 luaL_error(L,"You cannot set the `%s' attribute of a protocol",name);
916                 return 0;
917             }
918         }
919     }
920     
921     luaL_error(L,"A protocol doesn't have a `%s' attribute",name);
922     return 0;
923 }
924
925 static const luaL_reg Proto_meta[] = {
926     {"__tostring", Proto_tostring},
927     {"__index", Proto_index},
928     {"__newindex", Proto_newindex},
929     {0, 0}
930 };
931
932 int Proto_register(lua_State* L) {
933
934         ELUA_REGISTER_META(Proto);
935
936         lua_newtable(L);
937         protocols_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
938                                 
939     lua_pushstring(L, "Proto");
940     lua_pushcfunction(L, Proto_new);
941     lua_settable(L, LUA_GLOBALSINDEX);
942     
943     Pref_register(L);
944     Prefs_register(L);
945     
946     return 1;
947 }
948
949 int Proto_commit(lua_State* L) {
950         lua_settop(L,0);
951         lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref);
952         
953         for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 2)) {
954                 GArray* hfa = g_array_new(TRUE,TRUE,sizeof(hf_register_info));
955                 GArray* etta = g_array_new(TRUE,TRUE,sizeof(gint*));
956                 Proto proto;
957                 const gchar* proto_name;
958                 proto_name = lua_tostring(L,2);
959                 proto = checkProto(L,3);
960                 
961                 lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields);
962
963                 for (lua_pushnil(L); lua_next(L, 4); lua_pop(L, 1)) {
964                         ProtoField f = checkProtoField(L,6);
965                         hf_register_info hfri = { &(f->hfid), {f->name,f->abbr,f->type,f->base,VALS(f->vs),f->mask,f->blob,HFILL}};
966                         gint* ettp = &(f->ett);
967
968                         if (f->hfid != -2) {
969                                 return luaL_error(L,"fields can be registered only once");
970                         }
971                         
972                         f->hfid = -1;
973                         g_array_append_val(hfa,hfri);
974                         g_array_append_val(etta,ettp);
975                 }
976                 
977                 proto_register_field_array(proto->hfid,(hf_register_info*)hfa->data,hfa->len);
978                 proto_register_subtree_array((gint**)etta->data,etta->len);
979                 
980                 g_array_free(hfa,FALSE);
981                 g_array_free(etta,FALSE);
982         }
983         
984         return 0;
985 }
986
987
988
989 ELUA_CLASS_DEFINE(Dissector,NOP)
990 /*
991    A refererence to a dissector, used to call a dissector against a packet or a part of it.
992  */
993
994
995 ELUA_CONSTRUCTOR Dissector_get (lua_State *L) {
996         /*
997          *  Obtains a dissector reference by name
998          */
999 #define ELUA_ARG_Dissector_get_NAME 1 /* The name of the dissector */
1000     const gchar* name = luaL_checkstring(L,1);
1001     Dissector d;
1002     
1003     if (!name)
1004         ELUA_ARG_ERROR(Dissector_get,NAME,"must be a string");
1005     
1006     if ((d = find_dissector(name))) {
1007         pushDissector(L, d);
1008         ELUA_RETURN(1); /* The Dissector reference */
1009     } else
1010         ELUA_ARG_ERROR(Dissector_get,NAME,"No such dissector");
1011     
1012 }
1013
1014 ELUA_METHOD Dissector_call(lua_State* L) {
1015         /*
1016          *  Calls a dissector against a given packet (or part of it)
1017          */
1018 #define ELUA_ARG_Dissector_call_TVB 2 /* The buffer to dissect */
1019 #define ELUA_ARG_Dissector_call_PINFO 3 /* The packet info */
1020 #define ELUA_ARG_Dissector_call_TREE 4 /* The tree on which to add the protocol items */
1021         
1022     Dissector d = checkDissector(L,1);
1023     Tvb tvb = checkTvb(L,ELUA_ARG_Dissector_call_TVB);
1024     Pinfo pinfo = checkPinfo(L,ELUA_ARG_Dissector_call_PINFO);
1025     TreeItem ti = checkTreeItem(L,ELUA_ARG_Dissector_call_TREE);
1026     
1027     if (! ( d && tvb && pinfo) ) return 0;
1028     
1029     TRY {
1030         call_dissector(d, tvb, pinfo, ti->tree);
1031                 /* XXX Are we sure about this??? is this the right/only thing to catch */
1032     } CATCH(ReportedBoundsError) {
1033         proto_tree_add_protocol_format(lua_tree->tree, lua_malformed, lua_tvb, 0, 0, "[Malformed Frame: Packet Length]" );
1034         ELUA_ERROR(Dissector_call,"malformed frame");
1035         return 0;
1036     } ENDTRY;
1037     
1038     return 0;
1039 }
1040
1041
1042 static int Dissector_tostring(lua_State* L) {
1043     Dissector d = checkDissector(L,1);
1044     if (!d) return 0;
1045     lua_pushstring(L,dissector_handle_get_short_name(d));
1046     return 1;
1047 }
1048
1049 static const luaL_reg Dissector_methods[] = {
1050     {"get", Dissector_get },
1051     {"call", Dissector_call },
1052     {0,0}
1053 };
1054
1055 static const luaL_reg Dissector_meta[] = {
1056     {"__tostring", Dissector_tostring},
1057     {0, 0}
1058 };
1059
1060 int Dissector_register(lua_State* L) {
1061         ELUA_REGISTER_CLASS(Dissector);
1062     return 1;
1063 }
1064
1065
1066 ELUA_CLASS_DEFINE(DissectorTable,NOP)
1067 /*
1068  A table of subdissectors of a particular protocol (e.g. TCP subdissectors like http, smtp, sip are added to table "tcp.port").
1069  Useful to add more dissectors to a table so that they appear in the Decode As... dialog. 
1070  */
1071
1072 ELUA_CONSTRUCTOR DissectorTable_new (lua_State *L) {
1073         /*
1074          Creates a new DissectorTable for your dissector's use .
1075          */
1076 #define ELUA_ARG_DissectorTable_new_TABLENAME 1 /* The short name of the table. */
1077 #define ELUA_OPTARG_DissectorTable_new_UINAME 2 /* The name of the table in the User Interface (defaults to the name given). */
1078 #define ELUA_OPTARG_DissectorTable_new_TYPE 3 /* either FT_UINT* or FT_STRING (defaults to FT_UINT32) */
1079     gchar* name = (void*)luaL_checkstring(L,ELUA_ARG_DissectorTable_new_TABLENAME);
1080     gchar* ui_name = (void*)luaL_optstring(L,ELUA_OPTARG_DissectorTable_new_UINAME,name);
1081     enum ftenum type = luaL_optint(L,ELUA_OPTARG_DissectorTable_new_TYPE,FT_UINT32);
1082     base_display_e base = luaL_optint(L,4,BASE_DEC);
1083     
1084     if(!(name && ui_name)) return 0;
1085     
1086     name = g_strdup(name);
1087     ui_name = g_strdup(ui_name);
1088     
1089     switch(type) {
1090         case FT_STRING:
1091             base = BASE_NONE;
1092         case FT_UINT8:
1093         case FT_UINT16:
1094         case FT_UINT24:
1095         case FT_UINT32:
1096         {
1097             DissectorTable dt = g_malloc(sizeof(struct _eth_distbl_t));
1098             
1099             dt->table = register_dissector_table(name, ui_name, type, base);
1100             dt->name = name;
1101             pushDissectorTable(L, dt);
1102         }
1103             ELUA_RETURN(1); /* The newly created DissectorTable */
1104         default:
1105             ELUA_OPTARG_ERROR(DissectorTable_new,TYPE,"must be FTUINT* or FT_STRING");
1106     }
1107         return 0;    
1108 }
1109
1110 ELUA_CONSTRUCTOR DissectorTable_get (lua_State *L) {
1111         /*
1112          Obtain a reference to an existing dissector table.
1113          */
1114 #define ELUA_ARG_DissectorTable_get_TABLENAME 1 /* The short name of the table. */
1115     const gchar* name = luaL_checkstring(L,ELUA_ARG_DissectorTable_get_TABLENAME);
1116     dissector_table_t table;
1117     
1118     if(!name) return 0;
1119     
1120     table = find_dissector_table(name);
1121     
1122     if (table) {
1123         DissectorTable dt = g_malloc(sizeof(struct _eth_distbl_t));
1124         dt->table = table;
1125         dt->name = g_strdup(name);
1126         
1127         pushDissectorTable(L, dt);
1128         
1129                 ELUA_RETURN(1); /* The DissectorTable */
1130     } else
1131         ELUA_ARG_ERROR(DissectorTable_get,TABLENAME,"no such dissector_table");
1132     
1133 }
1134
1135
1136 ELUA_METHOD DissectorTable_add (lua_State *L) {
1137         /*
1138          Add a dissector to a table.
1139          */
1140 #define ELUA_ARG_DissectorTable_add_PATTERN 2 /* The pattern to match (either an integer or a string depending on the table's type). */
1141 #define ELUA_ARG_DissectorTable_add_DISSECTOR 3 /* The dissector to add (either an Proto or a Dissector). */
1142         
1143     DissectorTable dt = checkDissectorTable(L,1);
1144     ftenum_t type;
1145     Dissector handle;
1146
1147     if (!dt) return 0;
1148
1149     if( isProto(L,ELUA_ARG_DissectorTable_add_DISSECTOR) ) {
1150         Proto p;
1151         p = toProto(L,ELUA_ARG_DissectorTable_add_DISSECTOR);
1152         handle = p->handle;
1153         
1154         if (! handle)
1155             ELUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"a Protocol that does not have a dissector cannot be added to a table");
1156         
1157     } else if ( isDissector(L,ELUA_ARG_DissectorTable_add_DISSECTOR) ) {
1158         handle = toDissector(L,ELUA_ARG_DissectorTable_add_DISSECTOR);
1159     } else
1160                 ELUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"must be either Proto or Dissector");
1161     
1162     type = get_dissector_table_selector_type(dt->name);
1163     
1164     if (type == FT_STRING) {
1165         gchar* pattern = g_strdup(luaL_checkstring(L,ELUA_ARG_DissectorTable_add_PATTERN));
1166         dissector_add_string(dt->name, pattern,handle);
1167     } else if ( type == FT_UINT32 || type == FT_UINT16 || type ==  FT_UINT8 || type ==  FT_UINT24 ) {
1168         int port = luaL_checkint(L, ELUA_ARG_DissectorTable_add_PATTERN);
1169         dissector_add(dt->name, port, handle);
1170     } else {
1171         luaL_error(L,"Strange type %d for a DissectorTable",type);
1172     }
1173     
1174     return 0;
1175 }
1176
1177 ELUA_METHOD DissectorTable_remove (lua_State *L) {
1178         /*
1179          Remove a dissector from a table
1180          */
1181 #define ELUA_ARG_DissectorTable_remove_PATTERN 2 /* The pattern to match (either an integer or a string depending on the table's type). */
1182 #define ELUA_ARG_DissectorTable_remove_DISSECTOR 3 /* The dissector to add (either an Proto or a Dissector). */
1183     DissectorTable dt = checkDissectorTable(L,1);
1184     ftenum_t type;
1185     Dissector handle;
1186     
1187     if (!dt) return 0;
1188     
1189     if( isProto(L,ELUA_ARG_DissectorTable_remove_DISSECTOR) ) {
1190         Proto p;
1191         p = toProto(L,ELUA_ARG_DissectorTable_remove_DISSECTOR);
1192         handle = p->handle;
1193         
1194     } else if ( isDissector(L,ELUA_ARG_DissectorTable_remove_DISSECTOR) ) {
1195         handle = toDissector(L,ELUA_ARG_DissectorTable_remove_DISSECTOR);
1196         } else
1197                 ELUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"must be either Proto or Dissector");
1198     
1199     type = get_dissector_table_selector_type(dt->name);
1200     
1201     if (type == FT_STRING) {
1202         gchar* pattern = g_strdup(luaL_checkstring(L,2));
1203         dissector_delete_string(dt->name, pattern,handle);
1204     } else if ( type == FT_UINT32 || type == FT_UINT16 || type ==  FT_UINT8 || type ==  FT_UINT24 ) {
1205         int port = luaL_checkint(L, 2);
1206         dissector_delete(dt->name, port, handle);
1207     }
1208     
1209     return 0;
1210 }
1211
1212
1213 ELUA_METHOD DissectorTable_try (lua_State *L) {
1214         /*
1215          Try to call a dissector from a table
1216          */
1217 #define ELUA_ARG_DissectorTable_try_PATTERN 2 /* The pattern to be matched (either an integer or a string depending on the table's type). */
1218 #define ELUA_ARG_DissectorTable_try_TVB 3 /* The buffer to dissect */
1219 #define ELUA_ARG_DissectorTable_try_PINFO 4 /* The packet info */
1220 #define ELUA_ARG_DissectorTable_try_TREE 5 /* The tree on which to add the protocol items */
1221     DissectorTable dt = checkDissectorTable(L,1);
1222     Tvb tvb = checkTvb(L,3);
1223     Pinfo pinfo = checkPinfo(L,4);
1224     TreeItem ti = checkTreeItem(L,5);
1225     ftenum_t type;
1226     
1227     if (! (dt && tvb && pinfo && ti) ) return 0;
1228     
1229     type = get_dissector_table_selector_type(dt->name);
1230     
1231         TRY {
1232                 
1233                 if (type == FT_STRING) {
1234                         const gchar* pattern = luaL_checkstring(L,2);
1235                         
1236                         if (!pattern) return 0;
1237                         
1238                         if (dissector_try_string(dt->table,pattern,tvb,pinfo,ti->tree))
1239                                 return 0;
1240                         
1241                 } else if ( type == FT_UINT32 || type == FT_UINT16 || type ==  FT_UINT8 || type ==  FT_UINT24 ) {
1242                         int port = luaL_checkint(L, 2);
1243                 
1244                         if (dissector_try_port(dt->table,port,tvb,pinfo,ti->tree)) 
1245                                 return 0;
1246                         
1247                 } else {
1248                         luaL_error(L,"No such type of dissector_table");
1249                 }
1250                 
1251                 call_dissector(lua_data_handle,tvb,pinfo,ti->tree);
1252         
1253                 /* XXX Are we sure about this??? is this the right/only thing to catch */
1254         } CATCH(ReportedBoundsError) {
1255                 proto_tree_add_protocol_format(lua_tree->tree, lua_malformed, lua_tvb, 0, 0, "[Malformed Frame: Packet Length]" );
1256                 ELUA_ERROR(DissectorTable_try,"malformed frame");
1257         } ENDTRY;
1258
1259         return 0;
1260         
1261 }
1262
1263 ELUA_METHOD DissectorTable_get_dissector (lua_State *L) {
1264         /*
1265          Try to obtain a dissector from a table.
1266          */
1267 #define ELUA_ARG_DissectorTable_try_PATTERN 2 /* The pattern to be matched (either an integer or a string depending on the table's type). */
1268
1269     DissectorTable dt = checkDissectorTable(L,1);
1270     ftenum_t type;
1271     dissector_handle_t handle = lua_data_handle;
1272     
1273     if (!dt) return 0;
1274     
1275     type = get_dissector_table_selector_type(dt->name);
1276     
1277     if (type == FT_STRING) {
1278         const gchar* pattern = luaL_checkstring(L,ELUA_ARG_DissectorTable_try_PATTERN);
1279                 
1280                 if (!pattern) ELUA_ARG_ERROR(DissectorTable_try,PATTERN,"must be a string");
1281                 
1282         handle = dissector_get_string_handle(dt->table,pattern);
1283     } else if ( type == FT_UINT32 || type == FT_UINT16 || type ==  FT_UINT8 || type ==  FT_UINT24 ) {
1284         int port = luaL_checkint(L, ELUA_ARG_DissectorTable_try_PATTERN);
1285         handle = dissector_get_port_handle(dt->table,port);
1286     }
1287     
1288         if (handle) {
1289                 pushDissector(L,handle);
1290                 ELUA_RETURN(1); /* The dissector handle if found */
1291         } else {
1292                 lua_pushnil(L);
1293                 ELUA_RETURN(1); /* nil if not found */
1294         }
1295 }
1296
1297
1298 static int DissectorTable_tostring(lua_State* L) {
1299         /* XXX It would be nice to iterate and print which dissectors it has */
1300     DissectorTable dt = checkDissectorTable(L,1);
1301     GString* s;
1302     ftenum_t type;
1303     
1304     if (!dt) return 0;
1305     
1306     type =  get_dissector_table_selector_type(dt->name);
1307     s = g_string_new("DissectorTable ");
1308     
1309     switch(type) {
1310         case FT_STRING:
1311         {
1312             g_string_sprintfa(s,"%s String:\n",dt->name);
1313             break;
1314         }
1315         case FT_UINT8:
1316         case FT_UINT16:
1317         case FT_UINT24:
1318         case FT_UINT32:
1319         {
1320             int base = get_dissector_table_base(dt->name);
1321             g_string_sprintfa(s,"%s Integer(%i):\n",dt->name,base);
1322             break;
1323         }
1324         default:
1325             luaL_error(L,"Strange table type");
1326     }            
1327     
1328     lua_pushstring(L,s->str);
1329     g_string_free(s,TRUE);
1330     return 1;
1331 }
1332
1333 static const luaL_reg DissectorTable_methods[] = {
1334     {"new", DissectorTable_new },
1335     {"get", DissectorTable_get },
1336     {"add", DissectorTable_add },
1337     {"remove", DissectorTable_remove },
1338     {"try", DissectorTable_try },
1339     {"get_dissector", DissectorTable_get_dissector },
1340     {0,0}
1341 };
1342
1343 static const luaL_reg DissectorTable_meta[] = {
1344     {"__tostring", DissectorTable_tostring},
1345     {0, 0}
1346 };
1347
1348 int DissectorTable_register(lua_State* L) {
1349         ELUA_REGISTER_CLASS(DissectorTable);
1350     return 1;
1351 }
1352
1353
1354