Add access to pinfo->desegment_len and pinfo->desegment_offset to Lua API.
[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  *
9  * $Id$
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 /* WSLUA_MODULE Pinfo Obtaining packet information */
31
32
33 #include "wslua.h"
34
35 #include <epan/addr_resolv.h>
36 #include <string.h>
37
38
39 /*
40  * Track pointers to wireshark's structures.
41  * see comment on wslua_tvb.c
42  */
43
44 static GPtrArray* outstanding_Pinfo = NULL;
45 static GPtrArray* outstanding_Column = NULL;
46 static GPtrArray* outstanding_Columns = NULL;
47
48 CLEAR_OUTSTANDING(Pinfo,expired, TRUE)
49 CLEAR_OUTSTANDING(Column,expired, TRUE)
50 CLEAR_OUTSTANDING(Columns,expired, TRUE)
51
52 Pinfo* push_Pinfo(lua_State* L, packet_info* ws_pinfo) {
53     Pinfo pinfo = NULL;
54     if (ws_pinfo) {
55         pinfo = g_malloc(sizeof(struct _wslua_pinfo));
56         pinfo->ws_pinfo = ws_pinfo;
57         pinfo->expired = FALSE;
58         g_ptr_array_add(outstanding_Pinfo,pinfo);
59     }
60     return pushPinfo(L,pinfo);
61 }
62
63 #define PUSH_COLUMN(L,c) {g_ptr_array_add(outstanding_Column,c);pushColumn(L,c);}
64 #define PUSH_COLUMNS(L,c) {g_ptr_array_add(outstanding_Columns,c);pushColumns(L,c);}
65
66 WSLUA_CLASS_DEFINE(Address,NOP,NOP); /* Represents an address */
67
68 WSLUA_CONSTRUCTOR Address_ip(lua_State* L) {
69         /* Creates an Address Object representing an IP address. */
70         
71 #define WSLUA_ARG_Address_ip_HOSTNAME 1 /* The address or name of the IP host. */
72     Address addr = g_malloc(sizeof(address));
73     guint32* ip_addr = g_malloc(sizeof(guint32));
74     const gchar* name = luaL_checkstring(L,WSLUA_ARG_Address_ip_HOSTNAME);
75
76     if (! get_host_ipaddr(name, (guint32*)ip_addr)) {
77         *ip_addr = 0;
78     }
79
80     SET_ADDRESS(addr, AT_IPv4, 4, ip_addr);
81     pushAddress(L,addr);
82     WSLUA_RETURN(1); /* the Address object */
83 }
84
85 #if 0
86 /* TODO */
87 static int Address_ipv6(lua_State* L) {
88     Address addr = g_malloc(sizeof(address));
89
90     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
91
92     pushAddress(L,addr);
93     return 1;
94 }
95 static int Address_ss7(lua_State* L) {
96     Address addr = g_malloc(sizeof(address));
97
98     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
99
100     pushAddress(L,addr);
101     return 1;
102 }
103 static int Address_eth(lua_State* L) {
104     Address addr = g_malloc(sizeof(address));
105
106     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
107
108     pushAddress(L,addr);
109     return 1;
110 }
111 static int Address_sna(lua_State* L) {
112     Address addr = g_malloc(sizeof(address));
113
114     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
115
116     pushAddress(L,addr);
117     return 1;
118 }
119 static int Address_atalk(lua_State* L) {
120     Address addr = g_malloc(sizeof(address));
121
122     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
123
124     pushAddress(L,addr);
125     return 1;
126 }
127 static int Address_vines(lua_State* L) {
128     Address addr = g_malloc(sizeof(address));
129
130     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
131
132     pushAddress(L,addr);
133     return 1;
134 }
135 static int Address_osi(lua_State* L) {
136     Address addr = g_malloc(sizeof(address));
137
138     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
139
140     pushAddress(L,addr);
141     return 1;
142 }
143 static int Address_arcnet(lua_State* L) {
144     Address addr = g_malloc(sizeof(address));
145
146     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
147
148     pushAddress(L,addr);
149     return 1;
150 }
151 static int Address_fc(lua_State* L) {
152     Address addr = g_malloc(sizeof(address));
153
154     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
155
156     pushAddress(L,addr);
157     return 1;
158 }
159 static int Address_string(lua_State* L) {
160     Address addr = g_malloc(sizeof(address));
161
162     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
163
164     pushAddress(L,addr);
165     return 1;
166 }
167 static int Address_eui64(lua_State* L) {
168     Address addr = g_malloc(sizeof(address));
169
170     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
171
172     pushAddress(L,addr);
173     return 1;
174 }
175 static int Address_uri(lua_State* L) {
176     Address addr = g_malloc(sizeof(address));
177
178     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
179
180     pushAddress(L,addr);
181     return 1;
182 }
183 static int Address_tipc(lua_State* L) {
184     Address addr = g_malloc(sizeof(address));
185
186     SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4));
187
188     pushAddress(L,addr);
189     return 1;
190 }
191 #endif
192
193 WSLUA_METHODS Address_methods[] = {
194         {"ip", Address_ip },
195         {"ipv4", Address_ip },
196 #if 0
197     {"ipv6", Address_ipv6 },
198     {"ss7pc", Address_ss7 },
199     {"eth", Address_eth },
200     {"sna", Address_sna },
201     {"atalk", Address_atalk },
202     {"vines", Address_vines },
203     {"osi", Address_osi },
204     {"arcnet", Address_arcnet },
205     {"fc", Address_fc },
206     {"string", Address_string },
207     {"eui64", Address_eui64 },
208     {"uri", Address_uri },
209     {"tipc", Address_tipc },
210 #endif
211     {0,0}
212 };
213
214 WSLUA_METAMETHOD Address__tostring(lua_State* L) {
215     Address addr = checkAddress(L,1);
216
217     lua_pushstring(L,get_addr_name(addr));
218
219     WSLUA_RETURN(1); /* The string representing the address. */
220 }
221
222 static int Address__gc(lua_State* L) {
223     Address addr = checkAddress(L,1);
224
225     if (addr) {
226         if (addr->data) g_free((void*)addr->data);
227         g_free((void*)addr);
228     }
229
230     return 0;
231 }
232
233 WSLUA_METAMETHOD Address__eq(lua_State* L) { /* compares two Addresses */
234     Address addr1 = checkAddress(L,1);
235     Address addr2 = checkAddress(L,2);
236     gboolean result = FALSE;
237
238     if (ADDRESSES_EQUAL(addr1, addr2))
239         result = TRUE;
240
241     lua_pushboolean(L,result);
242
243     return 1;
244 }
245
246 WSLUA_METAMETHOD Address__le(lua_State* L) { /* compares two Addresses */
247     Address addr1 = checkAddress(L,1);
248     Address addr2 = checkAddress(L,2);
249     gboolean result = FALSE;
250
251     if (CMP_ADDRESS(addr1, addr2) <= 0)
252         result = TRUE;
253
254     lua_pushboolean(L,result);
255
256     return 1;
257 }
258
259 WSLUA_METAMETHOD Address__lt(lua_State* L) { /* compares two Addresses */
260     Address addr1 = checkAddress(L,1);
261     Address addr2 = checkAddress(L,2);
262     gboolean result = FALSE;
263
264     if (CMP_ADDRESS(addr1, addr2) < 0)
265         result = TRUE;
266
267     lua_pushboolean(L,result);
268
269     return 1;
270 }
271
272 WSLUA_META Address_meta[] = {
273     {"__gc", Address__gc },
274     {"__tostring", Address__tostring },
275     {"__eq",Address__eq},
276     {"__le",Address__le},
277     {"__lt",Address__lt},
278     {0,0}
279 };
280
281
282 int Address_register(lua_State *L) {
283         WSLUA_REGISTER_CLASS(Address);
284     return 1;
285 }
286
287
288 WSLUA_CLASS_DEFINE(Column,FAIL_ON_NULL("expired column"),NOP); /* A Column in the packet list */
289
290 struct col_names_t {
291     const gchar* name;
292     int id;
293 };
294
295 static const struct col_names_t colnames[] = {
296     {"number",COL_NUMBER},
297     {"abs_time",COL_ABS_TIME},
298     {"cls_time",COL_CLS_TIME},
299     {"rel_time",COL_REL_TIME},
300     {"date",COL_ABS_DATE_TIME},
301     {"delta_time",COL_DELTA_TIME},
302     {"delta_time_displayed",COL_DELTA_TIME_DIS},
303     {"src",COL_DEF_SRC},
304     {"src_res",COL_RES_SRC},
305     {"src_unres",COL_UNRES_SRC},
306     {"dl_src",COL_DEF_DL_SRC},
307     {"dl_src_res",COL_RES_DL_SRC},
308     {"dl_src_unres",COL_UNRES_DL_SRC},
309     {"net_src",COL_DEF_NET_SRC},
310     {"net_src_res",COL_RES_NET_SRC},
311     {"net_src_unres",COL_UNRES_NET_SRC},
312     {"dst",COL_DEF_DST},
313     {"dst_res",COL_RES_DST},
314     {"dst_unres",COL_UNRES_DST},
315     {"dl_dst",COL_DEF_DL_DST},
316     {"dl_dst_res",COL_RES_DL_DST},
317     {"dl_dst_unres",COL_UNRES_DL_DST},
318     {"net_dst",COL_DEF_NET_DST},
319     {"net_dst_res",COL_RES_NET_DST},
320     {"net_dst_unres",COL_UNRES_NET_DST},
321     {"src_port",COL_DEF_SRC_PORT},
322     {"src_port_res",COL_RES_SRC_PORT},
323     {"src_port_unres",COL_UNRES_SRC_PORT},
324     {"dst_port",COL_DEF_DST_PORT},
325     {"dst_port_res",COL_RES_DST_PORT},
326     {"dst_port_unres",COL_UNRES_DST_PORT},
327     {"protocol",COL_PROTOCOL},
328     {"info",COL_INFO},
329     {"packet_len",COL_PACKET_LENGTH},
330     {"cumulative_bytes",COL_CUMULATIVE_BYTES},
331     {"oxid",COL_OXID},
332     {"rxid",COL_RXID},
333     {"direction",COL_IF_DIR},
334     {"circuit_id",COL_CIRCUIT_ID},
335     {"src_idx",COL_SRCIDX},
336     {"dst_idx",COL_DSTIDX},
337     {"vsan",COL_VSAN},
338     {"tx_rate",COL_TX_RATE},
339     {"rssi",COL_RSSI},
340     {"hpux_subsys",COL_HPUX_SUBSYS},
341     {"hpux_devid",COL_HPUX_DEVID},
342     {"dce_call",COL_DCE_CALL},
343     {NULL,0}
344 };
345
346 static gint col_name_to_id(const gchar* name) {
347     const struct col_names_t* cn;
348     for(cn = colnames; cn->name; cn++) {
349         if (g_str_equal(cn->name,name)) {
350             return cn->id;
351         }
352     }
353
354     return 0;
355 }
356
357 static const gchar*  col_id_to_name(gint id) {
358     const struct col_names_t* cn;
359     for(cn = colnames; cn->name; cn++) {
360         if ( cn->id == id ) {
361             return cn->name;
362         }
363     }
364     return NULL;
365 }
366
367
368 WSLUA_METAMETHOD Column__tostring(lua_State *L) {
369     Column c = checkColumn(L,1);
370     const gchar* name;
371
372     if (!(c)) {
373         return 0;
374     }
375
376     /* XXX: should return the column's text ! */
377     name = col_id_to_name(c->col);
378     lua_pushstring(L,name ? name : "Unknown Column");
379
380     WSLUA_RETURN(1); /* A string representing the column */
381 }
382
383 static int Column__gc(lua_State* L) {
384     Column col = checkColumn(L,1);
385
386     if (!col) return 0;
387     
388     if (!col->expired)
389         col->expired = TRUE;
390     else
391         g_free(col);
392
393     return 0;
394
395 }
396
397 WSLUA_METHOD Column_clear(lua_State *L) {
398         /* Clears a Column */
399     Column c = checkColumn(L,1);
400
401     if (!(c && c->cinfo)) return 0;
402
403     if (check_col(c->cinfo, c->col))
404         col_clear(c->cinfo, c->col);
405
406     return 0;
407 }
408
409 WSLUA_METHOD Column_set(lua_State *L) {
410         /* Sets the text of a Column */
411 #define WSLUA_ARG_Column_set_TEXT 2 /* The text to which to set the Column */
412         Column c = checkColumn(L,1);
413     const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_set_TEXT);
414
415     if (!(c && c->cinfo))
416                 return 0;
417
418         if (!s) WSLUA_ARG_ERROR(Column_set,TEXT,"must be a string");
419
420     if (check_col(c->cinfo, c->col))
421         col_set_str(c->cinfo, c->col, s);
422
423     return 0;
424 }
425
426 WSLUA_METHOD Column_append(lua_State *L) {
427         /* Appends text to a Column */
428 #define WSLUA_ARG_Column_append_TEXT 2 /* The text to append to the Column */
429     Column c = checkColumn(L,1);
430     const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_append_TEXT);
431
432         if (!(c && c->cinfo))
433                 return 0;
434
435         if (!s) WSLUA_ARG_ERROR(Column_append,TEXT,"must be a string");
436
437
438     if (check_col(c->cinfo, c->col))
439         col_append_str(c->cinfo, c->col, s);
440
441     return 0;
442 }
443
444 WSLUA_METHOD Column_preppend(lua_State *L) {
445         /* Prepends text to a Column */
446 #define WSLUA_ARG_Column_prepend_TEXT 2 /* The text to prepend to the Column */
447     Column c = checkColumn(L,1);
448     const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_prepend_TEXT);
449
450         if (!(c && c->cinfo))
451                 return 0;
452
453         if (!s) WSLUA_ARG_ERROR(Column_prepend,TEXT,"must be a string");
454
455     if (check_col(c->cinfo, c->col))
456         col_prepend_fstr(c->cinfo, c->col, "%s",s);
457
458     return 0;
459 }
460
461 WSLUA_METHODS Column_methods[] = {
462     {"clear", Column_clear },
463     {"set", Column_set },
464     {"append", Column_append },
465     {"preppend", Column_preppend },
466     {0,0}
467 };
468
469
470 WSLUA_META Column_meta[] = {
471     {"__tostring", Column__tostring },
472     {"__gc", Column__gc },
473     {0,0}
474 };
475
476
477 int Column_register(lua_State *L) {
478         WSLUA_REGISTER_CLASS(Column);
479     return 1;
480 }
481
482
483
484
485
486
487 WSLUA_CLASS_DEFINE(Columns,NOP,NOP);
488 /* The Columns of the packet list. */
489
490 WSLUA_METAMETHOD Columns__tostring(lua_State *L) {
491     lua_pushstring(L,"Columns");
492     WSLUA_RETURN(1);
493         /* The string "Columns", no real use, just for debugging purposes. */
494 }
495
496 WSLUA_METAMETHOD Columns__newindex(lua_State *L) {
497         /* Sets the text of a specific column */
498 #define WSLUA_ARG_Columns__newindex_COLUMN 2 /* the name of the column to set */
499 #define WSLUA_ARG_Columns__newindex_TEXT 3 /* the text for the column */
500     Columns cols = checkColumns(L,1);
501     const struct col_names_t* cn;
502     const char* colname;
503     const char* text;
504
505     if (!cols) return 0;
506     if (cols->expired) {
507         luaL_error(L,"expired column");
508         return 0;
509     }
510
511     colname = luaL_checkstring(L,WSLUA_ARG_Columns__newindex_COLUMN);
512     text = luaL_checkstring(L,WSLUA_ARG_Columns__newindex_TEXT);
513
514     for(cn = colnames; cn->name; cn++) {
515         if( g_str_equal(cn->name,colname) ) {
516             if (check_col(cols->cinfo, cn->id))
517                 col_set_str(cols->cinfo, cn->id, text);
518             return 0;
519         }
520     }
521
522         WSLUA_ARG_ERROR(Columns__newindex,COLUMN,"the column name must be a valid column");
523
524     return 0;
525 }
526
527 WSLUA_METAMETHOD Columns_index(lua_State *L) {
528     Columns cols = checkColumns(L,1);
529     const struct col_names_t* cn;
530     const char* colname = luaL_checkstring(L,2);
531
532     if (!cols) {
533         Column c = g_malloc(sizeof(struct _wslua_col_info));
534         c->cinfo = NULL;
535         c->col = col_name_to_id(colname);
536         c->expired = FALSE;
537
538         PUSH_COLUMN(L,c);
539         return 1;
540     }
541
542
543     if (cols->expired) {
544         luaL_error(L,"expired column");
545         return 0;
546     }
547
548     if (!colname) return 0;
549
550     for(cn = colnames; cn->name; cn++) {
551         if( g_str_equal(cn->name,colname) ) {
552             Column c = g_malloc(sizeof(struct _wslua_col_info));
553             c->cinfo = cols->cinfo;
554             c->col = col_name_to_id(colname);
555             c->expired = FALSE;
556
557             PUSH_COLUMN(L,c);
558             return 1;
559         }
560     }
561
562     return 0;
563 }
564
565 static int Columns_gc(lua_State* L) {
566     Columns cols = checkColumns(L,1);
567
568     if (!cols) return 0;
569     
570     if (!cols->expired)
571         cols->expired = TRUE;
572     else
573         g_free(cols);
574
575     return 0;
576
577 }
578
579
580 static const luaL_reg Columns_meta[] = {
581     {"__tostring", Columns__tostring },
582     {"__newindex", Columns__newindex },
583     {"__index",  Columns_index},
584     {"__gc",  Columns_gc},
585     { NULL, NULL }
586 };
587
588
589 int Columns_register(lua_State *L) {
590         WSLUA_REGISTER_META(Columns);
591     return 1;
592 }
593
594
595 WSLUA_CLASS_DEFINE(Pinfo,FAIL_ON_NULL("expired pinfo"),NOP);
596 /* Packet information */
597
598 static int Pinfo_tostring(lua_State *L) { lua_pushstring(L,"a Pinfo"); return 1; }
599
600 #define PINFO_GET_NUMBER(name,val) static int name(lua_State *L) {  \
601     Pinfo pinfo = checkPinfo(L,1); \
602     if (!pinfo) return 0;\
603     if (pinfo->expired) { \
604         luaL_error(L,"expired_pinfo"); \
605         return 0; \
606     } \
607     lua_pushnumber(L,(lua_Number)(val));\
608     return 1;\
609 }
610
611 #define PINFO_GET_STRING(name,val) static int name(lua_State *L) { \
612     Pinfo pinfo = checkPinfo(L,1); \
613     const gchar* value; \
614     if (!pinfo) return 0; \
615     if (pinfo->expired) { \
616         luaL_error(L,"expired_pinfo"); \
617         return 0; \
618     } \
619     value = val; \
620     if (value) lua_pushstring(L,(const char*)(value)); else lua_pushnil(L); \
621     return 1; \
622 }
623
624 #define PINFO_GET_ADDRESS(name,role) static int name(lua_State *L) { \
625     Pinfo pinfo = checkPinfo(L,1); \
626     Address addr = g_malloc(sizeof(address)); \
627     if (!pinfo) return 0; \
628     if (pinfo->expired) { \
629         luaL_error(L,"expired_pinfo"); \
630         return 0; \
631     } \
632     COPY_ADDRESS(addr, &(pinfo->ws_pinfo->role)); \
633     pushAddress(L,addr); \
634     return 1; \
635 }
636
637 PINFO_GET_NUMBER(Pinfo_number,pinfo->ws_pinfo->fd->num)
638 PINFO_GET_NUMBER(Pinfo_len,pinfo->ws_pinfo->fd->pkt_len)
639 PINFO_GET_NUMBER(Pinfo_caplen,pinfo->ws_pinfo->fd->cap_len)
640 PINFO_GET_NUMBER(Pinfo_abs_ts,(((double)pinfo->ws_pinfo->fd->abs_ts.secs) + (((double)pinfo->ws_pinfo->fd->abs_ts.nsecs) / 1000000000.0) ))
641 PINFO_GET_NUMBER(Pinfo_rel_ts,(((double)pinfo->ws_pinfo->fd->rel_ts.secs) + (((double)pinfo->ws_pinfo->fd->rel_ts.nsecs) / 1000000000.0) ))
642 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) ))
643 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) ))
644 PINFO_GET_NUMBER(Pinfo_ipproto,pinfo->ws_pinfo->ipproto)
645 PINFO_GET_NUMBER(Pinfo_circuit_id,pinfo->ws_pinfo->circuit_id)
646 PINFO_GET_NUMBER(Pinfo_desegment_len,pinfo->ws_pinfo->desegment_len)
647 PINFO_GET_NUMBER(Pinfo_desegment_offset,pinfo->ws_pinfo->desegment_offset)
648 PINFO_GET_NUMBER(Pinfo_ptype,pinfo->ws_pinfo->ptype)
649 PINFO_GET_NUMBER(Pinfo_src_port,pinfo->ws_pinfo->srcport)
650 PINFO_GET_NUMBER(Pinfo_dst_port,pinfo->ws_pinfo->destport)
651
652 PINFO_GET_STRING(Pinfo_curr_proto,pinfo->ws_pinfo->current_proto)
653
654 PINFO_GET_ADDRESS(Pinfo_net_src,net_src)
655 PINFO_GET_ADDRESS(Pinfo_net_dst,net_dst)
656 PINFO_GET_ADDRESS(Pinfo_dl_src,dl_src)
657 PINFO_GET_ADDRESS(Pinfo_dl_dst,dl_dst)
658 PINFO_GET_ADDRESS(Pinfo_src,src)
659 PINFO_GET_ADDRESS(Pinfo_dst,dst)
660
661 static int Pinfo_visited(lua_State *L) {
662     Pinfo pinfo = checkPinfo(L,1);
663     if (!pinfo) return 0;
664     if (pinfo->expired) {
665         luaL_error(L,"expired_pinfo");
666         return 0;
667     }
668     lua_pushboolean(L,pinfo->ws_pinfo->fd->flags.visited);
669     return 1;
670 }
671
672
673 static int Pinfo_match(lua_State *L) {
674     Pinfo pinfo = checkPinfo(L,1);
675
676     if (!pinfo) return 0;
677     if (pinfo->expired) {
678         luaL_error(L,"expired_pinfo");
679         return 0;
680     }
681
682     if (pinfo->ws_pinfo->match_string) {
683         lua_pushstring(L,pinfo->ws_pinfo->match_string);
684     } else {
685         lua_pushnumber(L,(lua_Number)(pinfo->ws_pinfo->match_port));
686     }
687
688     return 1;
689 }
690
691 static int Pinfo_columns(lua_State *L) {
692     Columns cols = NULL;
693     Pinfo pinfo = checkPinfo(L,1);
694     const gchar* colname = luaL_optstring(L,2,NULL);
695
696     if (pinfo->expired) {
697         luaL_error(L,"expired_pinfo");
698         return 0;
699     }
700     
701     cols = g_malloc(sizeof(struct _wslua_cols));
702     cols->cinfo = pinfo->ws_pinfo->cinfo;
703     cols->expired = FALSE;
704
705     if (!colname) {
706         PUSH_COLUMNS(L,cols);
707     } else {
708         lua_settop(L,0);
709         PUSH_COLUMNS(L,cols);
710         lua_pushstring(L,colname);
711         return Columns_index(L);
712     }
713     return 1;
714 }
715
716
717 typedef enum {
718     PARAM_NONE,
719     PARAM_ADDR_SRC,
720     PARAM_ADDR_DST,
721     PARAM_ADDR_DL_SRC,
722     PARAM_ADDR_DL_DST,
723     PARAM_ADDR_NET_SRC,
724     PARAM_ADDR_NET_DST,
725     PARAM_PORT_SRC,
726     PARAM_PORT_DST,
727     PARAM_CIRCUIT_ID,
728     PARAM_DESEGMENT_LEN,
729     PARAM_DESEGMENT_OFFSET,
730     PARAM_PORT_TYPE
731 } pinfo_param_type_t;
732
733 static int pushnil_param(lua_State* L, packet_info* pinfo _U_, pinfo_param_type_t pt _U_ ) {
734     lua_pushnil(L);
735     return 1;
736 }
737
738 int Pinfo_set_addr(lua_State* L, packet_info* pinfo, pinfo_param_type_t pt) {
739     const address* from = checkAddress(L,1);
740     address* to;
741
742     if (! from ) {
743         luaL_error(L,"Not an OK address");
744         return 0;
745     }
746     
747     if (!pinfo) {
748         luaL_error(L,"expired_pinfo");
749         return 0;
750     }
751
752     switch(pt) {
753         case PARAM_ADDR_SRC:
754             to = &(pinfo->src);
755             break;
756         case PARAM_ADDR_DST:
757             to = &(pinfo->dst);
758             break;
759         case PARAM_ADDR_DL_SRC:
760             to = &(pinfo->dl_src);
761             break;
762         case PARAM_ADDR_DL_DST:
763             to = &(pinfo->dl_dst);
764             break;
765         case PARAM_ADDR_NET_SRC:
766             to = &(pinfo->net_src);
767             break;
768         case PARAM_ADDR_NET_DST:
769             to = &(pinfo->net_dst);
770             break;
771         default:
772             g_assert(!"BUG: A bad parameter");
773             return 0;
774     }
775
776     COPY_ADDRESS(to,from);
777     return 0;
778 }
779
780 int Pinfo_set_int(lua_State* L, packet_info* pinfo, pinfo_param_type_t pt) {
781     gint64 v = luaL_checkint(L,1);
782
783     if (!pinfo) {
784         luaL_error(L,"expired_pinfo");
785         return 0;
786     }
787     
788     switch(pt) {
789         case PARAM_PORT_SRC:
790             pinfo->srcport = (guint32)v;
791             return 0;
792         case PARAM_PORT_DST:
793             pinfo->destport = (guint32)v;
794             return 0;
795         case PARAM_CIRCUIT_ID:
796             pinfo->circuit_id = (guint32)v;
797             return 0;
798         case PARAM_DESEGMENT_LEN:
799             pinfo->desegment_len = (guint32)v;
800             return 0;
801         case PARAM_DESEGMENT_OFFSET:
802             pinfo->desegment_offset = (int)v;
803             return 0;
804         default:
805             g_assert(!"BUG: A bad parameter");
806     }
807
808     return 0;
809 }
810
811 typedef struct _pinfo_method_t {
812     const gchar* name;
813     lua_CFunction get;
814     int (*set)(lua_State*, packet_info*, pinfo_param_type_t);
815     pinfo_param_type_t param;
816 } pinfo_method_t;
817
818 static int Pinfo_hi(lua_State *L) {
819     Pinfo pinfo = checkPinfo(L,1);
820         Address addr = g_malloc(sizeof(address));
821
822         if (!pinfo) return 0;
823         if (pinfo->expired) {
824         luaL_error(L,"expired_pinfo");
825         return 0;
826     }
827
828         if (CMP_ADDRESS(&(pinfo->ws_pinfo->src), &(pinfo->ws_pinfo->dst) ) >= 0) {
829                 COPY_ADDRESS(addr, &(pinfo->ws_pinfo->src));
830         } else {
831                 COPY_ADDRESS(addr, &(pinfo->ws_pinfo->dst));
832         }
833
834         pushAddress(L,addr);
835         return 1;
836 }
837
838 static int Pinfo_lo(lua_State *L) {
839     Pinfo pinfo = checkPinfo(L,1);
840         Address addr = g_malloc(sizeof(address));
841
842         if (!pinfo) return 0;
843         if (pinfo->expired) {
844         luaL_error(L,"expired_pinfo");
845         return 0;
846     }
847
848         if (CMP_ADDRESS(&(pinfo->ws_pinfo->src), &(pinfo->ws_pinfo->dst) ) < 0) {
849                 COPY_ADDRESS(addr, &(pinfo->ws_pinfo->src));
850         } else {
851                 COPY_ADDRESS(addr, &(pinfo->ws_pinfo->dst));
852         }
853
854         pushAddress(L,addr);
855         return 1;
856 }
857
858
859 static const pinfo_method_t Pinfo_methods[] = {
860
861         /* WSLUA_ATTRIBUTE Pinfo_number RO The number of this packet in the current file */
862     {"number", Pinfo_number, pushnil_param, PARAM_NONE},
863
864         /* WSLUA_ATTRIBUTE Pinfo_len  RO The length of the frame */
865     {"len", Pinfo_len, pushnil_param, PARAM_NONE },
866
867         /* WSLUA_ATTRIBUTE Pinfo_caplen RO The captured length of the frame */
868     {"caplen", Pinfo_caplen, pushnil_param, PARAM_NONE },
869
870         /* WSLUA_ATTRIBUTE Pinfo_abs_ts RO When the packet was captured */
871     {"abs_ts",Pinfo_abs_ts, pushnil_param, PARAM_NONE },
872
873         /* WSLUA_ATTRIBUTE Pinfo_rel_ts RO Number of seconds passed since beginning of capture */
874     {"rel_ts",Pinfo_rel_ts, pushnil_param, PARAM_NONE },
875
876         /* WSLUA_ATTRIBUTE Pinfo_delta_ts RO Number of seconds passed since the last captured packet */
877     {"delta_ts",Pinfo_delta_ts, pushnil_param, PARAM_NONE },
878
879         /* WSLUA_ATTRIBUTE Pinfo_delta_dis_ts RO Number of seconds passed since the last displayed packet */
880     {"delta_dis_ts",Pinfo_delta_dis_ts, pushnil_param, PARAM_NONE },
881
882         /* WSLUA_ATTRIBUTE Pinfo_visited RO Whether this packet hass been already visited */
883     {"visited",Pinfo_visited, pushnil_param, PARAM_NONE },
884
885         /* WSLUA_ATTRIBUTE Pinfo_src RW Source Address of this Packet */
886     {"src", Pinfo_src, Pinfo_set_addr, PARAM_ADDR_SRC },
887
888         /* WSLUA_ATTRIBUTE Pinfo_dst RW Destination Address of this Packet */
889     {"dst", Pinfo_dst, Pinfo_set_addr, PARAM_ADDR_DST },
890
891         /* WSLUA_ATTRIBUTE Pinfo_lo RO lower Address of this Packet */
892     {"lo", Pinfo_lo, pushnil_param, PARAM_NONE },
893
894         /* WSLUA_ATTRIBUTE Pinfo_hi RW higher Address of this Packet */
895     {"hi", Pinfo_hi, pushnil_param, PARAM_NONE },
896
897         /* WSLUA_ATTRIBUTE Pinfo_dl_src RW Data Link Source Address of this Packet */
898     {"dl_src", Pinfo_dl_src, Pinfo_set_addr, PARAM_ADDR_DL_SRC },
899
900         /* WSLUA_ATTRIBUTE Pinfo_dl_dst RW Data Link Destination Address of this Packet */
901     {"dl_dst", Pinfo_dl_dst, Pinfo_set_addr, PARAM_ADDR_DL_DST },
902
903         /* WSLUA_ATTRIBUTE Pinfo_net_src RW Network Layer Source Address of this Packet */
904     {"net_src", Pinfo_net_src, Pinfo_set_addr, PARAM_ADDR_NET_SRC },
905
906         /* WSLUA_ATTRIBUTE Pinfo_net_dst RW Network Layer Destination Address of this Packet */
907     {"net_dst", Pinfo_net_dst, Pinfo_set_addr, PARAM_ADDR_NET_DST },
908
909         /* WSLUA_ATTRIBUTE Pinfo_ptype RW Type of Port of .src_port and .dst_port */
910     {"port_type", Pinfo_ptype, pushnil_param, PARAM_NONE },
911
912         /* WSLUA_ATTRIBUTE Pinfo_src_port RW Source Port of this Packet */
913     {"src_port", Pinfo_src_port, Pinfo_set_int,  PARAM_PORT_SRC },
914
915         /* WSLUA_ATTRIBUTE Pinfo_dst_port RW Source Address of this Packet */
916     {"dst_port", Pinfo_dst_port, Pinfo_set_int,  PARAM_PORT_SRC },
917
918         /* WSLUA_ATTRIBUTE Pinfo_ipproto RO IP Protocol id */
919     {"ipproto", Pinfo_ipproto, pushnil_param,  PARAM_NONE },
920
921         /* WSLUA_ATTRIBUTE Pinfo_circuit_id RO For circuit based protocols */
922     {"circuit_id", Pinfo_circuit_id, Pinfo_set_int, PARAM_CIRCUIT_ID },
923
924         /* WSLUA_ATTRIBUTE Pinfo_match RO Port/Data we are matching */
925     {"match", Pinfo_match, pushnil_param, PARAM_NONE },
926
927         /* WSLUA_ATTRIBUTE Pinfo_curr_proto RO Which Protocol are we dissecting */
928     {"curr_proto", Pinfo_curr_proto, pushnil_param, PARAM_NONE },
929
930         /* WSLUA_ATTRIBUTE Pinfo_columns RO Accesss to the packet list columns */
931     {"columns", Pinfo_columns, pushnil_param, PARAM_NONE },
932
933         /* WSLUA_ATTRIBUTE Pinfo_cols RO Accesss to the packet list columns (equivalent to pinfo.cols) */
934     {"cols", Pinfo_columns, pushnil_param, PARAM_NONE },
935
936         /* WSLUA_ATTRIBUTE Pinfo_desegment_len RW Estimated number of additional bytes required for completing the PDU */
937     {"desegment_len", Pinfo_desegment_len, Pinfo_set_int,  PARAM_DESEGMENT_LEN },
938
939         /* WSLUA_ATTRIBUTE Pinfo_desegment_len RW Offset in the tvbuff at which the dissector will continue processing when next called*/
940     {"desegment_offset", Pinfo_desegment_offset, Pinfo_set_int,  PARAM_DESEGMENT_OFFSET },
941         
942         {NULL,NULL,NULL,PARAM_NONE}
943 };
944
945
946 static int pushnil(lua_State* L) {
947     lua_pushnil(L);
948     return 1;
949 }
950
951 static int Pinfo_index(lua_State* L) {
952     Pinfo pinfo = checkPinfo(L,1);
953     const gchar* name = luaL_checkstring(L,2);
954     lua_CFunction method = pushnil;
955     const pinfo_method_t* curr;
956
957     if (! (pinfo && name) ) {
958         lua_pushnil(L);
959         return 1;
960     }
961     if (pinfo->expired) {
962         luaL_error(L,"expired_pinfo");
963         return 0;
964     }
965
966     for (curr = Pinfo_methods ; curr->name ; curr++) {
967         if (g_str_equal(curr->name,name)) {
968             method = curr->get;
969             break;
970         }
971     }
972
973     lua_settop(L,1);
974     return method(L);
975 }
976
977 static int Pinfo_setindex(lua_State* L) {
978     Pinfo pinfo = checkPinfo(L,1);
979     const gchar* name = luaL_checkstring(L,2);
980     int (*method)(lua_State*, packet_info* pinfo, pinfo_param_type_t) = pushnil_param;
981     const pinfo_method_t* curr;
982     pinfo_param_type_t param_type = PARAM_NONE;
983
984     if (! (pinfo && name) ) {
985         return 0;
986     }
987     if (pinfo->expired) {
988         luaL_error(L,"expired_pinfo");
989         return 0;
990     }
991
992     for (curr = Pinfo_methods ; curr->name ; curr++) {
993         if (g_str_equal(curr->name,name)) {
994             method = curr->set;
995             param_type = curr->param;
996             break;
997         }
998     }
999
1000     lua_remove(L,1);
1001     lua_remove(L,1);
1002     return method(L,pinfo->ws_pinfo,param_type);
1003 }
1004
1005 static int Pinfo_gc(lua_State* L) {
1006     Pinfo pinfo = checkPinfo(L,1);
1007
1008     if (!pinfo) return 0;
1009     
1010     if (!pinfo->expired)
1011         pinfo->expired = TRUE;
1012     else
1013         g_free(pinfo);
1014
1015     return 0;
1016
1017 }
1018
1019 static const luaL_reg Pinfo_meta[] = {
1020     {"__index", Pinfo_index},
1021     {"__newindex",Pinfo_setindex},
1022     {"__tostring", Pinfo_tostring},
1023     {"__gc", Pinfo_gc},
1024     { NULL, NULL }
1025 };
1026
1027 int Pinfo_register(lua_State* L) {
1028         WSLUA_REGISTER_META(Pinfo);
1029     outstanding_Pinfo = g_ptr_array_new();
1030     outstanding_Column = g_ptr_array_new();
1031     outstanding_Columns = g_ptr_array_new();
1032     return 1;
1033 }
1034