We always HAVE_CONFIG_H so don't bother checking whether we have it or not.
[metze/wireshark/wip.git] / epan / wslua / wslua_pinfo.c
1 /*
2  * wslua_pinfo.c
3  *
4  * Wireshark's interface to the Lua Programming Language
5  *
6  * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
7  * (c) 2008, Balint Reczey <balint.reczey@ericsson.com>
8  * (c) 2011, Stig Bjorlykke <stig@bjorlykke.org>
9  *
10  * $Id$
11  *
12  * Wireshark - Network traffic analyzer
13  * By Gerald Combs <gerald@wireshark.org>
14  * Copyright 1998 Gerald Combs
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29  */
30
31 #include "config.h"
32
33 /* WSLUA_MODULE Pinfo Obtaining packet information */
34
35
36 #include "wslua.h"
37
38 #include <epan/addr_resolv.h>
39 #include <string.h>
40
41
42 /*
43  * Track pointers to wireshark's structures.
44  * see comment on wslua_tvb.c
45  */
46
47 static GPtrArray* outstanding_Pinfo = NULL;
48 static GPtrArray* outstanding_Column = NULL;
49 static GPtrArray* outstanding_Columns = NULL;
50 static GPtrArray* outstanding_PrivateTable = NULL;
51
52 CLEAR_OUTSTANDING(Pinfo,expired, TRUE)
53 CLEAR_OUTSTANDING(Column,expired, TRUE)
54 CLEAR_OUTSTANDING(Columns,expired, TRUE)
55 CLEAR_OUTSTANDING(PrivateTable,expired, TRUE)
56
57 Pinfo* push_Pinfo(lua_State* L, packet_info* ws_pinfo) {
58     Pinfo pinfo = NULL;
59     if (ws_pinfo) {
60         pinfo = g_malloc(sizeof(struct _wslua_pinfo));
61         pinfo->ws_pinfo = ws_pinfo;
62         pinfo->expired = FALSE;
63         g_ptr_array_add(outstanding_Pinfo,pinfo);
64     }
65     return pushPinfo(L,pinfo);
66 }
67
68 #define PUSH_COLUMN(L,c) {g_ptr_array_add(outstanding_Column,c);pushColumn(L,c);}
69 #define PUSH_COLUMNS(L,c) {g_ptr_array_add(outstanding_Columns,c);pushColumns(L,c);}
70 #define PUSH_PRIVATE_TABLE(L,c) {g_ptr_array_add(outstanding_PrivateTable,c);pushPrivateTable(L,c);}
71
72 WSLUA_CLASS_DEFINE(NSTime,NOP,NOP);
73         /* NSTime represents a nstime_t.  This is an object with seconds and nano seconds. */
74
75 WSLUA_CONSTRUCTOR NSTime_new(lua_State *L) {
76         /* Creates a new NSTime object */
77 #define WSLUA_OPTARG_NSTime_new_SECONDS 1 /* Seconds */
78 #define WSLUA_OPTARG_NSTime_new_NSECONDS 2 /* Nano seconds */
79     NSTime time = g_malloc(sizeof(nstime_t));
80
81     if (!time) return 0;
82
83     time->secs = (time_t) luaL_optint(L,WSLUA_OPTARG_NSTime_new_SECONDS,0);
84     time->nsecs = luaL_optint(L,WSLUA_OPTARG_NSTime_new_NSECONDS,0);
85
86     pushNSTime(L,time);
87
88     WSLUA_RETURN(1); /* The new NSTime object. */
89 }
90
91 WSLUA_METAMETHOD NSTime__tostring(lua_State* L) {
92     NSTime nstime = checkNSTime(L,1);
93
94     if (!nstime) return 0;
95
96     lua_pushstring(L,ep_strdup_printf("%ld.%09d", (long)nstime->secs, nstime->nsecs));
97
98     WSLUA_RETURN(1); /* The string representing the nstime. */
99 }
100 WSLUA_METAMETHOD NSTime__add(lua_State* L) { /* Calculates the sum of two NSTimes */
101     NSTime time1 = checkNSTime(L,1);
102     NSTime time2 = checkNSTime(L,2);
103     NSTime time3 = g_malloc (sizeof (nstime_t));
104
105     nstime_sum (time3, time1, time2);
106     pushNSTime (L, time3);
107
108     return 1;
109 }
110
111 WSLUA_METAMETHOD NSTime__sub(lua_State* L) { /* Calculates the diff of two NSTimes */
112     NSTime time1 = checkNSTime(L,1);
113     NSTime time2 = checkNSTime(L,2);
114     NSTime time3 = g_malloc (sizeof (nstime_t));
115
116     nstime_delta (time3, time1, time2);
117     pushNSTime (L, time3);
118
119     return 1;
120 }
121
122 WSLUA_METAMETHOD NSTime__unm(lua_State* L) { /* Calculates the negative NSTime */
123     NSTime time1 = checkNSTime(L,1);
124     NSTime time2 = g_malloc (sizeof (nstime_t));
125
126     nstime_set_zero (time2);
127     nstime_subtract (time2, time1);
128     pushNSTime (L, time2);
129
130     return 1;
131 }
132
133 WSLUA_METAMETHOD NSTime__eq(lua_State* L) { /* Compares two NSTimes */
134     NSTime time1 = checkNSTime(L,1);
135     NSTime time2 = checkNSTime(L,2);
136     gboolean result = FALSE;
137
138     if (!time1 || !time2)
139       WSLUA_ERROR(FieldInfo__eq,"Data source must be the same for both fields");
140
141     if (nstime_cmp(time1, time2) == 0)
142         result = TRUE;
143
144     lua_pushboolean(L,result);
145
146     return 1;
147 }
148
149 WSLUA_METAMETHOD NSTime__le(lua_State* L) { /* Compares two NSTimes */
150     NSTime time1 = checkNSTime(L,1);
151     NSTime time2 = checkNSTime(L,2);
152     gboolean result = FALSE;
153
154     if (!time1 || !time2)
155       WSLUA_ERROR(FieldInfo__eq,"Data source must be the same for both fields");
156
157     if (nstime_cmp(time1, time2) <= 0)
158         result = TRUE;
159
160     lua_pushboolean(L,result);
161
162     return 1;
163 }
164
165 WSLUA_METAMETHOD NSTime__lt(lua_State* L) { /* Compares two NSTimes */
166     NSTime time1 = checkNSTime(L,1);
167     NSTime time2 = checkNSTime(L,2);
168     gboolean result = FALSE;
169
170     if (!time1 || !time2)
171       WSLUA_ERROR(FieldInfo__eq,"Data source must be the same for both fields");
172
173     if (nstime_cmp(time1, time2) < 0)
174         result = TRUE;
175
176     lua_pushboolean(L,result);
177
178     return 1;
179 }
180
181 typedef struct {
182     gchar* name;
183     lua_CFunction get;
184     lua_CFunction set;
185 } nstime_actions_t;
186
187 static int NSTime_get_secs(lua_State* L) {
188     NSTime time = toNSTime(L,1);
189
190     lua_pushnumber (L,(lua_Number)(time->secs));
191
192     return 1;
193 }
194
195 static int NSTime_set_secs(lua_State* L)
196  {
197     NSTime time = toNSTime(L,1);
198     time_t secs = luaL_checkint(L,3);
199
200     time->secs = secs;
201
202     return 0;
203 }
204
205 static int NSTime_get_nsecs(lua_State* L) {
206     NSTime time = toNSTime(L,1);
207
208     lua_pushnumber (L,(lua_Number)(time->nsecs));
209
210     return 1;
211 }
212
213 static int NSTime_set_nsecs(lua_State* L) {
214     NSTime time = toNSTime(L,1);
215     int nsecs = luaL_checkint(L,3);
216
217     time->nsecs = nsecs;
218
219     return 0;
220 }
221
222 static const nstime_actions_t nstime_actions[] = {
223     /* WSLUA_ATTRIBUTE NSTime_secs RW The NSTime seconds */
224     {"secs", NSTime_get_secs, NSTime_set_secs},
225
226     /* WSLUA_ATTRIBUTE NSTime_nsecs RW The NSTime nano seconds */
227     {"nsecs", NSTime_get_nsecs, NSTime_set_nsecs},
228
229     {NULL,NULL,NULL}
230 };
231
232 static int NSTime__index(lua_State* L) {
233     NSTime time = checkNSTime(L,1);
234     const gchar* name = luaL_checkstring(L,2);
235     const nstime_actions_t* pa;
236
237     if (! (time && name) ) return 0;
238
239     for (pa = nstime_actions; pa->name; pa++) {
240         if ( g_str_equal(name,pa->name) ) {
241             if (pa->get) {
242                 return pa->get(L);
243             } else {
244                 luaL_error(L,"You cannot get the `%s' attribute of a nstime",name);
245                 return 0;
246             }
247         }
248     }
249
250     luaL_error(L,"A protocol doesn't have a `%s' nstime",name);
251     return 0;
252 }
253
254 static int NSTime__newindex(lua_State* L) {
255     NSTime time = checkNSTime(L,1);
256     const gchar* name = luaL_checkstring(L,2);
257     const nstime_actions_t* pa;
258
259     if (! (time && name) ) return 0;
260
261     for (pa = nstime_actions; pa->name; pa++) {
262         if ( g_str_equal(name,pa->name) ) {
263             if (pa->set) {
264                 return pa->set(L);
265             } else {
266                 luaL_error(L,"You cannot set the `%s' attribute of a nstime",name);
267                 return 0;
268             }
269         }
270     }
271
272     luaL_error(L,"A protocol doesn't have a `%s' nstime",name);
273     return 0;
274 }
275
276 static int NSTime__gc(lua_State* L) {
277     NSTime nstime = checkNSTime(L,1);
278
279     if (!nstime) return 0;
280
281     g_free (nstime);
282     return 0;
283 }
284
285 WSLUA_META NSTime_meta[] = {
286     {"__index", NSTime__index},
287     {"__newindex", NSTime__newindex},
288     {"__tostring", NSTime__tostring},
289     {"__add", NSTime__add},
290     {"__sub", NSTime__sub},
291     {"__unm", NSTime__unm},
292     {"__eq", NSTime__eq},
293     {"__le", NSTime__le},
294     {"__lt", NSTime__lt},
295     {"__gc", NSTime__gc},
296     { NULL, NULL}
297 };
298
299 int NSTime_register(lua_State* L) {
300     WSLUA_REGISTER_META(NSTime);
301
302     lua_pushcfunction(L, NSTime_new);
303     lua_setglobal(L, "NSTime");
304
305     return 1;
306 }
307
308 WSLUA_CLASS_DEFINE(Address,NOP,NOP); /* Represents an address */
309
310 WSLUA_CONSTRUCTOR Address_ip(lua_State* L) {
311         /* Creates an Address Object representing an IP address. */
312
313 #define WSLUA_ARG_Address_ip_HOSTNAME 1 /* The address or name of the IP host. */
314     Address addr = g_malloc(sizeof(address));
315     guint32* ip_addr = g_malloc(sizeof(guint32));
316     const gchar* name = luaL_checkstring(L,WSLUA_ARG_Address_ip_HOSTNAME);
317
318     if (! get_host_ipaddr(name, (guint32*)ip_addr)) {
319         *ip_addr = 0;
320     }
321
322     SET_ADDRESS(addr, AT_IPv4, 4, ip_addr);
323     pushAddress(L,addr);
324     WSLUA_RETURN(1); /* The Address object */
325 }
326
327 #if 0
328 /* TODO */
329 static int Address_ipv6(lua_State* L) {
330     Address addr = g_malloc(sizeof(address));
331
332     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
333
334     pushAddress(L,addr);
335     return 1;
336 }
337 static int Address_ss7(lua_State* L) {
338     Address addr = g_malloc(sizeof(address));
339
340     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
341
342     pushAddress(L,addr);
343     return 1;
344 }
345 static int Address_eth(lua_State* L) {
346     Address addr = g_malloc(sizeof(address));
347
348     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
349
350     pushAddress(L,addr);
351     return 1;
352 }
353 static int Address_sna(lua_State* L) {
354     Address addr = g_malloc(sizeof(address));
355
356     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
357
358     pushAddress(L,addr);
359     return 1;
360 }
361 static int Address_atalk(lua_State* L) {
362     Address addr = g_malloc(sizeof(address));
363
364     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
365
366     pushAddress(L,addr);
367     return 1;
368 }
369 static int Address_vines(lua_State* L) {
370     Address addr = g_malloc(sizeof(address));
371
372     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
373
374     pushAddress(L,addr);
375     return 1;
376 }
377 static int Address_osi(lua_State* L) {
378     Address addr = g_malloc(sizeof(address));
379
380     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
381
382     pushAddress(L,addr);
383     return 1;
384 }
385 static int Address_arcnet(lua_State* L) {
386     Address addr = g_malloc(sizeof(address));
387
388     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
389
390     pushAddress(L,addr);
391     return 1;
392 }
393 static int Address_fc(lua_State* L) {
394     Address addr = g_malloc(sizeof(address));
395
396     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
397
398     pushAddress(L,addr);
399     return 1;
400 }
401 static int Address_string(lua_State* L) {
402     Address addr = g_malloc(sizeof(address));
403
404     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
405
406     pushAddress(L,addr);
407     return 1;
408 }
409 static int Address_eui64(lua_State* L) {
410     Address addr = g_malloc(sizeof(address));
411
412     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
413
414     pushAddress(L,addr);
415     return 1;
416 }
417 static int Address_uri(lua_State* L) {
418     Address addr = g_malloc(sizeof(address));
419
420     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
421
422     pushAddress(L,addr);
423     return 1;
424 }
425 static int Address_tipc(lua_State* L) {
426     Address addr = g_malloc(sizeof(address));
427
428     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
429
430     pushAddress(L,addr);
431     return 1;
432 }
433 #endif
434
435 WSLUA_METHODS Address_methods[] = {
436         {"ip", Address_ip },
437         {"ipv4", Address_ip },
438 #if 0
439     {"ipv6", Address_ipv6 },
440     {"ss7pc", Address_ss7 },
441     {"eth", Address_eth },
442     {"sna", Address_sna },
443     {"atalk", Address_atalk },
444     {"vines", Address_vines },
445     {"osi", Address_osi },
446     {"arcnet", Address_arcnet },
447     {"fc", Address_fc },
448     {"string", Address_string },
449     {"eui64", Address_eui64 },
450     {"uri", Address_uri },
451     {"tipc", Address_tipc },
452 #endif
453     {0,0}
454 };
455
456 WSLUA_METAMETHOD Address__tostring(lua_State* L) {
457     Address addr = checkAddress(L,1);
458
459     lua_pushstring(L,get_addr_name(addr));
460
461     WSLUA_RETURN(1); /* The string representing the address. */
462 }
463
464 static int Address__gc(lua_State* L) {
465     Address addr = checkAddress(L,1);
466
467     if (addr) {
468         g_free((void*)addr->data);
469         g_free((void*)addr);
470     }
471
472     return 0;
473 }
474
475 WSLUA_METAMETHOD Address__eq(lua_State* L) { /* Compares two Addresses */
476     Address addr1 = checkAddress(L,1);
477     Address addr2 = checkAddress(L,2);
478     gboolean result = FALSE;
479
480     if (ADDRESSES_EQUAL(addr1, addr2))
481         result = TRUE;
482
483     lua_pushboolean(L,result);
484
485     return 1;
486 }
487
488 WSLUA_METAMETHOD Address__le(lua_State* L) { /* Compares two Addresses */
489     Address addr1 = checkAddress(L,1);
490     Address addr2 = checkAddress(L,2);
491     gboolean result = FALSE;
492
493     if (CMP_ADDRESS(addr1, addr2) <= 0)
494         result = TRUE;
495
496     lua_pushboolean(L,result);
497
498     return 1;
499 }
500
501 WSLUA_METAMETHOD Address__lt(lua_State* L) { /* Compares two Addresses */
502     Address addr1 = checkAddress(L,1);
503     Address addr2 = checkAddress(L,2);
504     gboolean result = FALSE;
505
506     if (CMP_ADDRESS(addr1, addr2) < 0)
507         result = TRUE;
508
509     lua_pushboolean(L,result);
510
511     return 1;
512 }
513
514 WSLUA_META Address_meta[] = {
515     {"__gc", Address__gc },
516     {"__tostring", Address__tostring },
517     {"__eq",Address__eq},
518     {"__le",Address__le},
519     {"__lt",Address__lt},
520     {0,0}
521 };
522
523
524 int Address_register(lua_State *L) {
525     WSLUA_REGISTER_CLASS(Address);
526     return 1;
527 }
528
529
530 WSLUA_CLASS_DEFINE(Column,FAIL_ON_NULL("expired column"),NOP); /* A Column in the packet list */
531
532 struct col_names_t {
533     const gchar* name;
534     int id;
535 };
536
537 static const struct col_names_t colnames[] = {
538     {"number",COL_NUMBER},
539     {"abs_time",COL_ABS_TIME},
540     {"utc_time",COL_UTC_TIME},
541     {"cls_time",COL_CLS_TIME},
542     {"rel_time",COL_REL_TIME},
543     {"date",COL_ABS_DATE_TIME},
544     {"utc_date",COL_UTC_DATE_TIME},
545     {"delta_time",COL_DELTA_TIME},
546     {"delta_time_displayed",COL_DELTA_TIME_DIS},
547     {"src",COL_DEF_SRC},
548     {"src_res",COL_RES_SRC},
549     {"src_unres",COL_UNRES_SRC},
550     {"dl_src",COL_DEF_DL_SRC},
551     {"dl_src_res",COL_RES_DL_SRC},
552     {"dl_src_unres",COL_UNRES_DL_SRC},
553     {"net_src",COL_DEF_NET_SRC},
554     {"net_src_res",COL_RES_NET_SRC},
555     {"net_src_unres",COL_UNRES_NET_SRC},
556     {"dst",COL_DEF_DST},
557     {"dst_res",COL_RES_DST},
558     {"dst_unres",COL_UNRES_DST},
559     {"dl_dst",COL_DEF_DL_DST},
560     {"dl_dst_res",COL_RES_DL_DST},
561     {"dl_dst_unres",COL_UNRES_DL_DST},
562     {"net_dst",COL_DEF_NET_DST},
563     {"net_dst_res",COL_RES_NET_DST},
564     {"net_dst_unres",COL_UNRES_NET_DST},
565     {"src_port",COL_DEF_SRC_PORT},
566     {"src_port_res",COL_RES_SRC_PORT},
567     {"src_port_unres",COL_UNRES_SRC_PORT},
568     {"dst_port",COL_DEF_DST_PORT},
569     {"dst_port_res",COL_RES_DST_PORT},
570     {"dst_port_unres",COL_UNRES_DST_PORT},
571     {"protocol",COL_PROTOCOL},
572     {"info",COL_INFO},
573     {"packet_len",COL_PACKET_LENGTH},
574     {"cumulative_bytes",COL_CUMULATIVE_BYTES},
575     {"direction",COL_IF_DIR},
576     {"vsan",COL_VSAN},
577     {"tx_rate",COL_TX_RATE},
578     {"rssi",COL_RSSI},
579     {"dce_call",COL_DCE_CALL},
580     {NULL,0}
581 };
582
583 static gint col_name_to_id(const gchar* name) {
584     const struct col_names_t* cn;
585     for(cn = colnames; cn->name; cn++) {
586         if (g_str_equal(cn->name,name)) {
587             return cn->id;
588         }
589     }
590
591     return 0;
592 }
593
594 static const gchar*  col_id_to_name(gint id) {
595     const struct col_names_t* cn;
596     for(cn = colnames; cn->name; cn++) {
597         if ( cn->id == id ) {
598             return cn->name;
599         }
600     }
601     return NULL;
602 }
603
604
605 WSLUA_METAMETHOD Column__tostring(lua_State *L) {
606     Column c = checkColumn(L,1);
607     const gchar* name;
608
609     if (!(c)) {
610         return 0;
611     }
612
613     /* XXX: should return the column's text ! */
614     name = col_id_to_name(c->col);
615     lua_pushstring(L,name ? name : "Unknown Column");
616
617     WSLUA_RETURN(1); /* A string representing the column */
618 }
619
620 static int Column__gc(lua_State* L) {
621     Column col = checkColumn(L,1);
622
623     if (!col) return 0;
624
625     if (!col->expired)
626         col->expired = TRUE;
627     else
628         g_free(col);
629
630     return 0;
631
632 }
633
634 WSLUA_METHOD Column_clear(lua_State *L) {
635         /* Clears a Column */
636     Column c = checkColumn(L,1);
637
638     if (!(c && c->cinfo)) return 0;
639
640     col_clear(c->cinfo, c->col);
641
642     return 0;
643 }
644
645 WSLUA_METHOD Column_set(lua_State *L) {
646         /* Sets the text of a Column */
647 #define WSLUA_ARG_Column_set_TEXT 2 /* The text to which to set the Column */
648     Column c = checkColumn(L,1);
649     const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_set_TEXT);
650
651     if (!(c && c->cinfo))
652         return 0;
653
654     if (!s) WSLUA_ARG_ERROR(Column_set,TEXT,"must be a string");
655
656     col_add_str(c->cinfo, c->col, s);
657
658     return 0;
659 }
660
661 WSLUA_METHOD Column_append(lua_State *L) {
662         /* Appends text to a Column */
663 #define WSLUA_ARG_Column_append_TEXT 2 /* The text to append to the Column */
664     Column c = checkColumn(L,1);
665     const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_append_TEXT);
666
667     if (!(c && c->cinfo))
668         return 0;
669
670     if (!s) WSLUA_ARG_ERROR(Column_append,TEXT,"must be a string");
671
672     col_append_str(c->cinfo, c->col, s);
673
674     return 0;
675 }
676
677 WSLUA_METHOD Column_preppend(lua_State *L) {
678         /* Prepends text to a Column */
679 #define WSLUA_ARG_Column_prepend_TEXT 2 /* The text to prepend to the Column */
680     Column c = checkColumn(L,1);
681     const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_prepend_TEXT);
682
683     if (!(c && c->cinfo))
684         return 0;
685
686     if (!s) WSLUA_ARG_ERROR(Column_prepend,TEXT,"must be a string");
687
688     if (check_col(c->cinfo, c->col))
689         col_prepend_fstr(c->cinfo, c->col, "%s",s);
690
691     return 0;
692 }
693
694 WSLUA_METHODS Column_methods[] = {
695     {"clear", Column_clear },
696     {"set", Column_set },
697     {"append", Column_append },
698     {"preppend", Column_preppend },
699     {0,0}
700 };
701
702
703 WSLUA_META Column_meta[] = {
704     {"__tostring", Column__tostring },
705     {"__gc", Column__gc },
706     {0,0}
707 };
708
709
710 int Column_register(lua_State *L) {
711     WSLUA_REGISTER_CLASS(Column);
712     return 1;
713 }
714
715
716
717
718
719
720 WSLUA_CLASS_DEFINE(Columns,NOP,NOP);
721 /* The Columns of the packet list. */
722
723 WSLUA_METAMETHOD Columns__tostring(lua_State *L) {
724     lua_pushstring(L,"Columns");
725     WSLUA_RETURN(1);
726     /* The string "Columns", no real use, just for debugging purposes. */
727 }
728
729 WSLUA_METAMETHOD Columns__newindex(lua_State *L) {
730         /* Sets the text of a specific column */
731 #define WSLUA_ARG_Columns__newindex_COLUMN 2 /* The name of the column to set */
732 #define WSLUA_ARG_Columns__newindex_TEXT 3 /* The text for the column */
733     Columns cols = checkColumns(L,1);
734     const struct col_names_t* cn;
735     const char* colname;
736     const char* text;
737
738     if (!cols) return 0;
739     if (cols->expired) {
740         luaL_error(L,"expired column");
741         return 0;
742     }
743
744     colname = luaL_checkstring(L,WSLUA_ARG_Columns__newindex_COLUMN);
745     text = luaL_checkstring(L,WSLUA_ARG_Columns__newindex_TEXT);
746
747     for(cn = colnames; cn->name; cn++) {
748         if( g_str_equal(cn->name,colname) ) {
749             col_add_str(cols->cinfo, cn->id, text);
750             return 0;
751         }
752     }
753
754     WSLUA_ARG_ERROR(Columns__newindex,COLUMN,"the column name must be a valid column");
755 }
756
757 WSLUA_METAMETHOD Columns_index(lua_State *L) {
758     Columns cols = checkColumns(L,1);
759     const struct col_names_t* cn;
760     const char* colname = luaL_checkstring(L,2);
761
762     if (!cols) {
763         Column c = g_malloc(sizeof(struct _wslua_col_info));
764         c->cinfo = NULL;
765         c->col = col_name_to_id(colname);
766         c->expired = FALSE;
767
768         PUSH_COLUMN(L,c);
769         return 1;
770     }
771
772
773     if (cols->expired) {
774         luaL_error(L,"expired column");
775         return 0;
776     }
777
778     if (!colname) return 0;
779
780     for(cn = colnames; cn->name; cn++) {
781         if( g_str_equal(cn->name,colname) ) {
782             Column c = g_malloc(sizeof(struct _wslua_col_info));
783             c->cinfo = cols->cinfo;
784             c->col = col_name_to_id(colname);
785             c->expired = FALSE;
786
787             PUSH_COLUMN(L,c);
788             return 1;
789         }
790     }
791
792     return 0;
793 }
794
795 static int Columns_gc(lua_State* L) {
796     Columns cols = checkColumns(L,1);
797
798     if (!cols) return 0;
799
800     if (!cols->expired)
801         cols->expired = TRUE;
802     else
803         g_free(cols);
804
805     return 0;
806
807 }
808
809
810 static const luaL_Reg Columns_meta[] = {
811     {"__tostring", Columns__tostring },
812     {"__newindex", Columns__newindex },
813     {"__index",  Columns_index},
814     {"__gc",  Columns_gc},
815     { NULL, NULL }
816 };
817
818
819 int Columns_register(lua_State *L) {
820     WSLUA_REGISTER_META(Columns);
821     return 1;
822 }
823
824 WSLUA_CLASS_DEFINE(PrivateTable,NOP,NOP);
825         /* PrivateTable represents the pinfo->private_table. */
826
827 WSLUA_METAMETHOD PrivateTable__tostring(lua_State* L) {
828     PrivateTable priv = checkPrivateTable(L,1);
829     GString *key_string;
830     GList *keys, *key;
831
832     if (!priv) return 0;
833
834     key_string = g_string_new ("");
835     keys = g_hash_table_get_keys (priv->table);
836     key = g_list_first (keys);
837     while (key) {
838         key_string = g_string_append (key_string, key->data);
839         key = g_list_next (key);
840         if (key) {
841             key_string = g_string_append_c (key_string, ',');
842         }
843     }
844
845     lua_pushstring(L,key_string->str);
846
847     g_string_free (key_string, TRUE);
848     g_list_free (keys);
849
850     WSLUA_RETURN(1); /* A string with all keys in the table, mostly for debugging. */
851 }
852
853 static int PrivateTable__index(lua_State* L) {
854         /* Gets the text of a specific entry */
855     PrivateTable priv = checkPrivateTable(L,1);
856     const gchar* name = luaL_checkstring(L,2);
857     const gchar* string;
858
859     if (! (priv && name) ) return 0;
860
861     if (priv->expired) {
862         luaL_error(L,"expired private_table");
863         return 0;
864     }
865
866     string = g_hash_table_lookup (priv->table, (gpointer) name);
867
868     if (string) {
869         lua_pushstring(L, string);
870     } else {
871         lua_pushnil(L);
872     }
873
874     return 1;
875 }
876
877 static int PrivateTable__newindex(lua_State* L) {
878         /* Sets the text of a specific entry */
879     PrivateTable priv = checkPrivateTable(L,1);
880     const gchar* name = luaL_checkstring(L,2);
881     const gchar* string = NULL;
882
883     if (! (priv && name) ) return 0;
884
885     if (priv->expired) {
886         luaL_error(L,"expired private_table");
887         return 0;
888     }
889
890     if (lua_isstring(L,3)) {
891         /* This also catches numbers, which is converted to string */
892         string = luaL_checkstring(L,3);
893     } else if (lua_isboolean(L,3)) {
894         /* We support boolean by setting a empty string if true and NULL if false */
895         string = lua_toboolean(L,3) ? "" : NULL;
896     } else if (!lua_isnil(L,3)) {
897         luaL_error(L,"unsupported type: %s", lua_typename(L,3));
898         return 0;
899     }
900
901     if (string) {
902       g_hash_table_replace (priv->table, (gpointer) ep_strdup(name), (gpointer) ep_strdup(string));
903     } else {
904       g_hash_table_remove (priv->table, (gpointer) name);
905     }
906
907     return 1;
908 }
909
910 static int PrivateTable__gc(lua_State* L) {
911     PrivateTable priv = checkPrivateTable(L,1);
912
913     if (!priv) return 0;
914
915     if (!priv->expired) {
916         priv->expired = TRUE;
917     } else {
918         if (priv->is_allocated) {
919             g_hash_table_destroy (priv->table);
920         }
921         g_free(priv);
922     }
923
924     return 0;
925 }
926
927 WSLUA_META PrivateTable_meta[] = {
928     {"__index", PrivateTable__index},
929     {"__newindex", PrivateTable__newindex},
930     {"__tostring", PrivateTable__tostring},
931     {"__gc", PrivateTable__gc},
932     { NULL, NULL}
933 };
934
935 int PrivateTable_register(lua_State* L) {
936     WSLUA_REGISTER_META(PrivateTable);
937     return 1;
938 }
939
940
941 WSLUA_CLASS_DEFINE(Pinfo,FAIL_ON_NULL("expired pinfo"),NOP);
942 /* Packet information */
943
944 static int Pinfo_tostring(lua_State *L) { lua_pushstring(L,"a Pinfo"); return 1; }
945
946 #define PINFO_GET_BOOLEAN(name,val) static int name(lua_State *L) {  \
947     Pinfo pinfo = checkPinfo(L,1); \
948     if (!pinfo) return 0;\
949     if (pinfo->expired) { \
950         luaL_error(L,"expired_pinfo"); \
951         return 0; \
952     } \
953     lua_pushboolean(L,val);\
954     return 1;\
955 }
956
957 #define PINFO_GET_NUMBER(name,val) static int name(lua_State *L) {  \
958     Pinfo pinfo = checkPinfo(L,1); \
959     if (!pinfo) return 0;\
960     if (pinfo->expired) { \
961         luaL_error(L,"expired_pinfo"); \
962         return 0; \
963     } \
964     lua_pushnumber(L,(lua_Number)(val));\
965     return 1;\
966 }
967
968 #define PINFO_GET_STRING(name,val) static int name(lua_State *L) { \
969     Pinfo pinfo = checkPinfo(L,1); \
970     const gchar* value; \
971     if (!pinfo) return 0; \
972     if (pinfo->expired) { \
973         luaL_error(L,"expired_pinfo"); \
974         return 0; \
975     } \
976     value = val; \
977     if (value) lua_pushstring(L,(const char*)(value)); else lua_pushnil(L); \
978     return 1; \
979 }
980
981 #define PINFO_GET_ADDRESS(name,role) static int name(lua_State *L) { \
982     Pinfo pinfo = checkPinfo(L,1); \
983     Address addr; \
984     if (!pinfo) return 0; \
985     if (pinfo->expired) { \
986         luaL_error(L,"expired_pinfo"); \
987         return 0; \
988     } \
989     addr = g_new(address,1); \
990     COPY_ADDRESS(addr, &(pinfo->ws_pinfo->role)); \
991     pushAddress(L,addr); \
992     return 1; \
993 }
994
995 #define PINFO_GET_LIGHTUSERDATA(name, val) static int name(lua_State *L) { \
996     Pinfo pinfo = checkPinfo(L, 1); \
997     if (!pinfo) return 0; \
998     if (pinfo->expired) { \
999         luaL_error(L, "expired_pinfo"); \
1000         return 0; \
1001     } \
1002     lua_pushlightuserdata(L, (void *) (val)); \
1003     return 1; \
1004 }
1005
1006 PINFO_GET_BOOLEAN(Pinfo_fragmented,pinfo->ws_pinfo->fragmented)
1007 PINFO_GET_BOOLEAN(Pinfo_in_error_pkt,pinfo->ws_pinfo->flags.in_error_pkt)
1008 PINFO_GET_BOOLEAN(Pinfo_visited,pinfo->ws_pinfo->fd->flags.visited)
1009
1010 PINFO_GET_NUMBER(Pinfo_number,pinfo->ws_pinfo->fd->num)
1011 PINFO_GET_NUMBER(Pinfo_len,pinfo->ws_pinfo->fd->pkt_len)
1012 PINFO_GET_NUMBER(Pinfo_caplen,pinfo->ws_pinfo->fd->cap_len)
1013 PINFO_GET_NUMBER(Pinfo_abs_ts,(((double)pinfo->ws_pinfo->fd->abs_ts.secs) + (((double)pinfo->ws_pinfo->fd->abs_ts.nsecs) / 1000000000.0) ))
1014 PINFO_GET_NUMBER(Pinfo_rel_ts,(((double)pinfo->ws_pinfo->fd->rel_ts.secs) + (((double)pinfo->ws_pinfo->fd->rel_ts.nsecs) / 1000000000.0) ))
1015 PINFO_GET_NUMBER(Pinfo_delta_ts,(((double)pinfo->ws_pinfo->fd->del_cap_ts.secs) + (((double)pinfo->ws_pinfo->fd->del_cap_ts.nsecs) / 1000000000.0) ))
1016 PINFO_GET_NUMBER(Pinfo_delta_dis_ts,(((double)pinfo->ws_pinfo->fd->del_dis_ts.secs) + (((double)pinfo->ws_pinfo->fd->del_dis_ts.nsecs) / 1000000000.0) ))
1017 PINFO_GET_NUMBER(Pinfo_ipproto,pinfo->ws_pinfo->ipproto)
1018 PINFO_GET_NUMBER(Pinfo_circuit_id,pinfo->ws_pinfo->circuit_id)
1019 PINFO_GET_NUMBER(Pinfo_desegment_len,pinfo->ws_pinfo->desegment_len)
1020 PINFO_GET_NUMBER(Pinfo_desegment_offset,pinfo->ws_pinfo->desegment_offset)
1021 PINFO_GET_NUMBER(Pinfo_ptype,pinfo->ws_pinfo->ptype)
1022 PINFO_GET_NUMBER(Pinfo_src_port,pinfo->ws_pinfo->srcport)
1023 PINFO_GET_NUMBER(Pinfo_dst_port,pinfo->ws_pinfo->destport)
1024 PINFO_GET_NUMBER(Pinfo_ethertype,pinfo->ws_pinfo->ethertype)
1025 PINFO_GET_NUMBER(Pinfo_match_uint,pinfo->ws_pinfo->match_uint)
1026
1027 PINFO_GET_STRING(Pinfo_curr_proto,pinfo->ws_pinfo->current_proto)
1028 PINFO_GET_STRING(Pinfo_match_string,pinfo->ws_pinfo->match_string)
1029
1030 PINFO_GET_ADDRESS(Pinfo_net_src,net_src)
1031 PINFO_GET_ADDRESS(Pinfo_net_dst,net_dst)
1032 PINFO_GET_ADDRESS(Pinfo_dl_src,dl_src)
1033 PINFO_GET_ADDRESS(Pinfo_dl_dst,dl_dst)
1034 PINFO_GET_ADDRESS(Pinfo_src,src)
1035 PINFO_GET_ADDRESS(Pinfo_dst,dst)
1036
1037 PINFO_GET_LIGHTUSERDATA(Pinfo_private_data, pinfo->ws_pinfo->private_data)
1038
1039 static int Pinfo_match(lua_State *L) {
1040     Pinfo pinfo = checkPinfo(L,1);
1041
1042     if (!pinfo) return 0;
1043     if (pinfo->expired) {
1044         luaL_error(L,"expired_pinfo");
1045         return 0;
1046     }
1047
1048     if (pinfo->ws_pinfo->match_string) {
1049         lua_pushstring(L,pinfo->ws_pinfo->match_string);
1050     } else {
1051         lua_pushnumber(L,(lua_Number)(pinfo->ws_pinfo->match_uint));
1052     }
1053
1054     return 1;
1055 }
1056
1057 static int Pinfo_columns(lua_State *L) {
1058     Columns cols = NULL;
1059     Pinfo pinfo = checkPinfo(L,1);
1060     const gchar* colname = luaL_optstring(L,2,NULL);
1061
1062     if (pinfo->expired) {
1063         luaL_error(L,"expired_pinfo");
1064         return 0;
1065     }
1066
1067     cols = g_malloc(sizeof(struct _wslua_cols));
1068     cols->cinfo = pinfo->ws_pinfo->cinfo;
1069     cols->expired = FALSE;
1070
1071     if (!colname) {
1072         PUSH_COLUMNS(L,cols);
1073     } else {
1074         lua_settop(L,0);
1075         PUSH_COLUMNS(L,cols);
1076         lua_pushstring(L,colname);
1077         return Columns_index(L);
1078     }
1079     return 1;
1080 }
1081
1082 static int Pinfo_private(lua_State *L) {
1083     PrivateTable priv = NULL;
1084     Pinfo pinfo = checkPinfo(L,1);
1085     const gchar* privname = luaL_optstring(L,2,NULL);
1086     gboolean is_allocated = FALSE;
1087
1088     if (!pinfo) return 0;
1089
1090     if (pinfo->expired) {
1091         luaL_error(L,"expired private_table");
1092         return 0;
1093     }
1094
1095     if (!pinfo->ws_pinfo->private_table) {
1096         pinfo->ws_pinfo->private_table = g_hash_table_new(g_str_hash,g_str_equal);
1097         is_allocated = TRUE;
1098     }
1099
1100     priv = g_malloc(sizeof(struct _wslua_private_table));
1101     priv->table = pinfo->ws_pinfo->private_table;
1102     priv->is_allocated = is_allocated;
1103     priv->expired = FALSE;
1104
1105     if (!privname) {
1106         PUSH_PRIVATE_TABLE(L,priv);
1107     } else {
1108         lua_settop(L,0);
1109         PUSH_PRIVATE_TABLE(L,priv);
1110         lua_pushstring(L,privname);
1111         return PrivateTable__index(L);
1112     }
1113     return 1;
1114 }
1115
1116 typedef enum {
1117     PARAM_NONE,
1118     PARAM_ADDR_SRC,
1119     PARAM_ADDR_DST,
1120     PARAM_ADDR_DL_SRC,
1121     PARAM_ADDR_DL_DST,
1122     PARAM_ADDR_NET_SRC,
1123     PARAM_ADDR_NET_DST,
1124     PARAM_PORT_SRC,
1125     PARAM_PORT_DST,
1126     PARAM_CIRCUIT_ID,
1127     PARAM_DESEGMENT_LEN,
1128     PARAM_DESEGMENT_OFFSET,
1129     PARAM_PORT_TYPE,
1130     PARAM_ETHERTYPE
1131 } pinfo_param_type_t;
1132
1133 static int pushnil_param(lua_State* L, packet_info* pinfo _U_, pinfo_param_type_t pt _U_ ) {
1134     lua_pushnil(L);
1135     return 1;
1136 }
1137
1138 static int Pinfo_set_addr(lua_State* L, packet_info* pinfo, pinfo_param_type_t pt) {
1139     const address* from = checkAddress(L,1);
1140     address* to;
1141
1142     if (! from ) {
1143         luaL_error(L,"Not an OK address");
1144         return 0;
1145     }
1146
1147     if (!pinfo) {
1148         luaL_error(L,"expired_pinfo");
1149         return 0;
1150     }
1151
1152     switch(pt) {
1153         case PARAM_ADDR_SRC:
1154             to = &(pinfo->src);
1155             break;
1156         case PARAM_ADDR_DST:
1157             to = &(pinfo->dst);
1158             break;
1159         case PARAM_ADDR_DL_SRC:
1160             to = &(pinfo->dl_src);
1161             break;
1162         case PARAM_ADDR_DL_DST:
1163             to = &(pinfo->dl_dst);
1164             break;
1165         case PARAM_ADDR_NET_SRC:
1166             to = &(pinfo->net_src);
1167             break;
1168         case PARAM_ADDR_NET_DST:
1169             to = &(pinfo->net_dst);
1170             break;
1171         default:
1172             g_assert(!"BUG: A bad parameter");
1173             return 0;
1174     }
1175
1176     COPY_ADDRESS(to,from);
1177     return 0;
1178 }
1179
1180 static int Pinfo_set_int(lua_State* L, packet_info* pinfo, pinfo_param_type_t pt) {
1181     gint64 v = luaL_checkint(L,1);
1182
1183     if (!pinfo) {
1184         luaL_error(L,"expired_pinfo");
1185         return 0;
1186     }
1187
1188     switch(pt) {
1189         case PARAM_PORT_SRC:
1190             pinfo->srcport = (guint32)v;
1191             return 0;
1192         case PARAM_PORT_DST:
1193             pinfo->destport = (guint32)v;
1194             return 0;
1195         case PARAM_CIRCUIT_ID:
1196             pinfo->circuit_id = (guint32)v;
1197             return 0;
1198         case PARAM_DESEGMENT_LEN:
1199             pinfo->desegment_len = (guint32)v;
1200             return 0;
1201         case PARAM_DESEGMENT_OFFSET:
1202             pinfo->desegment_offset = (int)v;
1203             return 0;
1204         case PARAM_ETHERTYPE:
1205             pinfo->ethertype = (guint32)v;
1206             return 0;
1207         default:
1208             g_assert(!"BUG: A bad parameter");
1209     }
1210
1211     return 0;
1212 }
1213
1214 typedef struct _pinfo_method_t {
1215     const gchar* name;
1216     lua_CFunction get;
1217     int (*set)(lua_State*, packet_info*, pinfo_param_type_t);
1218     pinfo_param_type_t param;
1219 } pinfo_method_t;
1220
1221 static int Pinfo_hi(lua_State *L) {
1222     Pinfo pinfo = checkPinfo(L,1);
1223     Address addr;
1224
1225     if (!pinfo) return 0;
1226     if (pinfo->expired) {
1227         luaL_error(L,"expired_pinfo");
1228         return 0;
1229     }
1230
1231     addr = g_malloc(sizeof(address));
1232     if (CMP_ADDRESS(&(pinfo->ws_pinfo->src), &(pinfo->ws_pinfo->dst) ) >= 0) {
1233         COPY_ADDRESS(addr, &(pinfo->ws_pinfo->src));
1234     } else {
1235         COPY_ADDRESS(addr, &(pinfo->ws_pinfo->dst));
1236     }
1237
1238     pushAddress(L,addr);
1239     return 1;
1240 }
1241
1242 static int Pinfo_lo(lua_State *L) {
1243     Pinfo pinfo = checkPinfo(L,1);
1244     Address addr;
1245
1246     if (!pinfo) return 0;
1247     if (pinfo->expired) {
1248         luaL_error(L,"expired_pinfo");
1249         return 0;
1250     }
1251
1252     addr = g_malloc(sizeof(address));
1253     if (CMP_ADDRESS(&(pinfo->ws_pinfo->src), &(pinfo->ws_pinfo->dst) ) < 0) {
1254         COPY_ADDRESS(addr, &(pinfo->ws_pinfo->src));
1255     } else {
1256         COPY_ADDRESS(addr, &(pinfo->ws_pinfo->dst));
1257     }
1258
1259     pushAddress(L,addr);
1260     return 1;
1261 }
1262
1263
1264 static const pinfo_method_t Pinfo_methods[] = {
1265
1266         /* WSLUA_ATTRIBUTE Pinfo_number RO The number of this packet in the current file */
1267     {"number", Pinfo_number, pushnil_param, PARAM_NONE},
1268
1269         /* WSLUA_ATTRIBUTE Pinfo_len  RO The length of the frame */
1270     {"len", Pinfo_len, pushnil_param, PARAM_NONE },
1271
1272         /* WSLUA_ATTRIBUTE Pinfo_caplen RO The captured length of the frame */
1273     {"caplen", Pinfo_caplen, pushnil_param, PARAM_NONE },
1274
1275         /* WSLUA_ATTRIBUTE Pinfo_abs_ts RO When the packet was captured */
1276     {"abs_ts",Pinfo_abs_ts, pushnil_param, PARAM_NONE },
1277
1278         /* WSLUA_ATTRIBUTE Pinfo_rel_ts RO Number of seconds passed since beginning of capture */
1279     {"rel_ts",Pinfo_rel_ts, pushnil_param, PARAM_NONE },
1280
1281         /* WSLUA_ATTRIBUTE Pinfo_delta_ts RO Number of seconds passed since the last captured packet */
1282     {"delta_ts",Pinfo_delta_ts, pushnil_param, PARAM_NONE },
1283
1284         /* WSLUA_ATTRIBUTE Pinfo_delta_dis_ts RO Number of seconds passed since the last displayed packet */
1285     {"delta_dis_ts",Pinfo_delta_dis_ts, pushnil_param, PARAM_NONE },
1286
1287         /* WSLUA_ATTRIBUTE Pinfo_visited RO Whether this packet hass been already visited */
1288     {"visited",Pinfo_visited, pushnil_param, PARAM_NONE },
1289
1290         /* WSLUA_ATTRIBUTE Pinfo_src RW Source Address of this Packet */
1291     {"src", Pinfo_src, Pinfo_set_addr, PARAM_ADDR_SRC },
1292
1293         /* WSLUA_ATTRIBUTE Pinfo_dst RW Destination Address of this Packet */
1294     {"dst", Pinfo_dst, Pinfo_set_addr, PARAM_ADDR_DST },
1295
1296         /* WSLUA_ATTRIBUTE Pinfo_lo RO lower Address of this Packet */
1297     {"lo", Pinfo_lo, pushnil_param, PARAM_NONE },
1298
1299         /* WSLUA_ATTRIBUTE Pinfo_hi RW higher Address of this Packet */
1300     {"hi", Pinfo_hi, pushnil_param, PARAM_NONE },
1301
1302         /* WSLUA_ATTRIBUTE Pinfo_dl_src RW Data Link Source Address of this Packet */
1303     {"dl_src", Pinfo_dl_src, Pinfo_set_addr, PARAM_ADDR_DL_SRC },
1304
1305         /* WSLUA_ATTRIBUTE Pinfo_dl_dst RW Data Link Destination Address of this Packet */
1306     {"dl_dst", Pinfo_dl_dst, Pinfo_set_addr, PARAM_ADDR_DL_DST },
1307
1308         /* WSLUA_ATTRIBUTE Pinfo_net_src RW Network Layer Source Address of this Packet */
1309     {"net_src", Pinfo_net_src, Pinfo_set_addr, PARAM_ADDR_NET_SRC },
1310
1311         /* WSLUA_ATTRIBUTE Pinfo_net_dst RW Network Layer Destination Address of this Packet */
1312     {"net_dst", Pinfo_net_dst, Pinfo_set_addr, PARAM_ADDR_NET_DST },
1313
1314         /* WSLUA_ATTRIBUTE Pinfo_ptype RW Type of Port of .src_port and .dst_port */
1315     {"port_type", Pinfo_ptype, pushnil_param, PARAM_NONE },
1316
1317         /* WSLUA_ATTRIBUTE Pinfo_src_port RW Source Port of this Packet */
1318     {"src_port", Pinfo_src_port, Pinfo_set_int,  PARAM_PORT_SRC },
1319
1320         /* WSLUA_ATTRIBUTE Pinfo_dst_port RW Source Address of this Packet */
1321     {"dst_port", Pinfo_dst_port, Pinfo_set_int,  PARAM_PORT_SRC },
1322
1323         /* WSLUA_ATTRIBUTE Pinfo_ipproto RO IP Protocol id */
1324     {"ipproto", Pinfo_ipproto, pushnil_param,  PARAM_NONE },
1325
1326         /* WSLUA_ATTRIBUTE Pinfo_circuit_id RO For circuit based protocols */
1327     {"circuit_id", Pinfo_circuit_id, Pinfo_set_int, PARAM_CIRCUIT_ID },
1328
1329         /* WSLUA_ATTRIBUTE Pinfo_match RO Port/Data we are matching */
1330     {"match", Pinfo_match, pushnil_param, PARAM_NONE },
1331
1332         /* WSLUA_ATTRIBUTE Pinfo_curr_proto RO Which Protocol are we dissecting */
1333     {"curr_proto", Pinfo_curr_proto, pushnil_param, PARAM_NONE },
1334
1335         /* WSLUA_ATTRIBUTE Pinfo_columns RO Accesss to the packet list columns */
1336     {"columns", Pinfo_columns, pushnil_param, PARAM_NONE },
1337
1338         /* WSLUA_ATTRIBUTE Pinfo_cols RO Accesss to the packet list columns (equivalent to pinfo.columns) */
1339     {"cols", Pinfo_columns, pushnil_param, PARAM_NONE },
1340
1341         /* WSLUA_ATTRIBUTE Pinfo_desegment_len RW Estimated number of additional bytes required for completing the PDU */
1342     {"desegment_len", Pinfo_desegment_len, Pinfo_set_int,  PARAM_DESEGMENT_LEN },
1343
1344         /* WSLUA_ATTRIBUTE Pinfo_desegment_offset RW Offset in the tvbuff at which the dissector will continue processing when next called*/
1345     {"desegment_offset", Pinfo_desegment_offset, Pinfo_set_int,  PARAM_DESEGMENT_OFFSET },
1346
1347         /* WSLUA_ATTRIBUTE Pinfo_private_data RO Access to private data */
1348     {"private_data", Pinfo_private_data, pushnil_param, PARAM_NONE},
1349
1350         /* WSLUA_ATTRIBUTE Pinfo_private RW Access to the private table entries */
1351     {"private", Pinfo_private, pushnil_param, PARAM_NONE},
1352
1353         /* WSLUA_ATTRIBUTE Pinfo_ethertype RW Ethernet Type Code, if this is an Ethernet packet */
1354     {"ethertype", Pinfo_ethertype, Pinfo_set_int, PARAM_ETHERTYPE},
1355
1356         /* WSLUA_ATTRIBUTE Pinfo_fragmented RO If the protocol is only a fragment */
1357     {"fragmented", Pinfo_fragmented, pushnil_param, PARAM_NONE},
1358
1359         /* WSLUA_ATTRIBUTE Pinfo_in_error_pkt RO If we're inside an error packet */
1360     {"in_error_pkt", Pinfo_in_error_pkt, pushnil_param, PARAM_NONE},
1361
1362         /* WSLUA_ATTRIBUTE Pinfo_match_uint RO Matched uint for calling subdissector from table */
1363     {"match_uint", Pinfo_match_uint, pushnil_param, PARAM_NONE },
1364
1365         /* WSLUA_ATTRIBUTE Pinfo_match_string RO Matched string for calling subdissector from table */
1366     {"match_string", Pinfo_match_string, pushnil_param, PARAM_NONE },
1367
1368     {NULL,NULL,NULL,PARAM_NONE}
1369 };
1370
1371
1372 static int pushnil(lua_State* L) {
1373     lua_pushnil(L);
1374     return 1;
1375 }
1376
1377 static int Pinfo_index(lua_State* L) {
1378     Pinfo pinfo = checkPinfo(L,1);
1379     const gchar* name = luaL_checkstring(L,2);
1380     lua_CFunction method = pushnil;
1381     const pinfo_method_t* curr;
1382
1383     if (! (pinfo && name) ) {
1384         lua_pushnil(L);
1385         return 1;
1386     }
1387     if (pinfo->expired) {
1388         luaL_error(L,"expired_pinfo");
1389         return 0;
1390     }
1391
1392     for (curr = Pinfo_methods ; curr->name ; curr++) {
1393         if (g_str_equal(curr->name,name)) {
1394             method = curr->get;
1395             break;
1396         }
1397     }
1398
1399     lua_settop(L,1);
1400     return method(L);
1401 }
1402
1403 static int Pinfo_setindex(lua_State* L) {
1404     Pinfo pinfo = checkPinfo(L,1);
1405     const gchar* name = luaL_checkstring(L,2);
1406     int (*method)(lua_State*, packet_info* pinfo, pinfo_param_type_t) = pushnil_param;
1407     const pinfo_method_t* curr;
1408     pinfo_param_type_t param_type = PARAM_NONE;
1409
1410     if (! (pinfo && name) ) {
1411         return 0;
1412     }
1413     if (pinfo->expired) {
1414         luaL_error(L,"expired_pinfo");
1415         return 0;
1416     }
1417
1418     for (curr = Pinfo_methods ; curr->name ; curr++) {
1419         if (g_str_equal(curr->name,name)) {
1420             method = curr->set;
1421             param_type = curr->param;
1422             break;
1423         }
1424     }
1425
1426     lua_remove(L,1);
1427     lua_remove(L,1);
1428     return method(L,pinfo->ws_pinfo,param_type);
1429 }
1430
1431 static int Pinfo_gc(lua_State* L) {
1432     Pinfo pinfo = checkPinfo(L,1);
1433
1434     if (!pinfo) return 0;
1435
1436     if (!pinfo->expired)
1437         pinfo->expired = TRUE;
1438     else
1439         g_free(pinfo);
1440
1441     return 0;
1442
1443 }
1444
1445 static const luaL_Reg Pinfo_meta[] = {
1446     {"__index", Pinfo_index},
1447     {"__newindex",Pinfo_setindex},
1448     {"__tostring", Pinfo_tostring},
1449     {"__gc", Pinfo_gc},
1450     { NULL, NULL }
1451 };
1452
1453 int Pinfo_register(lua_State* L) {
1454     WSLUA_REGISTER_META(Pinfo);
1455     outstanding_Pinfo = g_ptr_array_new();
1456     outstanding_Column = g_ptr_array_new();
1457     outstanding_Columns = g_ptr_array_new();
1458     outstanding_PrivateTable = g_ptr_array_new();
1459     return 1;
1460 }