Lua accessor for Protocol field type gets wrong data
[metze/wireshark/wip.git] / epan / wslua / wslua_field.c
1 /*
2  *  wslua_field.c
3  *
4  * Wireshark's interface to the Lua Programming Language
5  *
6  * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26
27 #include "config.h"
28
29 #include <epan/emem.h>
30 #include <epan/dfilter/dfilter.h>
31 #include <epan/ftypes/ftypes-int.h>
32
33 /* WSLUA_MODULE Field Obtaining dissection data */
34
35 #include "wslua.h"
36
37 /* any call to checkFieldInfo() will now error on null or expired, so no need to check again */
38 WSLUA_CLASS_DEFINE(FieldInfo,FAIL_ON_NULL_OR_EXPIRED("FieldInfo"),NOP);
39 /*
40    An extracted Field from dissected packet data. A `FieldInfo` object can only be used within
41    the callback functions of dissectors, post-dissectors, heuristic-dissectors, and taps.
42
43    A `FieldInfo` can be called on either existing Wireshark fields by using either `Field.new()`
44    or `Field()` before-hand, or it can be called on new fields created by Lua from a `ProtoField`.
45  */
46
47 static GPtrArray* outstanding_FieldInfo = NULL;
48
49 #define PUSH_FIELDINFO(L,fi) {g_ptr_array_add(outstanding_FieldInfo,fi);pushFieldInfo(L,fi);}
50
51 CLEAR_OUTSTANDING(FieldInfo,expired,TRUE)
52
53 /* WSLUA_ATTRIBUTE FieldInfo_len RO The length of this field. */
54 WSLUA_METAMETHOD FieldInfo__len(lua_State* L) {
55     /*
56        Obtain the Length of the field
57        */
58     FieldInfo fi = checkFieldInfo(L,1);
59
60     lua_pushnumber(L,fi->ws_fi->length);
61     return 1;
62 }
63
64 /* WSLUA_ATTRIBUTE FieldInfo_offset RO The offset of this field. */
65 WSLUA_METAMETHOD FieldInfo__unm(lua_State* L) {
66     /*
67        Obtain the Offset of the field
68        */
69     FieldInfo fi = checkFieldInfo(L,1);
70
71     lua_pushnumber(L,fi->ws_fi->start);
72     return 1;
73 }
74
75 /* WSLUA_ATTRIBUTE FieldInfo_value RO The value of this field. */
76 WSLUA_METAMETHOD FieldInfo__call(lua_State* L) {
77     /*
78        Obtain the Value of the field.
79
80        Previous to 1.11.4, this function retrieved the value for most field types,
81        but for `ftypes.UINT_BYTES` it retrieved the `ByteArray` of the field's entire `TvbRange`.
82        In other words, it returned a `ByteArray` that included the leading length byte(s),
83        instead of just the *value* bytes. That was a bug, and has been changed in 1.11.4.
84        Furthermore, it retrieved an `ftypes.GUID` as a `ByteArray`, which is also incorrect.
85
86        If you wish to still get a `ByteArray` of the `TvbRange`, use `FieldInfo:get_range()`
87        to get the `TvbRange`, and then use `Tvb:bytes()` to convert it to a `ByteArray`.
88        */
89     FieldInfo fi = checkFieldInfo(L,1);
90
91     switch(fi->ws_fi->hfinfo->type) {
92         case FT_BOOLEAN:
93                 lua_pushboolean(L,(int)fvalue_get_uinteger(&(fi->ws_fi->value)));
94                 return 1;
95         case FT_UINT8:
96         case FT_UINT16:
97         case FT_UINT24:
98         case FT_UINT32:
99         case FT_FRAMENUM:
100                 lua_pushnumber(L,(lua_Number)(fvalue_get_uinteger(&(fi->ws_fi->value))));
101                 return 1;
102         case FT_INT8:
103         case FT_INT16:
104         case FT_INT24:
105         case FT_INT32:
106                 lua_pushnumber(L,(lua_Number)(fvalue_get_sinteger(&(fi->ws_fi->value))));
107                 return 1;
108         case FT_FLOAT:
109         case FT_DOUBLE:
110                 lua_pushnumber(L,(lua_Number)(fvalue_get_floating(&(fi->ws_fi->value))));
111                 return 1;
112         case FT_INT64: {
113                 pushInt64(L,(Int64)(fvalue_get_integer64(&(fi->ws_fi->value))));
114                 return 1;
115             }
116         case FT_UINT64: {
117                 pushUInt64(L,fvalue_get_integer64(&(fi->ws_fi->value)));
118                 return 1;
119             }
120         case FT_ETHER: {
121                 Address eth = (Address)g_malloc(sizeof(address));
122                 eth->type = AT_ETHER;
123                 eth->len = fi->ws_fi->length;
124                 eth->data = tvb_memdup(NULL,fi->ws_fi->ds_tvb,fi->ws_fi->start,fi->ws_fi->length);
125                 pushAddress(L,eth);
126                 return 1;
127             }
128         case FT_IPv4:{
129                 Address ipv4 = (Address)g_malloc(sizeof(address));
130                 ipv4->type = AT_IPv4;
131                 ipv4->len = fi->ws_fi->length;
132                 ipv4->data = tvb_memdup(NULL,fi->ws_fi->ds_tvb,fi->ws_fi->start,fi->ws_fi->length);
133                 pushAddress(L,ipv4);
134                 return 1;
135             }
136         case FT_IPv6: {
137                 Address ipv6 = (Address)g_malloc(sizeof(address));
138                 ipv6->type = AT_IPv6;
139                 ipv6->len = fi->ws_fi->length;
140                 ipv6->data = tvb_memdup(NULL,fi->ws_fi->ds_tvb,fi->ws_fi->start,fi->ws_fi->length);
141                 pushAddress(L,ipv6);
142                 return 1;
143             }
144         case FT_IPXNET:{
145                 Address ipx = (Address)g_malloc(sizeof(address));
146                 ipx->type = AT_IPX;
147                 ipx->len = fi->ws_fi->length;
148                 ipx->data = tvb_memdup(NULL,fi->ws_fi->ds_tvb,fi->ws_fi->start,fi->ws_fi->length);
149                 pushAddress(L,ipx);
150                 return 1;
151             }
152         case FT_ABSOLUTE_TIME:
153         case FT_RELATIVE_TIME: {
154                 NSTime nstime = (NSTime)g_malloc(sizeof(nstime_t));
155                 *nstime = *(NSTime)fvalue_get(&(fi->ws_fi->value));
156                 pushNSTime(L,nstime);
157                 return 1;
158             }
159         case FT_STRING:
160         case FT_STRINGZ: {
161                 gchar* repr = fvalue_to_string_repr(&fi->ws_fi->value,FTREPR_DISPLAY,NULL);
162                 if (repr)
163                     lua_pushstring(L,repr);
164                 else
165                     luaL_error(L,"field cannot be represented as string because it may contain invalid characters");
166
167                 return 1;
168             }
169         case FT_NONE:
170                 if (fi->ws_fi->length == 0) {
171                         lua_pushnil(L);
172                         return 1;
173                 }
174                 /* FALLTHROUGH */
175         case FT_BYTES:
176         case FT_UINT_BYTES:
177         case FT_REL_OID:
178         case FT_SYSTEM_ID:
179         case FT_OID:
180             {
181                 ByteArray ba = g_byte_array_new();
182                 g_byte_array_append(ba, (const guint8 *) fvalue_get(&fi->ws_fi->value),
183                                     fvalue_length(&fi->ws_fi->value));
184                 pushByteArray(L,ba);
185                 return 1;
186             }
187         case FT_PROTOCOL:
188             {
189                 ByteArray ba = g_byte_array_new();
190                 tvbuff_t* tvb = (tvbuff_t *) fvalue_get(&fi->ws_fi->value);
191                 g_byte_array_append(ba, (const guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0,
192                                             tvb_captured_length(tvb)), tvb_captured_length(tvb));
193                 pushByteArray(L,ba);
194                 return 1;
195             }
196
197         case FT_GUID:
198         default:
199                 luaL_error(L,"FT_ not yet supported");
200                 return 1;
201     }
202 }
203
204 /* WSLUA_ATTRIBUTE FieldInfo_label RO The string representing this field */
205 WSLUA_METAMETHOD FieldInfo__tostring(lua_State* L) {
206     /* The string representation of the field. */
207     FieldInfo fi = checkFieldInfo(L,1);
208
209     if (fi->ws_fi->value.ftype->val_to_string_repr) {
210         gchar* repr = NULL;
211
212         if (fi->ws_fi->hfinfo->type == FT_PROTOCOL || fi->ws_fi->hfinfo->type == FT_PCRE) {
213             repr = fvalue_to_string_repr(&fi->ws_fi->value,FTREPR_DFILTER,NULL);
214         }
215         else {
216             repr = fvalue_to_string_repr(&fi->ws_fi->value,FTREPR_DISPLAY,NULL);
217         }
218
219         if (repr) {
220             lua_pushstring(L,repr);
221             /* fvalue_to_string_repr() g_malloc's the string's buffer */
222             g_free(repr);
223         }
224         else {
225             lua_pushstring(L,"(unknown)");
226         }
227     }
228     else if (fi->ws_fi->hfinfo->type == FT_NONE) {
229         lua_pushstring(L, "(none)");
230     }
231     else {
232         lua_pushstring(L,"(n/a)");
233     }
234
235     return 1;
236 }
237
238 /* WSLUA_ATTRIBUTE FieldInfo_display RO The string display of this field as seen in GUI */
239 static int FieldInfo_get_display(lua_State* L) {
240     /* The display string of this field as seen in GUI. */
241     FieldInfo fi = checkFieldInfo(L,1);
242     gchar         label_str[ITEM_LABEL_LENGTH+1];
243     gchar        *label_ptr;
244     gchar        *value_ptr;
245
246     if (!fi->ws_fi->rep) {
247         label_ptr = label_str;
248         proto_item_fill_label(fi->ws_fi, label_str);
249     } else
250         label_ptr = fi->ws_fi->rep->representation;
251
252     if (!label_ptr) return 0;
253
254     value_ptr = strstr(label_ptr, ": ");
255     if (!value_ptr) {
256         /* just use whatever's there */
257         lua_pushstring(L, label_ptr);
258     } else {
259         value_ptr += 2;  /* get past the ': ' */
260         lua_pushstring(L, value_ptr);
261     }
262
263     return 1;
264 }
265
266 /* WSLUA_ATTRIBUTE FieldInfo_range RO The `TvbRange` covering this field */
267 static int FieldInfo_get_range(lua_State* L) {
268     /* The `TvbRange` covering this field. */
269     FieldInfo fi = checkFieldInfo(L,1);
270
271     if (push_TvbRange (L, fi->ws_fi->ds_tvb, fi->ws_fi->start, fi->ws_fi->length)) {
272         return 1;
273     }
274
275     return 0;
276 }
277
278 /* WSLUA_ATTRIBUTE FieldInfo_generated RO Whether this field was marked as generated (boolean) */
279 static int FieldInfo_get_generated(lua_State* L) {
280     /* Whether this field was marked as generated. */
281     FieldInfo fi = checkFieldInfo(L,1);
282
283     lua_pushboolean(L,FI_GET_FLAG(fi->ws_fi, FI_GENERATED));
284     return 1;
285 }
286
287 /* WSLUA_ATTRIBUTE FieldInfo_name RO The name of this field */
288 static int FieldInfo_get_name(lua_State* L) {
289     /* The filter name of this field. */
290     FieldInfo fi = checkFieldInfo(L,1);
291
292     lua_pushstring(L,fi->ws_fi->hfinfo->abbrev);
293     return 1;
294 }
295
296 WSLUA_METAMETHOD FieldInfo__eq(lua_State* L) {
297     /* Checks whether lhs is within rhs. */
298     FieldInfo l = checkFieldInfo(L,1);
299     FieldInfo r = checkFieldInfo(L,2);
300
301     if (l->ws_fi->ds_tvb != r->ws_fi->ds_tvb) {
302         WSLUA_ERROR(FieldInfo__eq,"Data source must be the same for both fields");
303         return 0;
304     }
305
306     if (l->ws_fi->start <= r->ws_fi->start && r->ws_fi->start + r->ws_fi->length <= l->ws_fi->start + r->ws_fi->length) {
307         lua_pushboolean(L,1);
308         return 1;
309     } else {
310         return 0;
311     }
312 }
313
314 WSLUA_METAMETHOD FieldInfo__le(lua_State* L) {
315     /* Checks whether the end byte of lhs is before the end of rhs. */
316     FieldInfo l = checkFieldInfo(L,1);
317     FieldInfo r = checkFieldInfo(L,2);
318
319     if (l->ws_fi->ds_tvb != r->ws_fi->ds_tvb)
320         WSLUA_ERROR(FieldInfo__le,"Data source must be the same for both fields");
321
322     if (r->ws_fi->start + r->ws_fi->length <= l->ws_fi->start + r->ws_fi->length) {
323         lua_pushboolean(L,1);
324         return 1;
325     } else {
326         return 0;
327     }
328 }
329
330 WSLUA_METAMETHOD FieldInfo__lt(lua_State* L) {
331     /* Checks whether the end byte of rhs is before the beginning of rhs. */
332     FieldInfo l = checkFieldInfo(L,1);
333     FieldInfo r = checkFieldInfo(L,2);
334
335     if (l->ws_fi->ds_tvb != r->ws_fi->ds_tvb) {
336         WSLUA_ERROR(FieldInfo__lt,"Data source must be the same for both fields");
337         return 0;
338     }
339
340     if (r->ws_fi->start + r->ws_fi->length < l->ws_fi->start) {
341         lua_pushboolean(L,1);
342         return 1;
343     } else {
344         return 0;
345     }
346 }
347
348 /* Gets registered as metamethod automatically by WSLUA_REGISTER_META */
349 static int FieldInfo__gc(lua_State* L _U_) {
350     FieldInfo fi = toFieldInfo(L,1);
351
352     if (!fi) return 0;
353
354     if (!fi->expired)
355         fi->expired = TRUE;
356     else
357         /* do NOT free fi->ws_fi */
358         g_free(fi);
359
360     return 0;
361 }
362
363 /* This table is ultimately registered as a sub-table of the class' metatable,
364  * and if __index/__newindex is invoked then it calls the appropriate function
365  * from this table for getting/setting the members.
366  */
367 WSLUA_ATTRIBUTES FieldInfo_attributes[] = {
368     WSLUA_ATTRIBUTE_ROREG(FieldInfo,range),
369     WSLUA_ATTRIBUTE_ROREG(FieldInfo,generated),
370     WSLUA_ATTRIBUTE_ROREG(FieldInfo,name),
371     WSLUA_ATTRIBUTE_ROREG(FieldInfo,display),
372     { "label", FieldInfo__tostring, NULL },
373     { "value", FieldInfo__call, NULL },
374     { "tvb", FieldInfo_get_range, NULL },
375     { "len", FieldInfo__len, NULL },
376     { "offset", FieldInfo__unm, NULL },
377     { NULL, NULL, NULL }
378 };
379
380 WSLUA_META FieldInfo_meta[] = {
381     WSLUA_CLASS_MTREG(FieldInfo,tostring),
382     WSLUA_CLASS_MTREG(FieldInfo,call),
383     WSLUA_CLASS_MTREG(FieldInfo,len),
384     WSLUA_CLASS_MTREG(FieldInfo,unm),
385     WSLUA_CLASS_MTREG(FieldInfo,eq),
386     WSLUA_CLASS_MTREG(FieldInfo,le),
387     WSLUA_CLASS_MTREG(FieldInfo,lt),
388     { NULL, NULL }
389 };
390
391 int FieldInfo_register(lua_State* L) {
392     WSLUA_REGISTER_META(FieldInfo);
393     WSLUA_REGISTER_ATTRIBUTES(FieldInfo);
394     return 0;
395 }
396
397
398 WSLUA_FUNCTION wslua_all_field_infos(lua_State* L) {
399     /*
400     Obtain all fields from the current tree.  Note this only gets whatever fields the underlying
401     dissectors have filled in for this packet at this time - there may be fields applicable to
402     the packet that simply aren't being filled in because at this time they're not needed for anything.
403     This function only gets what the C-side code has currently populated, not the full list.
404     */
405     GPtrArray* found;
406     int items_found = 0;
407     guint i;
408
409     if (! lua_tree || ! lua_tree->tree ) {
410         WSLUA_ERROR(wslua_all_field_infos,"Cannot be called outside a listener or dissector");
411         return 0;
412     }
413
414     found = proto_all_finfos(lua_tree->tree);
415
416     if (found) {
417         for (i=0; i<found->len; i++) {
418             FieldInfo fi = (FieldInfo)g_malloc(sizeof(struct _wslua_field_info));
419             fi->ws_fi = (field_info *)g_ptr_array_index(found,i);
420             fi->expired = FALSE;
421
422             PUSH_FIELDINFO(L,fi);
423             items_found++;
424         }
425
426         g_ptr_array_free(found,TRUE);
427     }
428
429     return items_found;
430 }
431
432 WSLUA_CLASS_DEFINE(Field,FAIL_ON_NULL("Field"),NOP);
433 /*
434    A Field extractor to to obtain field values. A `Field` object can only be created *outside* of
435    the callback functions of dissectors, post-dissectors, heuristic-dissectors, and taps.
436
437    Once created, it is used *inside* the callback functions, to generate a `FieldInfo` object.
438  */
439
440 static GPtrArray* wanted_fields = NULL;
441 static dfilter_t* wslua_dfilter = NULL;
442
443 /* We use a fake dfilter for Lua field extractors, so that
444  * epan_dissect_run() will populate the fields.  This won't happen
445  * if the passed-in edt->tree is NULL, which it will be if the
446  * proto_tree isn't created by epan_dissect_init().  But that's by
447  * design - if shark doesn't pass in a proto_tree, it's probably for
448  * a good reason and we shouldn't override that. (right?)
449  */
450 void wslua_prime_dfilter(epan_dissect_t *edt) {
451     if (wslua_dfilter && edt && edt->tree) {
452         dfilter_prime_proto_tree(wslua_dfilter, edt->tree);
453     }
454 }
455
456 /*
457  * field extractor registration is tricky, In order to allow
458  * the user to define them in the body of the script we will
459  * populate the Field value with a pointer of the abbrev of it
460  * to later replace it with the hfi.
461  *
462  * This will be added to the wanted_fields array that will
463  * exists only while they can be defined, and be cleared right
464  * after the fields are primed.
465  */
466
467 void lua_prime_all_fields(proto_tree* tree _U_) {
468     GString* fake_tap_filter = g_string_new("frame");
469     guint i;
470     static gboolean fake_tap = FALSE;
471
472     for(i=0; i < wanted_fields->len; i++) {
473         Field f = (Field)g_ptr_array_index(wanted_fields,i);
474         gchar* name = *((gchar**)f);
475
476         *f = proto_registrar_get_byname(name);
477
478         if (!*f) {
479             report_failure("Could not find field `%s'",name);
480             *f = NULL;
481             g_free(name);
482             continue;
483         }
484
485         g_free(name);
486
487         g_string_append_printf(fake_tap_filter," || %s",(*f)->abbrev);
488         fake_tap = TRUE;
489     }
490
491     g_ptr_array_free(wanted_fields,TRUE);
492     wanted_fields = NULL;
493
494     if (fake_tap) {
495         /* a boring tap :-) */
496         GString* error = register_tap_listener("frame",
497                 &fake_tap,
498                 fake_tap_filter->str,
499                 0, /* XXX - do we need the protocol tree or columns? */
500                 NULL, NULL, NULL);
501
502         if (error) {
503             report_failure("while registering lua_fake_tap:\n%s",error->str);
504             g_string_free(error,TRUE);
505         } else {
506             if (wslua_dfilter) {
507                 dfilter_free(wslua_dfilter);
508                 wslua_dfilter = NULL;
509             }
510             if (!dfilter_compile(fake_tap_filter->str, &wslua_dfilter)) {
511                 report_failure("while compiling dfilter for wslua: '%s'", fake_tap_filter->str);
512             }
513         }
514     }
515
516 }
517
518 WSLUA_CONSTRUCTOR Field_new(lua_State *L) {
519     /*
520        Create a Field extractor.
521        */
522 #define WSLUA_ARG_Field_new_FIELDNAME 1 /* The filter name of the field (e.g. ip.addr) */
523     const gchar* name = luaL_checkstring(L,WSLUA_ARG_Field_new_FIELDNAME);
524     Field f;
525
526     if (!proto_registrar_get_byname(name) && !wslua_is_field_available(L, name)) {
527         WSLUA_ARG_ERROR(Field_new,FIELDNAME,"a field with this name must exist");
528         return 0;
529     }
530
531     if (!wanted_fields) {
532         WSLUA_ERROR(Field_new,"A Field extractor must be defined before Taps or Dissectors get called");
533         return 0;
534     }
535
536     f = (Field)g_malloc(sizeof(void*));
537     *f = (header_field_info*)(void*)g_strdup(name); /* cheating */
538
539     g_ptr_array_add(wanted_fields,f);
540
541     pushField(L,f);
542     WSLUA_RETURN(1); /* The field extractor */
543 }
544
545 WSLUA_CONSTRUCTOR Field_list(lua_State *L) {
546     /* Gets a Lua array table of all registered field filter names.
547
548        NOTE: this is an expensive operation, and should only be used for troubleshooting.
549
550        @since 1.11.3
551      */
552     void *cookie, *cookie2;
553     int i = -1;
554     int count = 0;
555     header_field_info *hfinfo = NULL;
556
557     lua_newtable(L);
558
559     for (i = proto_get_first_protocol(&cookie); i != -1;
560          i = proto_get_next_protocol(&cookie)) {
561
562         for (hfinfo = proto_get_first_protocol_field(i, &cookie2); hfinfo != NULL;
563          hfinfo = proto_get_next_protocol_field(i, &cookie2)) {
564
565             if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
566                 continue;
567
568             count++;
569             lua_pushstring(L,hfinfo->abbrev);
570             lua_rawseti(L,1,count);
571         }
572     }
573
574     WSLUA_RETURN(1); /* The array table of field filter names */
575 }
576
577 WSLUA_METAMETHOD Field__call (lua_State* L) {
578     /* Obtain all values (see `FieldInfo`) for this field. */
579     Field f = checkField(L,1);
580     header_field_info* in = *f;
581     int items_found = 0;
582
583     if (! in) {
584         luaL_error(L,"invalid field");
585         return 0;
586     }
587
588     if (! lua_pinfo ) {
589         WSLUA_ERROR(Field__call,"Fields cannot be used outside dissectors or taps");
590         return 0;
591     }
592
593     while (in) {
594         GPtrArray* found = proto_get_finfo_ptr_array(lua_tree->tree, in->id);
595         guint i;
596         if (found) {
597             for (i=0; i<found->len; i++) {
598                 FieldInfo fi = (FieldInfo)g_malloc(sizeof(struct _wslua_field_info));
599                 fi->ws_fi = (field_info *)g_ptr_array_index(found,i);
600                 fi->expired = FALSE;
601
602                 PUSH_FIELDINFO(L,fi);
603                 items_found++;
604             }
605         }
606         in = (in->same_name_prev_id != -1) ? proto_registrar_get_nth(in->same_name_prev_id) : NULL;
607     }
608
609     WSLUA_RETURN(items_found); /* All the values of this field */
610 }
611
612 WSLUA_METAMETHOD Field__tostring(lua_State* L) {
613     /* Obtain a string with the field name. */
614     Field f = checkField(L,1);
615
616     if (wanted_fields) {
617         lua_pushstring(L,*((gchar**)f));
618     } else {
619         lua_pushstring(L,(*f)->abbrev);
620     }
621
622     return 1;
623 }
624
625 static int Field__gc(lua_State* L _U_) {
626     /* do NOT free Field */
627     return 0;
628 }
629
630 WSLUA_METHODS Field_methods[] = {
631     WSLUA_CLASS_FNREG(Field,new),
632     WSLUA_CLASS_FNREG(Field,list),
633     { NULL, NULL }
634 };
635
636 WSLUA_META Field_meta[] = {
637     WSLUA_CLASS_MTREG(Field,tostring),
638     WSLUA_CLASS_MTREG(Field,call),
639     { NULL, NULL }
640 };
641
642 int Field_register(lua_State* L) {
643
644     wanted_fields = g_ptr_array_new();
645
646     WSLUA_REGISTER_CLASS(Field);
647     outstanding_FieldInfo = g_ptr_array_new();
648
649     return 0;
650 }
651
652 /*
653  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
654  *
655  * Local variables:
656  * c-basic-offset: 4
657  * tab-width: 8
658  * indent-tabs-mode: nil
659  * End:
660  *
661  * vi: set shiftwidth=4 tabstop=8 expandtab:
662  * :indentSize=4:tabSize=8:noTabs=true:
663  */