4 * Wireshark's interface to the Lua Programming Language
6 * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
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.
31 #include <epan/emem.h>
33 /* WSLUA_MODULE Dumper Saving capture files */
38 WSLUA_CLASS_DEFINE(PseudoHeader
,NOP
,NOP
);
40 A pseudoheader to be used to save captured frames.
43 enum lua_pseudoheader_type
{
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
));
73 pushPseudoHeader(L
,ph
);
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
));
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
));
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
);
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 */
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; }
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 */
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
),
165 WSLUA_META PseudoHeader_meta
[] = {
169 int PseudoHeader_register(lua_State
* L
) {
170 WSLUA_REGISTER_CLASS(PseudoHeader
)
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];
184 g_strlcpy(fname_clean
,fname
,255);
185 fname_clean
[255] = '\0';
187 for(f
= fname_clean
; *f
; f
++) {
190 *f
= *(G_DIR_SEPARATOR_S
);
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 */
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
);
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
);
222 /* WSLUA_ERROR("Error while opening file for writing"); */
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
));
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
));
236 luaL_error(L
,"error while opening `%s': %s",
244 g_hash_table_insert(dumper_encaps
,d
,GINT_TO_POINTER(encap
));
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");
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",
266 /* this way if we close a dumper any attempt to use it (for everything but GC) will yield an error */
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);
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);
297 struct wtap_pkthdr pkthdr
;
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",
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. */
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
);
344 const char* filename
;
346 if (! fname
) return 0;
348 filename
= cross_plat_fname(fname
);
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
);
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
));
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
));
371 luaL_error(L
,"error while opening `%s': %s",
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
;
392 struct data_source
*data_src
;
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
);
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",
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");
432 /* If we are Garbage Collected it means the Dumper is no longer usable. Close it */
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",
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
),
458 WSLUA_META Dumper_meta
[] = {
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
);