HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / wslua / wslua_dumper.c
blobbdd29b93984de4724f38047850759703a33a7bf6
1 /*
2 * wslua_dumper.c
4 * Wireshark's interface to the Lua Programming Language
6 * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
8 * $Id$
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "config.h"
31 #include <epan/emem.h>
33 /* WSLUA_MODULE Dumper Saving capture files */
35 #include "wslua.h"
36 #include <math.h>
38 WSLUA_CLASS_DEFINE(PseudoHeader,NOP,NOP);
40 A pseudoheader to be used to save captured frames.
43 enum lua_pseudoheader_type {
44 PHDR_NONE,
45 PHDR_ETH,
46 PHDR_X25,
47 PHDR_ISDN,
48 PHDR_ATM,
49 PHDR_ASCEND,
50 PHDR_P2P,
51 PHDR_WIFI,
52 PHDR_COSINE,
53 PHDR_IRDA,
54 PHDR_NETTL,
55 PHDR_MTP2,
56 PHDR_K12
59 struct lua_pseudo_header {
60 enum lua_pseudoheader_type type;
61 union wtap_pseudo_header* wph;
64 WSLUA_CONSTRUCTOR PseudoHeader_none(lua_State* L) {
66 Creates a "no" pseudoheader.
69 PseudoHeader ph = (PseudoHeader)g_malloc(sizeof(struct lua_pseudo_header));
70 ph->type = PHDR_NONE;
71 ph->wph = NULL;
73 pushPseudoHeader(L,ph);
75 WSLUA_RETURN(1);
76 /* A null pseudoheader */
79 WSLUA_CONSTRUCTOR PseudoHeader_eth(lua_State* L) {
81 Creates an ethernet pseudoheader
84 #define WSLUA_OPTARG_PseudoHeader_eth_FCSLEN 1 /* The fcs length */
86 PseudoHeader ph = (PseudoHeader)g_malloc(sizeof(struct lua_pseudo_header));
87 ph->type = PHDR_ETH;
88 ph->wph = (union wtap_pseudo_header *)g_malloc(sizeof(union wtap_pseudo_header));
89 ph->wph->eth.fcs_len = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_eth_FCSLEN,-1);
91 pushPseudoHeader(L,ph);
93 WSLUA_RETURN(1); /* The ethernet pseudoheader */
96 WSLUA_CONSTRUCTOR PseudoHeader_atm(lua_State* L) {
98 Creates an ATM pseudoheader
100 #define WSLUA_OPTARG_PseudoHeader_atm_AAL 1 /* AAL number */
101 #define WSLUA_OPTARG_PseudoHeader_atm_VPI 2 /* VPI */
102 #define WSLUA_OPTARG_PseudoHeader_atm_VCI 3 /* VCI */
103 #define WSLUA_OPTARG_PseudoHeader_atm_CHANNEL 4 /* Channel */
104 #define WSLUA_OPTARG_PseudoHeader_atm_CELLS 5 /* Number of cells in the PDU */
105 #define WSLUA_OPTARG_PseudoHeader_atm_AAL5U2U 6 /* AAL5 User to User indicator */
106 #define WSLUA_OPTARG_PseudoHeader_atm_AAL5LEN 7 /* AAL5 Len */
108 PseudoHeader ph = (PseudoHeader)g_malloc(sizeof(struct lua_pseudo_header));
109 ph->type = PHDR_ATM;
110 ph->wph = (union wtap_pseudo_header *)g_malloc(sizeof(union wtap_pseudo_header));
111 ph->wph->atm.aal = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_AAL,5);
112 ph->wph->atm.vpi = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_VPI,1);
113 ph->wph->atm.vci = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_VCI,1);
114 ph->wph->atm.channel = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_CHANNEL,0);
115 ph->wph->atm.cells = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_CELLS,1);
116 ph->wph->atm.aal5t_u2u = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_AAL5U2U,1);
117 ph->wph->atm.aal5t_len = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_AAL5LEN,0);
119 pushPseudoHeader(L,ph);
120 WSLUA_RETURN(1);
121 /* The ATM pseudoheader */
124 WSLUA_CONSTRUCTOR PseudoHeader_mtp2(lua_State* L) {
125 /* Creates an MTP2 PseudoHeader */
126 #define WSLUA_OPTARG_PseudoHeader_mtp2_SENT 1 /* True if the packet is sent, False if received. */
127 #define WSLUA_OPTARG_PseudoHeader_mtp2_ANNEXA 2 /* True if annex A is used */
128 #define WSLUA_OPTARG_PseudoHeader_mtp2_LINKNUM 3 /* Link Number */
129 PseudoHeader ph = (PseudoHeader)g_malloc(sizeof(struct lua_pseudo_header));
130 ph->type = PHDR_MTP2;
131 ph->wph = (union wtap_pseudo_header *)g_malloc(sizeof(union wtap_pseudo_header));
132 ph->wph->mtp2.sent = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_mtp2_SENT,0);
133 ph->wph->mtp2.annex_a_used = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_mtp2_ANNEXA,0);
134 ph->wph->mtp2.link_number = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_mtp2_LINKNUM,0);
136 pushPseudoHeader(L,ph);
137 WSLUA_RETURN(1); /* The MTP2 pseudoheader */
140 #if 0
141 static int PseudoHeader_x25(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
142 static int PseudoHeader_isdn(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
143 static int PseudoHeader_ascend(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
144 static int PseudoHeader_wifi(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
145 static int PseudoHeader_cosine(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
146 static int PseudoHeader_irda(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
147 static int PseudoHeader_nettl(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
148 static int PseudoHeader_k12(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
149 #endif
151 /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
152 static int PseudoHeader__gc(lua_State* L _U_) {
153 /* do NOT free PseudoHeader */
154 return 0;
157 WSLUA_METHODS PseudoHeader_methods[] = {
158 WSLUA_CLASS_FNREG(PseudoHeader,mtp2),
159 WSLUA_CLASS_FNREG(PseudoHeader,atm),
160 WSLUA_CLASS_FNREG(PseudoHeader,eth),
161 WSLUA_CLASS_FNREG(PseudoHeader,none),
162 {0,0}
165 WSLUA_META PseudoHeader_meta[] = {
166 {0,0}
169 int PseudoHeader_register(lua_State* L) {
170 WSLUA_REGISTER_CLASS(PseudoHeader)
171 return 0;
175 WSLUA_CLASS_DEFINE(Dumper,FAIL_ON_NULL("Dumper already closed"),NOP);
177 static GHashTable* dumper_encaps = NULL;
178 #define DUMPER_ENCAP(d) GPOINTER_TO_INT(g_hash_table_lookup(dumper_encaps,d))
180 static const char* cross_plat_fname(const char* fname) {
181 static char fname_clean[256];
182 char* f;
184 g_strlcpy(fname_clean,fname,255);
185 fname_clean[255] = '\0';
187 for(f = fname_clean; *f; f++) {
188 switch(*f) {
189 case '/': case '\\':
190 *f = *(G_DIR_SEPARATOR_S);
191 break;
192 default:
193 break;
197 return fname_clean;
200 WSLUA_CONSTRUCTOR Dumper_new(lua_State* L) {
202 Creates a file to write packets.
203 Dumper:new_for_current() will probably be a better choice.
205 #define WSLUA_ARG_Dumper_new_FILENAME 1 /* The name of the capture file to be created */
206 #define WSLUA_OPTARG_Dumper_new_FILETYPE 2 /* The type of the file to be created */
207 #define WSLUA_OPTARG_Dumper_new_ENCAP 3 /* The encapsulation to be used in the file to be created */
208 Dumper d;
209 const char* fname = luaL_checkstring(L,WSLUA_ARG_Dumper_new_FILENAME);
210 int filetype = luaL_optint(L,WSLUA_OPTARG_Dumper_new_FILETYPE,WTAP_FILE_TYPE_SUBTYPE_PCAP);
211 int encap = luaL_optint(L,WSLUA_OPTARG_Dumper_new_ENCAP,WTAP_ENCAP_ETHERNET);
212 int err = 0;
213 const char* filename;
215 if (! fname) return 0;
217 filename = cross_plat_fname(fname);
219 d = wtap_dump_open(filename, filetype, encap, 0, FALSE, &err);
221 if (! d ) {
222 /* WSLUA_ERROR("Error while opening file for writing"); */
223 switch (err) {
224 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
225 luaL_error(L,"Files of file type %s cannot be written",
226 wtap_file_type_subtype_string(filetype));
227 break;
229 case WTAP_ERR_UNSUPPORTED_ENCAP:
230 luaL_error(L,"Files of file type %s don't support encapsulation %s",
231 wtap_file_type_subtype_string(filetype),
232 wtap_encap_short_string(encap));
233 break;
235 default:
236 luaL_error(L,"error while opening `%s': %s",
237 filename,
238 wtap_strerror(err));
239 break;
241 return 0;
244 g_hash_table_insert(dumper_encaps,d,GINT_TO_POINTER(encap));
246 pushDumper(L,d);
247 WSLUA_RETURN(1);
248 /* The newly created Dumper object */
251 WSLUA_METHOD Dumper_close(lua_State* L) {
252 /* Closes a dumper */
253 Dumper* dp = (Dumper*)luaL_checkudata(L, 1, "Dumper");
254 int err;
256 if (! *dp)
257 WSLUA_ERROR(Dumper_close,"Cannot operate on a closed dumper");
259 g_hash_table_remove(dumper_encaps,*dp);
261 if (!wtap_dump_close(*dp, &err)) {
262 luaL_error(L,"error closing: %s",
263 wtap_strerror(err));
266 /* this way if we close a dumper any attempt to use it (for everything but GC) will yield an error */
267 *dp = NULL;
269 return 0;
272 WSLUA_METHOD Dumper_flush(lua_State* L) {
274 Writes all unsaved data of a dumper to the disk.
276 Dumper d = checkDumper(L,1);
278 if (!d) return 0;
280 wtap_dump_flush(d);
282 return 0;
285 WSLUA_METHOD Dumper_dump(lua_State* L) {
287 Dumps an arbitrary packet.
288 Note: Dumper:dump_current() will fit best in most cases.
290 #define WSLUA_ARG_Dumper_dump_TIMESTAMP 2 /* The absolute timestamp the packet will have */
291 #define WSLUA_ARG_Dumper_dump_PSEUDOHEADER 3 /* The Pseudoheader to use. */
292 #define WSLUA_ARG_Dumper_dump_BYTEARRAY 4 /* the data to be saved */
294 Dumper d = checkDumper(L,1);
295 PseudoHeader ph;
296 ByteArray ba;
297 struct wtap_pkthdr pkthdr;
298 double ts;
299 int err;
301 if (!d) return 0;
303 ts = luaL_checknumber(L,WSLUA_ARG_Dumper_dump_TIMESTAMP);
304 ph = checkPseudoHeader(L,WSLUA_ARG_Dumper_dump_PSEUDOHEADER);
306 if (!ph) WSLUA_ARG_ERROR(Dumper_dump,TIMESTAMP,"need a PseudoHeader");
308 ba = checkByteArray(L,WSLUA_ARG_Dumper_dump_BYTEARRAY);
310 if (! ba) WSLUA_ARG_ERROR(Dumper_dump,BYTEARRAY,"must be a ByteArray");
312 memset(&pkthdr, 0, sizeof(pkthdr));
314 pkthdr.ts.secs = (unsigned)floor(ts);
315 pkthdr.ts.nsecs = (unsigned)floor((ts - (double)pkthdr.ts.secs) * 1000000000);
317 pkthdr.len = ba->len;
318 pkthdr.caplen = ba->len;
319 pkthdr.pkt_encap = DUMPER_ENCAP(d);
320 pkthdr.pseudo_header = *ph->wph;
322 /* TODO: Can we get access to pinfo->pkt_comment here somehow? We
323 * should be copying it to pkthdr.opt_comment if we can. */
325 if (! wtap_dump(d, &pkthdr, ba->data, &err)) {
326 luaL_error(L,"error while dumping: %s",
327 wtap_strerror(err));
330 return 0;
334 WSLUA_METHOD Dumper_new_for_current(lua_State* L) {
336 Creates a capture file using the same encapsulation as the one of the cuurrent packet
338 #define WSLUA_OPTARG_Dumper_new_for_current_FILETYPE 2 /* The file type. Defaults to pcap. */
339 Dumper d;
340 const char* fname = luaL_checkstring(L,1);
341 int filetype = luaL_optint(L,WSLUA_OPTARG_Dumper_new_for_current_FILETYPE,WTAP_FILE_TYPE_SUBTYPE_PCAP);
342 int encap;
343 int err = 0;
344 const char* filename;
346 if (! fname) return 0;
348 filename = cross_plat_fname(fname);
350 if (! lua_pinfo )
351 WSLUA_ERROR(Dumper_new_for_current,"Cannot be used outside a tap or a dissector");
353 encap = lua_pinfo->fd->lnk_t;
355 d = wtap_dump_open(filename, filetype, encap, 0, FALSE, &err);
357 if (! d ) {
358 switch (err) {
359 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
360 luaL_error(L,"Files of file type %s cannot be written",
361 wtap_file_type_subtype_string(filetype));
362 break;
364 case WTAP_ERR_UNSUPPORTED_ENCAP:
365 luaL_error(L,"Files of file type %s don't support encapsulation %s",
366 wtap_file_type_subtype_string(filetype),
367 wtap_encap_short_string(encap));
368 break;
370 default:
371 luaL_error(L,"error while opening `%s': %s",
372 filename,
373 wtap_strerror(err));
374 break;
376 return 0;
379 pushDumper(L,d);
380 WSLUA_RETURN(1); /* The newly created Dumper Object */
384 WSLUA_METHOD Dumper_dump_current(lua_State* L) {
386 Dumps the current packet as it is.
388 Dumper d = checkDumper(L,1);
389 struct wtap_pkthdr pkthdr;
390 const guchar* data;
391 tvbuff_t* tvb;
392 struct data_source *data_src;
393 int err = 0;
395 if (!d) return 0;
397 if (! lua_pinfo ) WSLUA_ERROR(Dumper_new_for_current,"Cannot be used outside a tap or a dissector");
399 data_src = (struct data_source*) (lua_pinfo->data_src->data);
400 if (!data_src)
401 return 0;
403 tvb = get_data_source_tvb(data_src);
405 memset(&pkthdr, 0, sizeof(pkthdr));
407 pkthdr.ts.secs = lua_pinfo->fd->abs_ts.secs;
408 pkthdr.ts.nsecs = lua_pinfo->fd->abs_ts.nsecs;
409 pkthdr.len = tvb_reported_length(tvb);
410 pkthdr.caplen = tvb_length(tvb);
411 pkthdr.pkt_encap = lua_pinfo->fd->lnk_t;
412 pkthdr.pseudo_header = *lua_pinfo->pseudo_header;
414 if (lua_pinfo->pkt_comment)
415 pkthdr.opt_comment = ep_strdup(lua_pinfo->pkt_comment);
417 data = (const guchar *)tvb_memdup(wmem_packet_scope(),tvb,0,pkthdr.caplen);
419 if (! wtap_dump(d, &pkthdr, data, &err)) {
420 luaL_error(L,"error while dumping: %s",
421 wtap_strerror(err));
424 return 0;
427 /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
428 static int Dumper__gc(lua_State* L) {
429 Dumper* dp = (Dumper*)luaL_checkudata(L, 1, "Dumper");
430 int err;
432 /* If we are Garbage Collected it means the Dumper is no longer usable. Close it */
434 if (! *dp)
435 return 0; /* already closed, nothing to do! */
437 g_hash_table_remove(dumper_encaps,*dp);
439 if (!wtap_dump_close(*dp, &err)) {
440 luaL_error(L,"error closing: %s",
441 wtap_strerror(err));
444 return 0;
448 WSLUA_METHODS Dumper_methods[] = {
449 WSLUA_CLASS_FNREG(Dumper,new),
450 WSLUA_CLASS_FNREG(Dumper,new_for_current),
451 WSLUA_CLASS_FNREG(Dumper,close),
452 WSLUA_CLASS_FNREG(Dumper,flush),
453 WSLUA_CLASS_FNREG(Dumper,dump),
454 WSLUA_CLASS_FNREG(Dumper,dump_current),
455 {0, 0}
458 WSLUA_META Dumper_meta[] = {
459 {0, 0}
462 int Dumper_register(lua_State* L) {
463 dumper_encaps = g_hash_table_new(g_direct_hash,g_direct_equal);
464 WSLUA_REGISTER_CLASS(Dumper);
465 return 1;