/* Similar to the classic wtap can_write_encap function. * This returns 0 if the encap is ok for this file type. */ static int wslua_filehandler_can_write_encap(int encap, void* data) { FileHandler fh = (FileHandler)(data); int retval = WTAP_ERR_UNWRITABLE_ENCAP; lua_State* L = NULL; INIT_FILEHANDLER_ROUTINE(can_write_encap,WTAP_ERR_INTERNAL); lua_pushnumber(L, encap); switch ( lua_pcall(L,1,1,1) ) { case 0: retval = wslua_optboolint(L,-1,WTAP_ERR_UNWRITABLE_ENCAP); break; CASE_ERROR("can_write_encap") } END_FILEHANDLER_ROUTINE(); /* the retval we got was either a 1 for true, 0 for false, or WTAP_ERR_UNWRITABLE_ENCAP; but can_write_encap() expects 0 to be true/yes */ if (retval == 1) { retval = 0; } else if (retval == 0) { retval = WTAP_ERR_UNWRITABLE_ENCAP; } return retval; }
/* The classic wtap dump_open function. * This returns 1 (TRUE) on success. */ static int wslua_filehandler_dump_open(wtap_dumper *wdh, int *err) { FileHandler fh = (FileHandler)(wdh->wslua_data); int retval = 0; lua_State* L = NULL; File *fp = NULL; CaptureInfoConst *fc = NULL; INIT_FILEHANDLER_ROUTINE(write_open,0); create_wdh_priv(L, wdh); fp = push_Wdh(L, wdh); fc = push_CaptureInfoConst(L,wdh); /* Reset err */ if (err) { *err = 0; } switch ( lua_pcall(L,2,1,1) ) { case 0: retval = wslua_optboolint(L,-1,0); break; CASE_ERROR("write_open") } END_FILEHANDLER_ROUTINE(); (*fp)->expired = TRUE; (*fc)->expired = TRUE; if (retval == 1) { /* this is our file type - set the routines and settings into wtap */ if (fh->write_ref != LUA_NOREF) { wdh->subtype_write = wslua_filehandler_dump; } else { g_warning("FileHandler was not set with a write function, even though write_open() returned true"); return 0; } /* it's ok to not have a finish routine */ if (fh->write_finish_ref != LUA_NOREF) wdh->subtype_finish = wslua_filehandler_dump_finish; else wdh->subtype_finish = NULL; } else { /* not our file type? */ remove_wdh_priv(L, wdh); } return retval; }
/* The classic wtap read routine. This returns TRUE if it found the next packet, * else FALSE. * If it finds a frame/packet, it should set the pseudo-header info (ie, let Lua set it). * Also Lua needs to set data_offset to the beginning of the line we're returning. * This will be the seek_off parameter when this frame is re-read. */ static gboolean wslua_filehandler_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) { FileHandler fh = (FileHandler)(wth->wslua_data); int retval = -1; lua_State* L = NULL; File *fp = NULL; CaptureInfo *fc = NULL; FrameInfo *fi = NULL; INIT_FILEHANDLER_ROUTINE(read,FALSE); /* Reset errno */ if (err) { *err = errno = 0; } wth->phdr.opt_comment = NULL; fp = push_File(L, wth->fh); fc = push_CaptureInfo(L, wth, FALSE); fi = push_FrameInfo(L, &wth->phdr, wth->frame_buffer); switch ( lua_pcall(L,3,1,1) ) { case 0: /* * Return values for FileHandler:read(): * Integer is the number of read bytes. * Boolean false indicates an error. * XXX handling of boolean true is not documented. Currently it will * succeed without advancing data offset. Should it fail instead? */ if (lua_type(L, -1) == LUA_TNUMBER) { *data_offset = wslua_togint64(L, -1); retval = 1; break; } retval = wslua_optboolint(L,-1,0); break; CASE_ERROR_ERRINFO("read") } END_FILEHANDLER_ROUTINE(); (*fp)->expired = TRUE; (*fc)->expired = TRUE; (*fi)->expired = TRUE; lua_settop(L,0); return (retval == 1); }
/* Classic wtap seek_read function, called by wtap core. This must return TRUE on * success, FALSE on error. */ static gboolean wslua_filehandler_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info) { FileHandler fh = (FileHandler)(wth->wslua_data); int retval = -1; lua_State* L = NULL; File *fp = NULL; CaptureInfo *fc = NULL; FrameInfo *fi = NULL; INIT_FILEHANDLER_ROUTINE(seek_read,FALSE); /* Reset errno */ if (err) { *err = errno = 0; } phdr->opt_comment = NULL; fp = push_File(L, wth->random_fh); fc = push_CaptureInfo(L, wth, FALSE); fi = push_FrameInfo(L, phdr, buf); lua_pushnumber(L, (lua_Number)seek_off); switch ( lua_pcall(L,4,1,1) ) { case 0: if (lua_isstring(L,-1)) { size_t len = 0; const gchar* fd = lua_tolstring(L, -1, &len); if (len < WTAP_MAX_PACKET_SIZE) memcpy(ws_buffer_start_ptr(buf), fd, len); retval = 1; break; } retval = wslua_optboolint(L,-1,0); break; CASE_ERROR_ERRINFO("seek_read") } END_FILEHANDLER_ROUTINE(); (*fp)->expired = TRUE; (*fc)->expired = TRUE; (*fi)->expired = TRUE; lua_settop(L,0); return (retval == 1); }
/* The classic wtap read routine. This returns TRUE if it found the next packet, * else FALSE. * If it finds a frame/packet, it should set the pseudo-header info (ie, let Lua set it). * Also Lua needs to set data_offset to the beginning of the line we're returning. * This will be the seek_off parameter when this frame is re-read. */ static gboolean wslua_filehandler_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) { FileHandler fh = (FileHandler)(wth->wslua_data); int retval = -1; lua_State* L = NULL; File *fp = NULL; CaptureInfo *fc = NULL; FrameInfo *fi = NULL; INIT_FILEHANDLER_ROUTINE(read,FALSE); /* Reset errno */ if (err) { *err = errno = 0; } wth->phdr.opt_comment = NULL; fp = push_File(L, wth->fh); fc = push_CaptureInfo(L, wth, FALSE); fi = push_FrameInfo(L, &wth->phdr, wth->frame_buffer); switch ( lua_pcall(L,3,1,1) ) { case 0: if (lua_isnumber(L,-1)) { *data_offset = wslua_togint64(L, -1); retval = 1; break; } retval = wslua_optboolint(L,-1,0); break; CASE_ERROR_ERRINFO("read") } END_FILEHANDLER_ROUTINE(); (*fp)->expired = TRUE; (*fc)->expired = TRUE; (*fi)->expired = TRUE; lua_settop(L,0); return (retval == 1); }
/* This is our one-and-only open routine for file handling. When called by * file_access.c, the wtap wth argument has a void* wslua_data that holds the specific * FileHandler for the specific registered file format reader. It has this because * we passed it in when we registered the open routine. * The open_file_* routines should return: * -1 on an I/O error; * 1 if the file they're reading is one of the types it handles; * 0 if the file they're reading isn't the type they're checking for. * If the routine handles this type of file, it should set the "file_type" * field in the "struct wtap" to the type of the file. */ static wtap_open_return_val wslua_filehandler_open(wtap *wth, int *err, gchar **err_info) { FileHandler fh = (FileHandler)(wth->wslua_data); wtap_open_return_val retval = WTAP_OPEN_NOT_MINE; lua_State* L = NULL; File *fp = NULL; CaptureInfo *fc = NULL; INIT_FILEHANDLER_ROUTINE(read_open,WTAP_OPEN_NOT_MINE); create_wth_priv(L, wth); fp = push_File(L, wth->fh); fc = push_CaptureInfo(L, wth, TRUE); errno = WTAP_ERR_CANT_OPEN; switch ( lua_pcall(L,2,1,1) ) { case 0: retval = (wtap_open_return_val)wslua_optboolint(L,-1,0); break; CASE_ERROR_ERRINFO("read_open") } END_FILEHANDLER_ROUTINE(); (*fp)->expired = TRUE; (*fc)->expired = TRUE; if (retval == WTAP_OPEN_MINE) { /* this is our file type - set the routines and settings into wtap */ if (fh->read_ref != LUA_NOREF) { wth->subtype_read = wslua_filehandler_read; } else { g_warning("Lua file format module lacks a read routine"); return WTAP_OPEN_NOT_MINE; } if (fh->seek_read_ref != LUA_NOREF) { wth->subtype_seek_read = wslua_filehandler_seek_read; } else { g_warning("Lua file format module lacks a seek-read routine"); return WTAP_OPEN_NOT_MINE; } /* it's ok to not have a close routine */ if (fh->read_close_ref != LUA_NOREF) wth->subtype_close = wslua_filehandler_close; else wth->subtype_close = NULL; /* it's ok to not have a sequential close routine */ if (fh->seq_read_close_ref != LUA_NOREF) wth->subtype_sequential_close = wslua_filehandler_sequential_close; else wth->subtype_sequential_close = NULL; wth->file_type_subtype = fh->file_type; } else if (retval == WTAP_OPEN_ERROR) { /* open error - we *must* return an error code! */ if (err) { *err = WTAP_ERR_CANT_OPEN; } } else if (retval == WTAP_OPEN_NOT_MINE) { /* not our file type */ remove_wth_priv(L, wth); } else { /* not a valid return type */ g_warning("FileHandler read_open routine returned %d", retval); if (err) { *err = WTAP_ERR_INTERNAL; } retval = WTAP_OPEN_ERROR; } lua_settop(L,0); return retval; }