From fc4764fa34381b972283c6297491314d095cb12f Mon Sep 17 00:00:00 2001 From: batrick Date: Sun, 17 May 2009 20:50:40 +0000 Subject: [PATCH] Cleaned up the whitespace in nse_nsock.cc as per David's suggestion (I agree with it). The whitespace was various styles in often confusing places. The whitespace also had many evil tabs. I used the indent program and tried to follow the whitespace of the rest of NSE C code as closely as possible. --- nse_nsock.cc | 2529 ++++++++++++++++++++++++++++---------------------- 1 file changed, 1406 insertions(+), 1123 deletions(-) diff --git a/nse_nsock.cc b/nse_nsock.cc index 3d9a8f033..b33bef760 100644 --- a/nse_nsock.cc +++ b/nse_nsock.cc @@ -1,7 +1,8 @@ -extern "C" { - #include "lua.h" - #include "lauxlib.h" +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" } #include @@ -21,62 +22,79 @@ extern "C" { #include "tcpip.h" #if HAVE_OPENSSL -#include +# include #endif -#define SCRIPT_ENGINE "NSE" -#define NSOCK_WRAPPER "NSOCK WRAPPER" -#define NSOCK_WRAPPER_SUCCESS 0 -#define NSOCK_WRAPPER_ERROR 2 +#define SCRIPT_ENGINE "NSE" +#define NSOCK_WRAPPER "NSOCK WRAPPER" +#define NSOCK_WRAPPER_SUCCESS 0 +#define NSOCK_WRAPPER_ERROR 2 #define NSOCK_WRAPPER_BUFFER_OK 1 #define NSOCK_WRAPPER_BUFFER_MOREREAD 2 -#define FROM 1 -#define TO 2 +#define FROM 1 +#define TO 2 #define DEFAULT_TIMEOUT 30000 extern NmapOps o; -static int l_nsock_connect(lua_State *L); -static int l_nsock_send(lua_State *L); -static int l_nsock_receive(lua_State *L); -static int l_nsock_receive_lines(lua_State *L); -static int l_nsock_receive_bytes(lua_State *L); -static int l_nsock_get_info(lua_State *L); -static int l_nsock_gc(lua_State *L); -static int l_nsock_close(lua_State *L); -static int l_nsock_set_timeout(lua_State *L); -static int l_nsock_receive_buf(lua_State *L); +static int l_nsock_connect(lua_State * L); -static int l_nsock_ncap_open(lua_State *L); -static int l_nsock_ncap_close(lua_State *L); -static int l_nsock_ncap_register(lua_State *L); -static int l_nsock_pcap_receive(lua_State *L); +static int l_nsock_send(lua_State * L); +static int l_nsock_receive(lua_State * L); + +static int l_nsock_receive_lines(lua_State * L); + +static int l_nsock_receive_bytes(lua_State * L); + +static int l_nsock_get_info(lua_State * L); + +static int l_nsock_gc(lua_State * L); + +static int l_nsock_close(lua_State * L); + +static int l_nsock_set_timeout(lua_State * L); + +static int l_nsock_receive_buf(lua_State * L); + +static int l_nsock_ncap_open(lua_State * L); + +static int l_nsock_ncap_close(lua_State * L); + +static int l_nsock_ncap_register(lua_State * L); + +static int l_nsock_pcap_receive(lua_State * L); void l_nsock_connect_handler(nsock_pool nsp, nsock_event nse, void *yield); + void l_nsock_send_handler(nsock_pool nsp, nsock_event nse, void *yield); + void l_nsock_receive_handler(nsock_pool nsp, nsock_event nse, void *yield); + void l_nsock_receive_buf_handler(nsock_pool nsp, nsock_event nse, void *yield); -int l_nsock_check_buf(lua_State *L); +int l_nsock_check_buf(lua_State * L); -int l_nsock_checkstatus(lua_State *L, nsock_event nse); +int l_nsock_checkstatus(lua_State * L, nsock_event nse); -void l_nsock_trace(nsock_iod nsiod, const char* message, int direction); -const char* inet_ntop_both(int af, const void* v_addr, char* ipstring); -unsigned short inet_port_both(int af, const void* v_addr); +void l_nsock_trace(nsock_iod nsiod, const char *message, int direction); + +const char *inet_ntop_both(int af, const void *v_addr, char *ipstring); + +unsigned short inet_port_both(int af, const void *v_addr); /* size_t table_length (lua_State *L, int index) * * Returns the length of the table at index index. * This length is the number of elements, not just array elements. */ -static size_t table_length (lua_State *L, int index) +static size_t table_length(lua_State * L, int index) { size_t len = 0; + lua_pushvalue(L, index); lua_pushnil(L); while (lua_next(L, -2) != 0) @@ -84,13 +102,14 @@ static size_t table_length (lua_State *L, int index) len++; lua_pop(L, 1); } - lua_pop(L, 1); // table + lua_pop(L, 1); // table return len; } -static std::string hexify (const unsigned char *str, size_t len) +static std::string hexify(const unsigned char *str, size_t len) { size_t num = 0; + std::ostringstream ret; // If more than 95% of the chars are printable, we escape unprintable chars @@ -104,7 +123,7 @@ static std::string hexify (const unsigned char *str, size_t len) if (isprint(str[i]) || isspace(str[i])) ret << str[i]; else - ret << std::setw(3) << "\\" << (unsigned int)(unsigned char) str[i]; + ret << std::setw(3) << "\\" << (unsigned int) (unsigned char) str[i]; } return ret.str(); } @@ -115,7 +134,7 @@ static std::string hexify (const unsigned char *str, size_t len) ret << std::setw(8) << i << ": "; for (size_t j = i; j < i + 16; j++) if (j < len) - ret << std::setw(2) << (unsigned int)(unsigned char) str[j] << " "; + ret << std::setw(2) << (unsigned int) (unsigned char) str[j] << " "; else ret << " "; for (size_t j = i; j < i + 16 && j < len; j++) @@ -144,27 +163,28 @@ static std::string hexify (const unsigned char *str, size_t len) * userdata's __gc metamethod, which will add a thread in WAITING to running. */ #define MAX_PARALLELISM 10 -#define THREAD_PROXY 1 /* */ -#define SOCKET_PROXY 2 /* */ -#define CONNECT_WAITING 3 /* Threads waiting to lock */ -#define PROXY_META 4 /* Proxy userdata's metatable */ +#define THREAD_PROXY 1 /* */ +#define SOCKET_PROXY 2 /* */ +#define CONNECT_WAITING 3 /* Threads waiting to lock */ +#define PROXY_META 4 /* Proxy userdata's metatable */ -static int proxy_gc (lua_State *L) +static int proxy_gc(lua_State * L) { lua_rawgeti(L, LUA_ENVIRONINDEX, CONNECT_WAITING); lua_pushnil(L); if (lua_next(L, -2) != 0) { lua_State *thread = lua_tothread(L, -2); + nse_restore(thread, 0); lua_pushnil(L); - lua_replace(L, -2); // replace boolean - lua_settable(L, -3); // remove thread from waiting + lua_replace(L, -2); // replace boolean + lua_settable(L, -3); // remove thread from waiting } return 0; } -static void new_proxy (lua_State *L) +static void new_proxy(lua_State * L) { lua_newuserdata(L, 0); lua_rawgeti(L, LUA_ENVIRONINDEX, PROXY_META); @@ -179,7 +199,7 @@ static void new_proxy (lua_State *L) * This function is called by Lua to get a "lock" on a socket. * See the connect function (in Lua) in luaopen_nsock. */ -static int socket_lock (lua_State *L) +static int socket_lock(lua_State * L) { lua_settop(L, 1); lua_rawgeti(L, LUA_ENVIRONINDEX, THREAD_PROXY); @@ -189,10 +209,10 @@ static int socket_lock (lua_State *L) { // Thread already has open sockets. Add the new socket to SOCKET_PROXY lua_rawgeti(L, LUA_ENVIRONINDEX, SOCKET_PROXY); - lua_pushvalue(L, 1); // socket - lua_pushvalue(L, -3); // proxy userdata + lua_pushvalue(L, 1); // socket + lua_pushvalue(L, -3); // proxy userdata lua_settable(L, -3); - lua_pop(L, 1); // SOCKET_PROXY + lua_pop(L, 1); // SOCKET_PROXY lua_pushboolean(L, true); } else if (table_length(L, 2) >= MAX(MAX_PARALLELISM, o.max_parallelism)) { @@ -202,7 +222,7 @@ static int socket_lock (lua_State *L) lua_pushthread(L); lua_pushboolean(L, true); lua_settable(L, -3); - lua_pop(L, 1); // CONNECT_WAITING + lua_pop(L, 1); // CONNECT_WAITING return lua_yield(L, 0); } else { @@ -211,14 +231,14 @@ static int socket_lock (lua_State *L) new_proxy(L); lua_rawgeti(L, LUA_ENVIRONINDEX, THREAD_PROXY); lua_pushthread(L); - lua_pushvalue(L, -3); // proxy + lua_pushvalue(L, -3); // proxy lua_settable(L, -3); - lua_pop(L, 1); // THREAD_PROXY) + lua_pop(L, 1); // THREAD_PROXY) lua_rawgeti(L, LUA_ENVIRONINDEX, SOCKET_PROXY); - lua_pushvalue(L, 1); // Socket - lua_pushvalue(L, -3); // proxy + lua_pushvalue(L, 1); // Socket + lua_pushvalue(L, -3); // proxy lua_settable(L, -3); - lua_pop(L, 2); // proxy, SOCKET_PROXY + lua_pop(L, 2); // proxy, SOCKET_PROXY lua_pushboolean(L, true); } return 1; @@ -230,14 +250,14 @@ static int socket_lock (lua_State *L) * A socket has been closed or collected, remove it from the SOCKET_PROXY * table. */ -static void socket_unlock (lua_State *L, int index) +static void socket_unlock(lua_State * L, int index) { - lua_pushvalue(L, index); // socket + lua_pushvalue(L, index); // socket lua_rawgeti(L, LUA_ENVIRONINDEX, SOCKET_PROXY); - lua_pushvalue(L, -2); // socket + lua_pushvalue(L, -2); // socket lua_pushnil(L); lua_settable(L, -3); - lua_pop(L, 2); // socket, SOCKET_PROXY + lua_pop(L, 2); // socket, SOCKET_PROXY } static nsock_pool nsp; @@ -246,79 +266,92 @@ static nsock_pool nsp; * Structure with nsock pcap descriptor. * shared between many lua threads */ -struct ncap_socket{ - nsock_iod nsiod; /* nsock pcap desc */ - int references; /* how many lua threads use this */ - char *key; /* (free) zero-terminated key used in map to - * address this structure. */ +struct ncap_socket +{ + nsock_iod nsiod; /* nsock pcap desc */ + int references; /* how many lua threads use + * this */ + char *key; /* (free) zero-terminated key + * used in map to * address + * this structure. */ }; -struct nsock_yield { - lua_State *thread; /* thread to resume */ - struct l_nsock_udata *udata; /* self reference */ +struct nsock_yield +{ + lua_State *thread; /* thread to resume */ + struct l_nsock_udata *udata; /* self reference */ }; /* * - */ -struct ncap_request{ - int suspended; /* is the thread suspended? (lua_yield) */ - //lua_State *L; /* lua_State of current process or NULL if process isn't suspended */ - struct nsock_yield *yield; - nsock_event_id nseid; /* nse for this specific lua_State */ - struct timeval end_time; - char *key; /* (free) zero-terminated key used in map to - * address this structure (hexified 'test') */ - - bool received; /* are results ready? */ - - bool r_success; /* true-> okay,data ready to pass to user - * flase-> this statusstring contains error description */ - char * r_status; /* errorstring */ - - unsigned char *r_layer2; - size_t r_layer2_len; - unsigned char *r_layer3; - size_t r_layer3_len; - size_t packetsz; - - int ncap_cback_ref; /* just copy of udata->ncap_cback_ref - * because we don't have access to udata in place - * we need to use this. */ -}; - -struct l_nsock_udata { - int timeout; - nsock_iod nsiod; - void *ssl_session; - struct nsock_yield yield; - /*used for buffered reading */ - int bufidx; /*index inside lua's registry */ - int bufused; - int rbuf_args[3]; /* indices in lua registry for receive_buf args */ - - struct ncap_socket *ncap_socket; - struct ncap_request *ncap_request; - int ncap_cback_ref; -}; - -void l_nsock_clear_buf(lua_State *L, l_nsock_udata* udata); - -int luaopen_nsock (lua_State *L) + */ +struct ncap_request { - /* nsock:connect(socket, ...) - * - * This Lua function is a wrapper around the actual l_nsock_connect. - * The connect function must get a lock through socket_lock (C function - * above). Once it has the lock, it can (tail call) return the actual - * connect function. - */ + int suspended; /* is the thread suspended? + * (lua_yield) */ + // lua_State *L; /* lua_State of current process or NULL if process isn't + // suspended */ + struct nsock_yield *yield; + nsock_event_id nseid; /* nse for this specific + * lua_State */ + struct timeval end_time; + char *key; /* (free) zero-terminated key + * used in map to * address + * this structure (hexified + * 'test') */ + + bool received; /* are results ready? */ + + bool r_success; /* true-> okay,data ready to + * pass to user * flase-> this + * statusstring contains error + * description */ + char *r_status; /* errorstring */ + + unsigned char *r_layer2; + size_t r_layer2_len; + unsigned char *r_layer3; + size_t r_layer3_len; + size_t packetsz; + + int ncap_cback_ref; /* just copy of + * udata->ncap_cback_ref * + * because we don't have + * access to udata in place * + * we need to use this. */ +}; + +struct l_nsock_udata +{ + int timeout; + nsock_iod nsiod; + void *ssl_session; + struct nsock_yield yield; + /* used for buffered reading */ + int bufidx; /* index inside lua's registry + */ + int bufused; + int rbuf_args[3]; /* indices in lua registry for + * receive_buf args */ + + struct ncap_socket *ncap_socket; + struct ncap_request *ncap_request; + int ncap_cback_ref; +}; + +void l_nsock_clear_buf(lua_State * L, l_nsock_udata * udata); + +int luaopen_nsock(lua_State * L) +{ + /* nsock:connect(socket, ...) This Lua function is a wrapper around the + * actual l_nsock_connect. The connect function must get a lock through + * socket_lock (C function above). Once it has the lock, it can (tail call) + * return the actual connect function. */ static const char connect[] = - "local connect, socket_lock = ...;\n" - "return function(socket, ...)\n" - " repeat until socket_lock(socket) == true;\n" - " return connect(socket, ...);\n" - "end"; + "local connect, socket_lock = ...;\n" + "return function(socket, ...)\n" + " repeat until socket_lock(socket) == true;\n" + " return connect(socket, ...);\n" "end"; static const luaL_Reg l_nsock[] = { {"send", l_nsock_send}, @@ -333,37 +366,37 @@ int luaopen_nsock (lua_State *L) {"pcap_close", l_nsock_ncap_close}, {"pcap_register", l_nsock_ncap_register}, {"pcap_receive", l_nsock_pcap_receive}, - //{"callback_test", l_nsock_pcap_callback_test}, + // {"callback_test", l_nsock_pcap_callback_test}, {NULL, NULL} }; - /* Set up an environment for all nsock C functions to share. - * This is especially important to make the THREAD_PROXY, SOCKET_PROXY, - * and CONNECT_WAITING tables available. These values can be accessed - * at the pseudo-index LUA_ENVIRONINDEX. These tables are documented - * where the #defines are above. - */ + /* Set up an environment for all nsock C functions to share. This is + * especially important to make the THREAD_PROXY, SOCKET_PROXY, and + * CONNECT_WAITING tables available. These values can be accessed at the + * pseudo-index LUA_ENVIRONINDEX. These tables are documented where the + * #defines are above. */ lua_createtable(L, 5, 0); lua_replace(L, LUA_ENVIRONINDEX); - lua_createtable(L, 0, 10); // THREAD_PROXY - lua_createtable(L, 0, 1); // metatable - lua_pushliteral(L, "kv"); // weak keys and values + lua_createtable(L, 0, 10); // THREAD_PROXY + lua_createtable(L, 0, 1); // metatable + lua_pushliteral(L, "kv"); // weak keys and values lua_setfield(L, -2, "__mode"); lua_setmetatable(L, -2); lua_rawseti(L, LUA_ENVIRONINDEX, THREAD_PROXY); - lua_createtable(L, 0, 193); // SOCKET_PROXY (large amount of room) - lua_createtable(L, 0, 1); // metatable - lua_pushliteral(L, "k"); // weak keys + lua_createtable(L, 0, 193); // SOCKET_PROXY (large amount of room) + lua_createtable(L, 0, 1); // metatable + lua_pushliteral(L, "k"); // weak keys lua_setfield(L, -2, "__mode"); lua_setmetatable(L, -2); lua_rawseti(L, LUA_ENVIRONINDEX, SOCKET_PROXY); - lua_createtable(L, 0, 499); // CONNECT_WAITING (large amount of room) + lua_createtable(L, 0, 499); // CONNECT_WAITING (large amount of + // room) lua_rawseti(L, LUA_ENVIRONINDEX, CONNECT_WAITING); - lua_createtable(L, 0, 1); // PROXY_META = metatable for proxies + lua_createtable(L, 0, 1); // PROXY_META = metatable for proxies lua_pushcclosure(L, proxy_gc, 0); lua_setfield(L, -2, "__gc"); lua_rawseti(L, LUA_ENVIRONINDEX, PROXY_META); @@ -373,22 +406,23 @@ int luaopen_nsock (lua_State *L) fatal("connect did not compile!"); lua_pushcclosure(L, l_nsock_connect, 0); lua_pushcclosure(L, socket_lock, 0); - lua_call(L, 2, 1); // leave connect function on stack... + lua_call(L, 2, 1); // leave connect function on stack... lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_setfenv(L, -2); // set the connect function's environment to _G + lua_setfenv(L, -2); // set the connect function's + // environment to _G /* Create the nsock metatable for sockets */ luaL_newmetatable(L, "nsock"); lua_createtable(L, 0, 23); luaL_register(L, NULL, l_nsock); - lua_pushvalue(L, -3); // connect function + lua_pushvalue(L, -3); // connect function lua_setfield(L, -2, "connect"); lua_setfield(L, -2, "__index"); lua_pushcclosure(L, l_nsock_gc, 0); lua_setfield(L, -2, "__gc"); lua_newtable(L); - lua_setfield(L, -2, "__metatable"); // protect metatable - lua_pop(L, 1); // nsock metatable + lua_setfield(L, -2, "__metatable"); // protect metatable + lua_pop(L, 1); // nsock metatable luaL_newmetatable(L, "nsock_proxy"); @@ -403,610 +437,750 @@ int luaopen_nsock (lua_State *L) return 0; } -int l_nsock_new(lua_State *L) { - struct l_nsock_udata* udata; - udata = (struct l_nsock_udata*) lua_newuserdata(L, sizeof(struct l_nsock_udata)); - luaL_getmetatable(L, "nsock"); - lua_setmetatable(L, -2); - udata->nsiod = NULL; - udata->ssl_session = NULL; - udata->timeout = DEFAULT_TIMEOUT; - udata->bufidx = LUA_NOREF; - udata->bufused= 0; - udata->rbuf_args[0] = LUA_NOREF; - udata->rbuf_args[1] = LUA_NOREF; - udata->rbuf_args[2] = LUA_NOREF; - udata->ncap_socket = NULL; - udata->ncap_request = NULL; - udata->ncap_cback_ref = 0; - - return 1; +int l_nsock_new(lua_State * L) +{ + struct l_nsock_udata *udata; + + udata = + (struct l_nsock_udata *) lua_newuserdata(L, sizeof(struct l_nsock_udata)); + luaL_getmetatable(L, "nsock"); + lua_setmetatable(L, -2); + udata->nsiod = NULL; + udata->ssl_session = NULL; + udata->timeout = DEFAULT_TIMEOUT; + udata->bufidx = LUA_NOREF; + udata->bufused = 0; + udata->rbuf_args[0] = LUA_NOREF; + udata->rbuf_args[1] = LUA_NOREF; + udata->rbuf_args[2] = LUA_NOREF; + udata->ncap_socket = NULL; + udata->ncap_request = NULL; + udata->ncap_cback_ref = 0; + + return 1; } -int l_nsock_loop(int tout) { - return nsock_loop(nsp, tout); +int l_nsock_loop(int tout) +{ + return nsock_loop(nsp, tout); } -int l_nsock_checkstatus(lua_State *L, nsock_event nse) { - enum nse_status status = nse_status(nse); +int l_nsock_checkstatus(lua_State * L, nsock_event nse) +{ + enum nse_status status = nse_status(nse); - switch (status) { - case NSE_STATUS_SUCCESS: - lua_pushboolean(L, true); - return NSOCK_WRAPPER_SUCCESS; - break; - case NSE_STATUS_ERROR: - case NSE_STATUS_TIMEOUT: - case NSE_STATUS_CANCELLED: - case NSE_STATUS_KILL: - case NSE_STATUS_EOF: - lua_pushnil(L); - lua_pushstring(L, nse_status2str(status)); - return NSOCK_WRAPPER_ERROR; - break; - case NSE_STATUS_NONE: - default: - fatal("%s: In: %s:%i This should never happen.", - NSOCK_WRAPPER, __FILE__, __LINE__); - break; - - } + switch (status) + { + case NSE_STATUS_SUCCESS: + lua_pushboolean(L, true); + return NSOCK_WRAPPER_SUCCESS; + break; + case NSE_STATUS_ERROR: + case NSE_STATUS_TIMEOUT: + case NSE_STATUS_CANCELLED: + case NSE_STATUS_KILL: + case NSE_STATUS_EOF: + lua_pushnil(L); + lua_pushstring(L, nse_status2str(status)); + return NSOCK_WRAPPER_ERROR; + break; + case NSE_STATUS_NONE: + default: + fatal("%s: In: %s:%i This should never happen.", + NSOCK_WRAPPER, __FILE__, __LINE__); + break; - return -1; + } + + return -1; } -static int l_nsock_connect(lua_State *L) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - const char* addr = luaL_checkstring(L, 2); - unsigned short port = (unsigned short) luaL_checkint(L, 3); - const char *how = luaL_optstring(L, 4, "tcp"); +static int l_nsock_connect(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - const char* error; - struct addrinfo *dest; - int error_id; - - l_nsock_clear_buf(L, udata); - - error_id = getaddrinfo(addr, NULL, NULL, &dest); - if (error_id) { - socket_unlock(L, 1); - error = gai_strerror(error_id); - lua_pushboolean(L, false); - lua_pushstring(L, error); - return 2; - } - if (dest == NULL) { - socket_unlock(L, 1); - lua_pushboolean(L, false); - lua_pushstring(L, "getaddrinfo returned success but no addresses"); - return 2; - } + const char *addr = luaL_checkstring(L, 2); - udata->nsiod = nsi_new(nsp, NULL); - if (o.spoofsource) { - struct sockaddr_storage ss; - size_t sslen; - o.SourceSockAddr(&ss, &sslen); - nsi_set_localaddr(udata->nsiod, &ss, sslen); - } - if (o.ipoptionslen) - nsi_set_ipoptions(udata->nsiod, o.ipoptions, o.ipoptionslen); + unsigned short port = (unsigned short) luaL_checkint(L, 3); - switch (how[0]) { - case 't': - if (strcmp(how, "tcp")) goto error; - nsock_connect_tcp(nsp, udata->nsiod, l_nsock_connect_handler, - udata->timeout, &udata->yield, dest->ai_addr, dest->ai_addrlen, port); - break; - case 'u': - if (strcmp(how, "udp")) goto error; - nsock_connect_udp(nsp, udata->nsiod, l_nsock_connect_handler, - &udata->yield, dest->ai_addr, dest->ai_addrlen, port); - break; - case 's': - if (strcmp(how, "ssl")) goto error; + const char *how = luaL_optstring(L, 4, "tcp"); + + const char *error; + + struct addrinfo *dest; + + int error_id; + + l_nsock_clear_buf(L, udata); + + error_id = getaddrinfo(addr, NULL, NULL, &dest); + if (error_id) + { + socket_unlock(L, 1); + error = gai_strerror(error_id); + lua_pushboolean(L, false); + lua_pushstring(L, error); + return 2; + } + if (dest == NULL) + { + socket_unlock(L, 1); + lua_pushboolean(L, false); + lua_pushstring(L, "getaddrinfo returned success but no addresses"); + return 2; + } + + udata->nsiod = nsi_new(nsp, NULL); + if (o.spoofsource) + { + struct sockaddr_storage ss; + + size_t sslen; + + o.SourceSockAddr(&ss, &sslen); + nsi_set_localaddr(udata->nsiod, &ss, sslen); + } + if (o.ipoptionslen) + nsi_set_ipoptions(udata->nsiod, o.ipoptions, o.ipoptionslen); + + switch (how[0]) + { + case 't': + if (strcmp(how, "tcp")) + goto error; + nsock_connect_tcp(nsp, udata->nsiod, l_nsock_connect_handler, + udata->timeout, &udata->yield, dest->ai_addr, dest->ai_addrlen, port); + break; + case 'u': + if (strcmp(how, "udp")) + goto error; + nsock_connect_udp(nsp, udata->nsiod, l_nsock_connect_handler, + &udata->yield, dest->ai_addr, dest->ai_addrlen, port); + break; + case 's': + if (strcmp(how, "ssl")) + goto error; #ifdef HAVE_OPENSSL - nsock_connect_ssl(nsp, udata->nsiod, l_nsock_connect_handler, - udata->timeout, &udata->yield, dest->ai_addr, dest->ai_addrlen, port, - udata->ssl_session); - break; + nsock_connect_ssl(nsp, udata->nsiod, l_nsock_connect_handler, + udata->timeout, &udata->yield, dest->ai_addr, dest->ai_addrlen, port, + udata->ssl_session); + break; #else - socket_unlock(L, 1); - lua_pushboolean(L, false); - lua_pushstring(L, "Sorry, you don't have OpenSSL\n"); - return 2; + socket_unlock(L, 1); + lua_pushboolean(L, false); + lua_pushstring(L, "Sorry, you don't have OpenSSL\n"); + return 2; #endif - default: - goto error; - break; - } + default: + goto error; + break; + } - freeaddrinfo(dest); - udata->yield.thread = L; - return lua_yield(L, 0); + freeaddrinfo(dest); + udata->yield.thread = L; + return lua_yield(L, 0); error: - socket_unlock(L, 1); - freeaddrinfo(dest); - luaL_argerror(L, 4, "invalid connection method"); - return 0; + socket_unlock(L, 1); + freeaddrinfo(dest); + luaL_argerror(L, 4, "invalid connection method"); + return 0; } -void l_nsock_connect_handler(nsock_pool nsp, nsock_event nse, void *yield) { - struct nsock_yield *y = (struct nsock_yield *) yield; - lua_State *L = y->thread; +void l_nsock_connect_handler(nsock_pool nsp, nsock_event nse, void *yield) +{ + struct nsock_yield *y = (struct nsock_yield *) yield; - if(o.scriptTrace()) { - l_nsock_trace(nse_iod(nse), "CONNECT", TO); - } + lua_State *L = y->thread; - if(l_nsock_checkstatus(L, nse) == NSOCK_WRAPPER_SUCCESS) { - nse_restore(y->thread, 1); - } else { - nse_restore(y->thread, 2); - } + if (o.scriptTrace()) + { + l_nsock_trace(nse_iod(nse), "CONNECT", TO); + } + + if (l_nsock_checkstatus(L, nse) == NSOCK_WRAPPER_SUCCESS) + { + nse_restore(y->thread, 1); + } else + { + nse_restore(y->thread, 2); + } } -static int l_nsock_send(lua_State *L) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - const char* string = luaL_checkstring(L, 2); - size_t string_len = lua_objlen (L, 2); - - l_nsock_clear_buf(L,udata); +static int l_nsock_send(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - if(udata->nsiod == NULL) { - lua_pushboolean(L, false); - lua_pushstring(L, "Trying to send through a closed socket\n"); - return 2; - } + const char *string = luaL_checkstring(L, 2); - if(o.scriptTrace()) - l_nsock_trace(udata->nsiod, hexify((unsigned char *) string, string_len).c_str(), TO); + size_t string_len = lua_objlen(L, 2); - nsock_write(nsp, udata->nsiod, l_nsock_send_handler, udata->timeout, &udata->yield, string, string_len); - udata->yield.thread = L; - return lua_yield(L, 0); + l_nsock_clear_buf(L, udata); + + if (udata->nsiod == NULL) + { + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to send through a closed socket\n"); + return 2; + } + + if (o.scriptTrace()) + l_nsock_trace(udata->nsiod, hexify((unsigned char *) string, + string_len).c_str(), TO); + + nsock_write(nsp, udata->nsiod, l_nsock_send_handler, udata->timeout, + &udata->yield, string, string_len); + udata->yield.thread = L; + return lua_yield(L, 0); } -void l_nsock_send_handler(nsock_pool nsp, nsock_event nse, void *yield) { - struct nsock_yield *y = (struct nsock_yield *) yield; - lua_State *L = y->thread; - - if(l_nsock_checkstatus(L, nse) == NSOCK_WRAPPER_SUCCESS) { - nse_restore(y->thread, 1); - } else { - nse_restore(y->thread, 2); - } +void l_nsock_send_handler(nsock_pool nsp, nsock_event nse, void *yield) +{ + struct nsock_yield *y = (struct nsock_yield *) yield; + + lua_State *L = y->thread; + + if (l_nsock_checkstatus(L, nse) == NSOCK_WRAPPER_SUCCESS) + { + nse_restore(y->thread, 1); + } else + { + nse_restore(y->thread, 2); + } } -static int l_nsock_receive(lua_State *L) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - l_nsock_clear_buf(L, udata); +static int l_nsock_receive(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - if(udata->nsiod == NULL) { - lua_pushboolean(L, false); - lua_pushstring(L, "Trying to receive through a closed socket\n"); - return 2; - } + l_nsock_clear_buf(L, udata); - nsock_read(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, &udata->yield); + if (udata->nsiod == NULL) + { + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to receive through a closed socket\n"); + return 2; + } - udata->yield.thread = L; - return lua_yield(L, 0); + nsock_read(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, + &udata->yield); + + udata->yield.thread = L; + return lua_yield(L, 0); } -static int l_nsock_receive_lines(lua_State *L) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - int nlines = (int) luaL_checknumber(L, 2); +static int l_nsock_receive_lines(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - l_nsock_clear_buf(L, udata); - - if(udata->nsiod == NULL) { - lua_pushboolean(L, false); - lua_pushstring(L, "Trying to receive lines through a closed socket\n"); - return 2; - } + int nlines = (int) luaL_checknumber(L, 2); - nsock_readlines(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, &udata->yield, nlines); + l_nsock_clear_buf(L, udata); + if (udata->nsiod == NULL) + { + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to receive lines through a closed socket\n"); + return 2; + } - udata->yield.thread = L; - return lua_yield(L, 0); + nsock_readlines(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, + &udata->yield, nlines); + + udata->yield.thread = L; + return lua_yield(L, 0); } -static int l_nsock_receive_bytes(lua_State *L) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - int nbytes = (int) luaL_checknumber(L, 2); - - l_nsock_clear_buf(L, udata); +static int l_nsock_receive_bytes(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - if(udata->nsiod == NULL) { - lua_pushboolean(L, false); - lua_pushstring(L, "Trying to receive bytes through a closed socket\n"); - return 2; - } + int nbytes = (int) luaL_checknumber(L, 2); - nsock_readbytes(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, &udata->yield, nbytes); + l_nsock_clear_buf(L, udata); - udata->yield.thread = L; - return lua_yield(L, 0); + if (udata->nsiod == NULL) + { + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to receive bytes through a closed socket\n"); + return 2; + } + + nsock_readbytes(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, + &udata->yield, nbytes); + + udata->yield.thread = L; + return lua_yield(L, 0); } -void l_nsock_receive_handler(nsock_pool nsp, nsock_event nse, void *yield) { - struct nsock_yield *y = (struct nsock_yield *) yield; - lua_State *L = y->thread; - char* rcvd_string; - int rcvd_len = 0; +void l_nsock_receive_handler(nsock_pool nsp, nsock_event nse, void *yield) +{ + struct nsock_yield *y = (struct nsock_yield *) yield; - if(l_nsock_checkstatus(L, nse) == NSOCK_WRAPPER_SUCCESS) { - rcvd_string = nse_readbuf(nse, &rcvd_len); + lua_State *L = y->thread; - if(o.scriptTrace()) - l_nsock_trace(nse_iod(nse), hexify((unsigned char *) rcvd_string, (size_t) rcvd_len).c_str(), FROM); + char *rcvd_string; - lua_pushlstring(L, rcvd_string, rcvd_len); - nse_restore(y->thread, 2); - } else { - nse_restore(y->thread, 2); - } + int rcvd_len = 0; + + if (l_nsock_checkstatus(L, nse) == NSOCK_WRAPPER_SUCCESS) + { + rcvd_string = nse_readbuf(nse, &rcvd_len); + + if (o.scriptTrace()) + l_nsock_trace(nse_iod(nse), hexify((unsigned char *) rcvd_string, + (size_t) rcvd_len).c_str(), FROM); + + lua_pushlstring(L, rcvd_string, rcvd_len); + nse_restore(y->thread, 2); + } else + { + nse_restore(y->thread, 2); + } } -void l_nsock_trace(nsock_iod nsiod, const char* message, int direction) { - int status; - int protocol; - int af; - struct sockaddr local; - struct sockaddr remote; - char* ipstring_local = (char*) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); - char* ipstring_remote = (char*) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); +void l_nsock_trace(nsock_iod nsiod, const char *message, int direction) +{ + int status; - if(!nsi_is_pcap(nsiod)){ - status = nsi_getlastcommunicationinfo(nsiod, &protocol, &af, - &local, &remote, sizeof(sockaddr)); - log_write(LOG_STDOUT, "%s: %s %s:%d %s %s:%d | %s\n", - SCRIPT_ENGINE, - (protocol == IPPROTO_TCP)? "TCP" : "UDP", - inet_ntop_both(af, &local, ipstring_local), - inet_port_both(af, &local), - (direction == TO)? ">" : "<", - inet_ntop_both(af, &remote, ipstring_remote), - inet_port_both(af, &remote), - message); + int protocol; - free(ipstring_local); - free(ipstring_remote); - }else{ // is pcap device - log_write(LOG_STDOUT, "%s: %s | %s\n", - SCRIPT_ENGINE, - (direction == TO)? ">" : "<", - message); - } + int af; + + struct sockaddr local; + + struct sockaddr remote; + + char *ipstring_local = (char *) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); + + char *ipstring_remote = (char *) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); + + if (!nsi_is_pcap(nsiod)) + { + status = nsi_getlastcommunicationinfo(nsiod, &protocol, &af, + &local, &remote, sizeof(sockaddr)); + log_write(LOG_STDOUT, "%s: %s %s:%d %s %s:%d | %s\n", + SCRIPT_ENGINE, + (protocol == IPPROTO_TCP) ? "TCP" : "UDP", + inet_ntop_both(af, &local, ipstring_local), + inet_port_both(af, &local), + (direction == TO) ? ">" : "<", + inet_ntop_both(af, &remote, ipstring_remote), + inet_port_both(af, &remote), message); + + free(ipstring_local); + free(ipstring_remote); + } else + { // is pcap device + log_write(LOG_STDOUT, "%s: %s | %s\n", + SCRIPT_ENGINE, (direction == TO) ? ">" : "<", message); + } } -const char* inet_ntop_both(int af, const void* v_addr, char* ipstring) { -// char* ipstring = (char*) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); +const char *inet_ntop_both(int af, const void *v_addr, char *ipstring) +{ +// char* ipstring = (char*) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); - if(af == AF_INET) { - inet_ntop(AF_INET, &((struct sockaddr_in*) v_addr)->sin_addr, - ipstring, INET6_ADDRSTRLEN); + if (af == AF_INET) + { + inet_ntop(AF_INET, &((struct sockaddr_in *) v_addr)->sin_addr, + ipstring, INET6_ADDRSTRLEN); - return ipstring; - } + return ipstring; + } #ifdef HAVE_IPV6 - else if(af == AF_INET6) { - inet_ntop(AF_INET6, &((struct sockaddr_in6*) v_addr)->sin6_addr, - ipstring, INET6_ADDRSTRLEN); - return ipstring; - } + else if (af == AF_INET6) + { + inet_ntop(AF_INET6, &((struct sockaddr_in6 *) v_addr)->sin6_addr, + ipstring, INET6_ADDRSTRLEN); + return ipstring; + } #endif - else { - return "unknown protocol"; - } + else + { + return "unknown protocol"; + } } -unsigned short inet_port_both(int af, const void* v_addr) { - int port; - if(af == AF_INET) { - port = ((struct sockaddr_in*) v_addr)->sin_port; - } +unsigned short inet_port_both(int af, const void *v_addr) +{ + int port; + + if (af == AF_INET) + { + port = ((struct sockaddr_in *) v_addr)->sin_port; + } #ifdef HAVE_IPV6 - else if(af == AF_INET6) { - port = ((struct sockaddr_in6*) v_addr)->sin6_port; - } + else if (af == AF_INET6) + { + port = ((struct sockaddr_in6 *) v_addr)->sin6_port; + } #endif - else { - port = 0; - } - - return ntohs(port); + else + { + port = 0; + } + + return ntohs(port); } -static int l_nsock_get_info(lua_State *L) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - int status; +static int l_nsock_get_info(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - int protocol; // tcp or udp - int af; // address family - struct sockaddr local; - struct sockaddr remote; - char* ipstring_local = (char*) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); - char* ipstring_remote = (char*) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); + int status; - if(udata->nsiod == NULL) { - lua_pushboolean(L, false); - lua_pushstring(L, "Trying to get info from a closed socket\n"); - return 2; - } + int protocol; // tcp or udp - status = nsi_getlastcommunicationinfo(udata->nsiod, &protocol, &af, - &local, &remote, sizeof(sockaddr)); + int af; // address family - lua_pushboolean(L, true); + struct sockaddr local; - lua_pushstring(L, inet_ntop_both(af, &local, ipstring_local)); - lua_pushnumber(L, inet_port_both(af, &local)); + struct sockaddr remote; - lua_pushstring(L, inet_ntop_both(af, &remote, ipstring_remote)); - lua_pushnumber(L, inet_port_both(af, &remote)); + char *ipstring_local = (char *) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); - free(ipstring_local); - free(ipstring_remote); - return 5; -} -static int l_nsock_gc(lua_State *L){ - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - if(udata->nsiod == NULL) { //socket obviously got closed already - so no finalization needed - return 0; - }else{ - //FIXME - check wheter close returned true!! - for (int i = 0; i < 3; i++) - luaL_unref(L, LUA_REGISTRYINDEX, udata->rbuf_args[i]); - l_nsock_close(L); - } - return 0; + char *ipstring_remote = (char *) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); + + if (udata->nsiod == NULL) + { + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to get info from a closed socket\n"); + return 2; + } + + status = nsi_getlastcommunicationinfo(udata->nsiod, &protocol, &af, + &local, &remote, sizeof(sockaddr)); + + lua_pushboolean(L, true); + + lua_pushstring(L, inet_ntop_both(af, &local, ipstring_local)); + lua_pushnumber(L, inet_port_both(af, &local)); + + lua_pushstring(L, inet_ntop_both(af, &remote, ipstring_remote)); + lua_pushnumber(L, inet_port_both(af, &remote)); + + free(ipstring_local); + free(ipstring_remote); + return 5; } -static int l_nsock_close(lua_State *L) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); +static int l_nsock_gc(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - socket_unlock(L, 1); // Unlock the socket. + if (udata->nsiod == NULL) + { // socket obviously got closed already - + // so no finalization needed + return 0; + } else + { + // FIXME - check wheter close returned true!! + for (int i = 0; i < 3; i++) + luaL_unref(L, LUA_REGISTRYINDEX, udata->rbuf_args[i]); + l_nsock_close(L); + } + return 0; +} - /* Never ever collect nse-pcap connections. */ - if(udata->ncap_socket){ - return 0; - } - - l_nsock_clear_buf(L, udata); +static int l_nsock_close(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - if(udata->nsiod == NULL) { - lua_pushboolean(L, false); - lua_pushstring(L, "Trying to close a closed socket\n"); - return 2; - } + socket_unlock(L, 1); // Unlock the socket. - if(o.scriptTrace()) { - l_nsock_trace(udata->nsiod, "CLOSE", TO); - } + /* Never ever collect nse-pcap connections. */ + if (udata->ncap_socket) + { + return 0; + } + l_nsock_clear_buf(L, udata); + + if (udata->nsiod == NULL) + { + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to close a closed socket\n"); + return 2; + } + + if (o.scriptTrace()) + { + l_nsock_trace(udata->nsiod, "CLOSE", TO); + } #ifdef HAVE_OPENSSL - if (udata->ssl_session) - SSL_SESSION_free((SSL_SESSION*)udata->ssl_session); - udata->ssl_session=NULL; + if (udata->ssl_session) + SSL_SESSION_free((SSL_SESSION *) udata->ssl_session); + udata->ssl_session = NULL; #endif - nsi_delete(udata->nsiod, NSOCK_PENDING_NOTIFY); + nsi_delete(udata->nsiod, NSOCK_PENDING_NOTIFY); - udata->nsiod = NULL; + udata->nsiod = NULL; - lua_pushboolean(L, true); - return 1; + lua_pushboolean(L, true); + return 1; } -static int l_nsock_set_timeout(lua_State *L) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - int timeout = (unsigned short) luaL_checkint(L, 2); +static int l_nsock_set_timeout(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - udata->timeout = timeout; + int timeout = (unsigned short) luaL_checkint(L, 2); - return 0; + udata->timeout = timeout; + + return 0; } /* buffered I/O */ -static int l_nsock_receive_buf(lua_State *L) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - lua_settop(L, 3); - udata->yield.udata = udata; - for (int i = 0; i < 3; i++) { /* compatibility, clean up someday */ - lua_pushvalue(L, i+1); /* argument 1-3 */ - udata->rbuf_args[i] = luaL_ref(L, LUA_REGISTRYINDEX); - } - if(udata->nsiod == NULL) { - lua_pushboolean(L, false); - lua_pushstring(L, "Trying to receive through a closed socket\n"); - return 2; - } - if(udata->bufused==0){ - lua_pushstring(L,""); - udata->bufidx = luaL_ref(L, LUA_REGISTRYINDEX); - udata->bufused=1; - nsock_read(nsp, udata->nsiod, l_nsock_receive_buf_handler, udata->timeout, &udata->yield); - }else if(udata->bufused==-1){ /*error message is inside the buffer*/ - lua_pushboolean(L,false); - lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); - return 2; - }else{ /*buffer contains already some data */ - /*we keep track here of how many calls to receive_buf are made */ - udata->bufused++; - if(l_nsock_check_buf(L)==NSOCK_WRAPPER_BUFFER_MOREREAD){ - /*if we didn't have enough data in the buffer another nsock_read() - * was scheduled - its callback will put us in running state again - */ - udata->yield.thread = L; - return lua_yield(L, 0); - } - return 2; - } - /*yielding with 3 arguments since we need them when the callback arrives */ - udata->yield.thread = L; - return lua_yield(L, 0); +static int l_nsock_receive_buf(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); + + lua_settop(L, 3); + udata->yield.udata = udata; + for (int i = 0; i < 3; i++) + { /* compatibility, clean up someday */ + lua_pushvalue(L, i + 1); /* argument 1-3 */ + udata->rbuf_args[i] = luaL_ref(L, LUA_REGISTRYINDEX); + } + if (udata->nsiod == NULL) + { + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to receive through a closed socket\n"); + return 2; + } + if (udata->bufused == 0) + { + lua_pushstring(L, ""); + udata->bufidx = luaL_ref(L, LUA_REGISTRYINDEX); + udata->bufused = 1; + nsock_read(nsp, udata->nsiod, l_nsock_receive_buf_handler, udata->timeout, + &udata->yield); + } else if (udata->bufused == -1) + { /* error message is inside the buffer */ + lua_pushboolean(L, false); + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); + return 2; + } else + { /* buffer contains already some data */ + /* we keep track here of how many calls to receive_buf are made */ + udata->bufused++; + if (l_nsock_check_buf(L) == NSOCK_WRAPPER_BUFFER_MOREREAD) + { + /* if we didn't have enough data in the buffer another nsock_read() was + * scheduled - its callback will put us in running state again */ + udata->yield.thread = L; + return lua_yield(L, 0); + } + return 2; + } + /* yielding with 3 arguments since we need them when the callback arrives */ + udata->yield.thread = L; + return lua_yield(L, 0); } -void l_nsock_receive_buf_handler(nsock_pool nsp, nsock_event nse, void *yield) { - struct nsock_yield *y = (struct nsock_yield *) yield; - l_nsock_udata *udata = y->udata; - lua_State *L= y->thread; - char* rcvd_string; - int rcvd_len = 0; - int tmpidx; - /* set stack values, this all needs fixing... */ - for (int i = 0; i < 3; i++) { - lua_rawgeti(L, LUA_REGISTRYINDEX, udata->rbuf_args[i]); - luaL_unref(L, LUA_REGISTRYINDEX, udata->rbuf_args[i]); - udata->rbuf_args[i] = LUA_NOREF; - } - if(l_nsock_checkstatus(L, nse) == NSOCK_WRAPPER_SUCCESS) { - - //l_nsock_checkstatus pushes true on the stack in case of success - // we do this on our own here - lua_pop(L,1); +void l_nsock_receive_buf_handler(nsock_pool nsp, nsock_event nse, void *yield) +{ + struct nsock_yield *y = (struct nsock_yield *) yield; - rcvd_string = nse_readbuf(nse, &rcvd_len); - - if(o.scriptTrace()) - l_nsock_trace(nse_iod(nse), hexify((unsigned char *) rcvd_string, (size_t) rcvd_len).c_str(), FROM); - /* push the buffer and what we received from nsock on the stack and - * concatenate both*/ - lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); - lua_pushlstring(L, rcvd_string, rcvd_len); - lua_concat (L, 2); - luaL_unref(L, LUA_REGISTRYINDEX, udata->bufidx); - udata->bufidx = luaL_ref(L, LUA_REGISTRYINDEX); - if(l_nsock_check_buf(L)==NSOCK_WRAPPER_BUFFER_MOREREAD){ - /*if there wasn't enough data in the buffer and we've issued another - * nsock_read() the next callback will schedule the script for running - */ - return; - } - nse_restore(y->thread, 2); - } else { - if(udata->bufused>1){ - /*error occured after we read into some data into the buffer - * behave as if there was no error and push the rest of the buffer - * and clean the buffer afterwards - */ - /*save the error message inside the buffer*/ - tmpidx=luaL_ref(L, LUA_REGISTRYINDEX); - /*pop the status (==false) of the stack*/ - lua_pop(L,1); - lua_pushboolean(L, true); - lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); - l_nsock_clear_buf(L, udata); - udata->bufidx=tmpidx; - udata->bufused=-1; - nse_restore(y->thread, 2); - }else{ /*buffer should be empty */ - nse_restore(y->thread, 2); - } - } + l_nsock_udata *udata = y->udata; + + lua_State *L = y->thread; + + char *rcvd_string; + + int rcvd_len = 0; + + int tmpidx; + + /* set stack values, this all needs fixing... */ + for (int i = 0; i < 3; i++) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->rbuf_args[i]); + luaL_unref(L, LUA_REGISTRYINDEX, udata->rbuf_args[i]); + udata->rbuf_args[i] = LUA_NOREF; + } + if (l_nsock_checkstatus(L, nse) == NSOCK_WRAPPER_SUCCESS) + { + + // l_nsock_checkstatus pushes true on the stack in case of success + // we do this on our own here + lua_pop(L, 1); + + rcvd_string = nse_readbuf(nse, &rcvd_len); + + if (o.scriptTrace()) + l_nsock_trace(nse_iod(nse), hexify((unsigned char *) rcvd_string, + (size_t) rcvd_len).c_str(), FROM); + /* push the buffer and what we received from nsock on the stack and + * concatenate both */ + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); + lua_pushlstring(L, rcvd_string, rcvd_len); + lua_concat(L, 2); + luaL_unref(L, LUA_REGISTRYINDEX, udata->bufidx); + udata->bufidx = luaL_ref(L, LUA_REGISTRYINDEX); + if (l_nsock_check_buf(L) == NSOCK_WRAPPER_BUFFER_MOREREAD) + { + /* if there wasn't enough data in the buffer and we've issued another + * nsock_read() the next callback will schedule the script for running */ + return; + } + nse_restore(y->thread, 2); + } else + { + if (udata->bufused > 1) + { + /* error occured after we read into some data into the buffer behave as + * if there was no error and push the rest of the buffer and clean the + * buffer afterwards */ + /* save the error message inside the buffer */ + tmpidx = luaL_ref(L, LUA_REGISTRYINDEX); + /* pop the status (==false) of the stack */ + lua_pop(L, 1); + lua_pushboolean(L, true); + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); + l_nsock_clear_buf(L, udata); + udata->bufidx = tmpidx; + udata->bufused = -1; + nse_restore(y->thread, 2); + } else + { /* buffer should be empty */ + nse_restore(y->thread, 2); + } + } } -int l_nsock_check_buf(lua_State *L ){ - l_nsock_udata* udata; - size_t startpos, endpos, bufsize; - const char *tmpbuf; - int tmpidx; - int keeppattern; - /*should we return the string including the pattern or without it */ - keeppattern= lua_toboolean(L,-1); - lua_pop(L,1); - udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - if(lua_isfunction(L,2)){ - lua_pushvalue(L,2); - lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); /* the buffer is the only argument to the function */ - if(lua_pcall(L,1,2,0)!=0){ - lua_pushboolean(L,false); - lua_pushfstring(L,"Error inside splitting-function: %s\n", lua_tostring(L,-1)); - return NSOCK_WRAPPER_BUFFER_OK; - //luaL_error(L,"Error inside splitting-function, given as argument to nsockobj:receive_buf: %s\n", lua_tostring(L,-1)); - } - }else if(lua_isstring(L,2)){ - lua_getglobal(L,"string"); - lua_getfield(L,-1,"find"); - lua_remove(L, -2); /*drop the string-table, since we don't need it! */ - lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); - lua_pushvalue(L,2); /*the pattern we are searching for */ - if(lua_pcall(L,2,2,0)!=0){ - lua_pushboolean(L,false); - lua_pushstring(L,"Error in string.find (nsockobj:receive_buf)!"); - return NSOCK_WRAPPER_BUFFER_OK; - } - }else{ - lua_pushboolean(L,false); - lua_pushstring(L,"Expected either a function or a string!"); - return NSOCK_WRAPPER_BUFFER_OK; - //luaL_argerror(L,2,"expected either a function or a string!"); - } - /*the stack contains on top the indices where we want to seperate */ - if(lua_isnil(L,-1)){ /*not found anything try to read more data*/ - lua_pop(L,2); - nsock_read(nsp, udata->nsiod, l_nsock_receive_buf_handler, udata->timeout, &udata->yield); - lua_pushboolean(L,keeppattern); - return NSOCK_WRAPPER_BUFFER_MOREREAD; - }else{ - startpos = (size_t) lua_tointeger(L, -2); - endpos = (size_t) lua_tointeger(L, -1); - lua_settop(L,0); /* clear the stack for returning */ - if(startpos>endpos){ - lua_pushboolean(L,false); - lua_pushstring(L,"Delimiter has negative size!"); - return NSOCK_WRAPPER_BUFFER_OK; - }else if(startpos==endpos){ - /* if the delimter has a size of zero we keep it, since otherwise - * retured string would be trucated - */ - keeppattern=1; - } - lua_settop(L,0); /* clear the stack for returning */ - lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); - tmpbuf = lua_tolstring(L, -1, &bufsize); - lua_pop(L,1); /* pop the buffer off the stack, should be safe since it - it is still in the registry */ - if(tmpbuf==NULL){ - fatal("%s: In: %s:%i The buffer is not a string?! - please report this to nmap-dev@insecure.org.", SCRIPT_ENGINE, __FILE__, __LINE__); - } - /*first push the remains of the buffer */ - lua_pushlstring(L,tmpbuf+endpos,(bufsize-endpos)); - tmpidx = luaL_ref(L,LUA_REGISTRYINDEX); - lua_pushboolean(L,true); - if(keeppattern){ - lua_pushlstring(L,tmpbuf,endpos); - }else{ - lua_pushlstring(L,tmpbuf,startpos-1); - } - luaL_unref(L,LUA_REGISTRYINDEX,udata->bufidx); - udata->bufidx=tmpidx; - //l_dumpStack(L); - return NSOCK_WRAPPER_BUFFER_OK; - } - assert(0); - return 1;//unreachable +int l_nsock_check_buf(lua_State * L) +{ + l_nsock_udata *udata; + + size_t startpos, endpos, bufsize; + + const char *tmpbuf; + + int tmpidx; + + int keeppattern; + + /* should we return the string including the pattern or without it */ + keeppattern = lua_toboolean(L, -1); + lua_pop(L, 1); + udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); + if (lua_isfunction(L, 2)) + { + lua_pushvalue(L, 2); + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); /* the buffer is the + * only argument to the + * function */ + if (lua_pcall(L, 1, 2, 0) != 0) + { + lua_pushboolean(L, false); + lua_pushfstring(L, "Error inside splitting-function: %s\n", + lua_tostring(L, -1)); + return NSOCK_WRAPPER_BUFFER_OK; + // luaL_error(L,"Error inside splitting-function, given as argument to + // nsockobj:receive_buf: %s\n", lua_tostring(L,-1)); + } + } else if (lua_isstring(L, 2)) + { + lua_getglobal(L, "string"); + lua_getfield(L, -1, "find"); + lua_remove(L, -2); /* drop the string-table, since we don't + * need it! */ + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); + lua_pushvalue(L, 2); /* the pattern we are searching for */ + if (lua_pcall(L, 2, 2, 0) != 0) + { + lua_pushboolean(L, false); + lua_pushstring(L, "Error in string.find (nsockobj:receive_buf)!"); + return NSOCK_WRAPPER_BUFFER_OK; + } + } else + { + lua_pushboolean(L, false); + lua_pushstring(L, "Expected either a function or a string!"); + return NSOCK_WRAPPER_BUFFER_OK; + // luaL_argerror(L,2,"expected either a function or a string!"); + } + /* the stack contains on top the indices where we want to seperate */ + if (lua_isnil(L, -1)) + { /* not found anything try to read more + * data */ + lua_pop(L, 2); + nsock_read(nsp, udata->nsiod, l_nsock_receive_buf_handler, udata->timeout, + &udata->yield); + lua_pushboolean(L, keeppattern); + return NSOCK_WRAPPER_BUFFER_MOREREAD; + } else + { + startpos = (size_t) lua_tointeger(L, -2); + endpos = (size_t) lua_tointeger(L, -1); + lua_settop(L, 0); /* clear the stack for returning */ + if (startpos > endpos) + { + lua_pushboolean(L, false); + lua_pushstring(L, "Delimiter has negative size!"); + return NSOCK_WRAPPER_BUFFER_OK; + } else if (startpos == endpos) + { + /* if the delimter has a size of zero we keep it, since otherwise + * retured string would be trucated */ + keeppattern = 1; + } + lua_settop(L, 0); /* clear the stack for returning */ + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); + tmpbuf = lua_tolstring(L, -1, &bufsize); + lua_pop(L, 1); /* pop the buffer off the stack, should + * be safe since it it is still in the + * registry */ + if (tmpbuf == NULL) + { + fatal + ("%s: In: %s:%i The buffer is not a string?! - please report this to nmap-dev@insecure.org.", + SCRIPT_ENGINE, __FILE__, __LINE__); + } + /* first push the remains of the buffer */ + lua_pushlstring(L, tmpbuf + endpos, (bufsize - endpos)); + tmpidx = luaL_ref(L, LUA_REGISTRYINDEX); + lua_pushboolean(L, true); + if (keeppattern) + { + lua_pushlstring(L, tmpbuf, endpos); + } else + { + lua_pushlstring(L, tmpbuf, startpos - 1); + } + luaL_unref(L, LUA_REGISTRYINDEX, udata->bufidx); + udata->bufidx = tmpidx; + // l_dumpStack(L); + return NSOCK_WRAPPER_BUFFER_OK; + } + assert(0); + return 1; // unreachable } -void l_nsock_clear_buf(lua_State *L, l_nsock_udata* udata){ - luaL_unref (L, LUA_REGISTRYINDEX, udata->bufidx); - udata->bufidx=LUA_NOREF; - udata->bufused=0; +void l_nsock_clear_buf(lua_State * L, l_nsock_udata * udata) +{ + luaL_unref(L, LUA_REGISTRYINDEX, udata->bufidx); + udata->bufidx = LUA_NOREF; + udata->bufused = 0; } -static void l_nsock_sleep_handler(nsock_pool nsp, nsock_event nse, void *udata) { - lua_State *L = (lua_State*) udata; +static void l_nsock_sleep_handler(nsock_pool nsp, nsock_event nse, void *udata) +{ + lua_State *L = (lua_State *) udata; + assert(nse_status(nse) == NSE_STATUS_SUCCESS); nse_restore(L, 0); } -int l_nsock_sleep(lua_State *L) { +int l_nsock_sleep(lua_State * L) +{ double secs = luaL_checknumber(L, 1); + int msecs; if (secs < 0) @@ -1018,7 +1192,7 @@ int l_nsock_sleep(lua_State *L) { return lua_yield(L, 0); } -/****************** NCAP_SOCKET ***********************************************/ +/****************** NCAP_SOCKET ***********************************************/ #ifdef WIN32 /* From tcpip.cc. Gets pcap device name from dnet name. */ bool DnetName2PcapName(const char *dnetdev, char *pcapdev, int pcapdevlen); @@ -1026,237 +1200,284 @@ bool DnetName2PcapName(const char *dnetdev, char *pcapdev, int pcapdevlen); /* fuckin' C++ maps stuff */ /* here we store ncap_sockets */ -std::map ncap_socket_map; +std::map < std::string, struct ncap_socket *>ncap_socket_map; /* receive sthing from socket_map */ -struct ncap_socket *ncap_socket_map_get(char *key){ - std::string skey = key; - return ncap_socket_map[skey]; +struct ncap_socket *ncap_socket_map_get(char *key) +{ + std::string skey = key; + return ncap_socket_map[skey]; } /* set sthing on socket_map */ -void ncap_socket_map_set(char *key, struct ncap_socket *ns){ - std::string skey = key; - ncap_socket_map[skey] = ns; - return; +void ncap_socket_map_set(char *key, struct ncap_socket *ns) +{ + std::string skey = key; + ncap_socket_map[skey] = ns; + return; } /* receive sthing from socket_map */ -void ncap_socket_map_del(char *key){ - std::string skey = key; - ncap_socket_map.erase(skey); - return; +void ncap_socket_map_del(char *key) +{ + std::string skey = key; + ncap_socket_map.erase(skey); + return; } - /* (static) Dnet-like device name to Pcap-like name */ -char *dnet_to_pcap_device_name(const char *device){ - static char pcapdev[128]; - if( strcmp(device, "any") == 0 ) - return strncpy(pcapdev, "any", sizeof(pcapdev)); - - #ifdef WIN32 - /* Nmap normally uses device names obtained through dnet for interfaces, - * but Pcap has its own naming system. So the conversion is done here */ - if (!DnetName2PcapName(device, pcapdev, sizeof(pcapdev))) { - /* Oh crap -- couldn't find the corresponding dev apparently. - * Let's just go with what we have then ... */ - strncpy(pcapdev, device, sizeof(pcapdev)); - } - #else - strncpy(pcapdev, device, sizeof(pcapdev)); - #endif - return pcapdev; +char *dnet_to_pcap_device_name(const char *device) +{ + static char pcapdev[128]; + + if (strcmp(device, "any") == 0) + return strncpy(pcapdev, "any", sizeof(pcapdev)); + +#ifdef WIN32 + /* Nmap normally uses device names obtained through dnet for interfaces, but + * Pcap has its own naming system. So the conversion is done here */ + if (!DnetName2PcapName(device, pcapdev, sizeof(pcapdev))) + { + /* Oh crap -- couldn't find the corresponding dev apparently. Let's just + * go with what we have then ... */ + strncpy(pcapdev, device, sizeof(pcapdev)); + } +#else + strncpy(pcapdev, device, sizeof(pcapdev)); +#endif + return pcapdev; } /* (LUA) Open nsock-pcap socket. - * 1) device - dnet-style network interface name, or "any" - * 2) snaplen - maximum number of bytes to be captured for packet - * 3) promisc - should we set network car in promiscuous mode (0/1) - * 4) callback- callback function, that will create hash string from packet - * 5) bpf - berkeley packet filter, see tcpdump(8) - * */ -static int l_nsock_ncap_open(lua_State *L){ - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - const char* device = luaL_checkstring(L, 2); - int snaplen = luaL_checkint(L, 3); - int promisc = luaL_checkint(L, 4); - luaL_checktype(L, 5, LUA_TFUNCTION); /* callback function that creates hash */ - const char* bpf = luaL_checkstring(L, 6); + * 1) device - dnet-style network interface name, or "any" + * 2) snaplen - maximum number of bytes to be captured for packet + * 3) promisc - should we set network car in promiscuous mode (0/1) + * 4) callback- callback function, that will create hash string from packet + * 5) bpf - berkeley packet filter, see tcpdump(8) + * */ +static int l_nsock_ncap_open(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - if(udata->nsiod || udata->ncap_request || udata->ncap_socket) { - luaL_argerror(L, 1, "Trying to open nsock-pcap, but this connection is already opened"); - return 0; - } - char *pcapdev = dnet_to_pcap_device_name(device); - if(!strlen(device) || !strlen(pcapdev)) { - luaL_argerror(L, 1, "Trying to open nsock-pcap, but you're passing empty or wrong device name."); - return 0; - } + const char *device = luaL_checkstring(L, 2); - lua_pop(L, 1); // pop bpf - /* take func from top of stack and store it in the Registry */ - int hash_func_ref = luaL_ref(L, LUA_REGISTRYINDEX); - /* push function on the registry-stack */ - lua_rawgeti(L, LUA_REGISTRYINDEX, hash_func_ref); - - struct ncap_socket *ns; - - /* create key */ - char key[8192]; - Snprintf(key, sizeof(key), "%s|%i|%i|%u|%s", - pcapdev, - snaplen, promisc, - (unsigned int)strlen(bpf), - bpf); - ns = ncap_socket_map_get(key); - if(ns == NULL){ - ns = (struct ncap_socket*)safe_zalloc(sizeof(struct ncap_socket)); - ns->nsiod = nsi_new(nsp, ns); - ns->key = strdup(key); - /* error messages are passed here */ - char *emsg = nsock_pcap_open(nsp, ns->nsiod, pcapdev, snaplen, promisc, bpf); - if(emsg){ - luaL_argerror(L, 1, emsg); - return 0; - } - ncap_socket_map_set(key, ns); - } - ns->references++; - udata->nsiod = ns->nsiod; - udata->ncap_socket = ns; - udata->ncap_cback_ref = hash_func_ref; - return 0; + int snaplen = luaL_checkint(L, 3); + + int promisc = luaL_checkint(L, 4); + + luaL_checktype(L, 5, LUA_TFUNCTION); /* callback function that creates hash */ + const char *bpf = luaL_checkstring(L, 6); + + if (udata->nsiod || udata->ncap_request || udata->ncap_socket) + { + luaL_argerror(L, 1, + "Trying to open nsock-pcap, but this connection is already opened"); + return 0; + } + char *pcapdev = dnet_to_pcap_device_name(device); + + if (!strlen(device) || !strlen(pcapdev)) + { + luaL_argerror(L, 1, + "Trying to open nsock-pcap, but you're passing empty or wrong device name."); + return 0; + } + + lua_pop(L, 1); // pop bpf + /* take func from top of stack and store it in the Registry */ + int hash_func_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + /* push function on the registry-stack */ + lua_rawgeti(L, LUA_REGISTRYINDEX, hash_func_ref); + + struct ncap_socket *ns; + + /* create key */ + char key[8192]; + + Snprintf(key, sizeof(key), "%s|%i|%i|%u|%s", + pcapdev, snaplen, promisc, (unsigned int) strlen(bpf), bpf); + ns = ncap_socket_map_get(key); + if (ns == NULL) + { + ns = (struct ncap_socket *) safe_zalloc(sizeof(struct ncap_socket)); + ns->nsiod = nsi_new(nsp, ns); + ns->key = strdup(key); + /* error messages are passed here */ + char *emsg = + nsock_pcap_open(nsp, ns->nsiod, pcapdev, snaplen, promisc, bpf); + if (emsg) + { + luaL_argerror(L, 1, emsg); + return 0; + } + ncap_socket_map_set(key, ns); + } + ns->references++; + udata->nsiod = ns->nsiod; + udata->ncap_socket = ns; + udata->ncap_cback_ref = hash_func_ref; + return 0; } /* (LUA) Close nsock-pcap socket. - * */ -static int l_nsock_ncap_close(lua_State *L){ - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - struct ncap_socket *ns = udata->ncap_socket; + * */ +static int l_nsock_ncap_close(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - if(!udata->nsiod || !udata->ncap_socket) { - luaL_argerror(L, 1, "Trying to close nsock-pcap, but it was never opened."); - return 0; - } - if(udata->ncap_request) { - luaL_argerror(L, 1, "Trying to close nsock-pcap, but it has active event."); - return 0; - } + struct ncap_socket *ns = udata->ncap_socket; - assert(ns->references > 0); + if (!udata->nsiod || !udata->ncap_socket) + { + luaL_argerror(L, 1, "Trying to close nsock-pcap, but it was never opened."); + return 0; + } + if (udata->ncap_request) + { + luaL_argerror(L, 1, "Trying to close nsock-pcap, but it has active event."); + return 0; + } - ns->references--; - if(ns->references == 0){ - ncap_socket_map_del(ns->key); - if(ns->key) free(ns->key); - nsi_delete(ns->nsiod, NSOCK_PENDING_NOTIFY); - free(ns); - } + assert(ns->references > 0); - udata->nsiod = NULL; - udata->ncap_socket = NULL; - lua_unref(L, udata->ncap_cback_ref); - udata->ncap_cback_ref = 0; + ns->references--; + if (ns->references == 0) + { + ncap_socket_map_del(ns->key); + if (ns->key) + free(ns->key); + nsi_delete(ns->nsiod, NSOCK_PENDING_NOTIFY); + free(ns); + } - lua_pushboolean(L, true); - return 1; + udata->nsiod = NULL; + udata->ncap_socket = NULL; + lua_unref(L, udata->ncap_cback_ref); + udata->ncap_cback_ref = 0; + + lua_pushboolean(L, true); + return 1; } - /* (static) binary string to hex zero-terminated string */ -char *hex(char *str, unsigned int strsz){ - static char x[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; - static char buf[2048]; - unsigned int i; - unsigned char *s; - for(i=0, s=(unsigned char*)str; isuspended_lua_threads */ -std::multimap ncap_request_map; -typedef std::multimap::iterator ncap_request_map_iterator; -typedef std::pair ncap_request_map_ii; +std::multimap < std::string, struct ncap_request *>ncap_request_map; + +typedef std::multimap < std::string, + struct ncap_request *>::iterator ncap_request_map_iterator; +typedef std::pair < ncap_request_map_iterator, + ncap_request_map_iterator > ncap_request_map_ii; /* del from multimap */ -void ncap_request_map_del(struct ncap_request *nr){ - ncap_request_map_iterator i; - ncap_request_map_ii ii; - std::string s = nr->key; - ii = ncap_request_map.equal_range(s); - - for(i=ii.first ; i!=ii.second ;i++){ - if(i->second == nr){ - i->second = NULL; - ncap_request_map.erase(i); - return; - } - } - assert(0); +void ncap_request_map_del(struct ncap_request *nr) +{ + ncap_request_map_iterator i; + + ncap_request_map_ii ii; + + std::string s = nr->key; + ii = ncap_request_map.equal_range(s); + + for (i = ii.first; i != ii.second; i++) + { + if (i->second == nr) + { + i->second = NULL; + ncap_request_map.erase(i); + return; + } + } + assert(0); } - /* add to multimap */ -void ncap_request_map_add(char *key, struct ncap_request *nr){ - std::string skey = key; - ncap_request_map.insert(std::pair(skey, nr)); - return; +void ncap_request_map_add(char *key, struct ncap_request *nr) +{ + std::string skey = key; + ncap_request_map.insert(std::pair < std::string, struct ncap_request *>(skey, + nr)); + return; } /* (LUA) Register event that will wait for one packet matching hash. * It's non-blocking method of capturing packets. - * 1) hash - hash for packet that should be matched. or empty string if you - * want to receive first packet + * 1) hash - hash for packet that should be matched. or empty string if you + * want to receive first packet * */ -static int l_nsock_ncap_register(lua_State *L){ - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - size_t testdatasz; - const char* testdata = luaL_checklstring(L, 2, &testdatasz); +static int l_nsock_ncap_register(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - struct timeval now = *nsock_gettimeofday(); - - if(!udata->nsiod || !udata->ncap_socket) { - luaL_argerror(L, 1, "You can't register to nsock-pcap if it wasn't opened."); - return 0; - } - if(udata->ncap_request){ - luaL_argerror(L, 1, "You are already registered to this socket."); - return 0; - } - - struct ncap_request *nr = - (struct ncap_request*)safe_zalloc(sizeof(struct ncap_request)); - - udata->ncap_request = nr; - - TIMEVAL_MSEC_ADD(nr->end_time, now, udata->timeout); - nr->key = strdup(hex((char*)testdata, testdatasz)); - nr->yield = &udata->yield; - udata->yield.thread = L; - udata->yield.udata = udata; - nr->ncap_cback_ref = udata->ncap_cback_ref; - /* always create new event. */ - nr->nseid = nsock_pcap_read_packet(nsp, - udata->nsiod, - l_nsock_pcap_receive_handler, - udata->timeout, nr); - - ncap_request_map_add(nr->key, nr); + size_t testdatasz; - /* that's it. return to lua */ - return 0; + const char *testdata = luaL_checklstring(L, 2, &testdatasz); + + struct timeval now = *nsock_gettimeofday(); + + if (!udata->nsiod || !udata->ncap_socket) + { + luaL_argerror(L, 1, + "You can't register to nsock-pcap if it wasn't opened."); + return 0; + } + if (udata->ncap_request) + { + luaL_argerror(L, 1, "You are already registered to this socket."); + return 0; + } + + struct ncap_request *nr = + (struct ncap_request *) safe_zalloc(sizeof(struct ncap_request)); + + udata->ncap_request = nr; + + TIMEVAL_MSEC_ADD(nr->end_time, now, udata->timeout); + nr->key = strdup(hex((char *) testdata, testdatasz)); + nr->yield = &udata->yield; + udata->yield.thread = L; + udata->yield.udata = udata; + nr->ncap_cback_ref = udata->ncap_cback_ref; + /* always create new event. */ + nr->nseid = nsock_pcap_read_packet(nsp, + udata->nsiod, l_nsock_pcap_receive_handler, udata->timeout, nr); + + ncap_request_map_add(nr->key, nr); + + /* that's it. return to lua */ + return 0; } /* (LUA) After "register" use this function to block, and wait for packet. @@ -1264,359 +1485,421 @@ static int l_nsock_ncap_register(lua_State *L){ * * return values: status(true/false), capture_len/error_msg, layer2data, layer3data * */ -int l_nsock_pcap_receive(lua_State *L){ - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); - if(!udata->nsiod || !udata->ncap_socket) { - luaL_argerror(L, 1, "You can't receive to nsock-pcap if it wasn't opened."); - return 0; - } - if(!udata->ncap_request){ - luaL_argerror(L, 1, "You can't it's not registered"); - return 0; - } +int l_nsock_pcap_receive(lua_State * L) +{ + l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); - /* and clear udata->ncap_request, we'll never,ever have access to current - * udata during this request */ - struct ncap_request *nr = udata->ncap_request; - udata->ncap_request = NULL; - udata->yield.thread = L; - udata->yield.udata = udata; - - /* ready to receive data? don't suspend thread*/ - if(nr->received) /*data already received*/ - return ncap_restore_lua(nr); - - /* no data yet? suspend thread */ - nr->suspended = 1; - - return lua_yield(L, 0); + if (!udata->nsiod || !udata->ncap_socket) + { + luaL_argerror(L, 1, "You can't receive to nsock-pcap if it wasn't opened."); + return 0; + } + if (!udata->ncap_request) + { + luaL_argerror(L, 1, "You can't it's not registered"); + return 0; + } + + /* and clear udata->ncap_request, we'll never,ever have access to current + * udata during this request */ + struct ncap_request *nr = udata->ncap_request; + + udata->ncap_request = NULL; + udata->yield.thread = L; + udata->yield.udata = udata; + + /* ready to receive data? don't suspend thread */ + if (nr->received) /* data already received */ + return ncap_restore_lua(nr); + + /* no data yet? suspend thread */ + nr->suspended = 1; + + return lua_yield(L, 0); } /* (free) excute callback function from lua script */ -char* ncap_request_do_callback(nsock_event nse, lua_State *L, int ncap_cback_ref){ - const unsigned char *l2_data, *l3_data; - size_t l2_len, l3_len, packet_len; - nse_readpcap(nse, &l2_data, &l2_len, &l3_data, &l3_len, &packet_len, NULL); - - lua_rawgeti(L, LUA_REGISTRYINDEX, ncap_cback_ref); - lua_pushnumber(L, packet_len); - lua_pushlstring(L, (char*)l2_data, l2_len); - lua_pushlstring(L, (char*)l3_data, l3_len); +char *ncap_request_do_callback(nsock_event nse, lua_State * L, + int ncap_cback_ref) +{ + const unsigned char *l2_data, *l3_data; - lua_call(L, 3, 1); - - /* get string from top of the stack*/ - size_t testdatasz; - const char* testdata = lua_tolstring(L, -1, &testdatasz); - - char *key = strdup(hex((char*)testdata, testdatasz)); - return key; + size_t l2_len, l3_len, packet_len; + + nse_readpcap(nse, &l2_data, &l2_len, &l3_data, &l3_len, &packet_len, NULL); + + lua_rawgeti(L, LUA_REGISTRYINDEX, ncap_cback_ref); + lua_pushnumber(L, packet_len); + lua_pushlstring(L, (char *) l2_data, l2_len); + lua_pushlstring(L, (char *) l3_data, l3_len); + + lua_call(L, 3, 1); + + /* get string from top of the stack */ + size_t testdatasz; + + const char *testdata = lua_tolstring(L, -1, &testdatasz); + + char *key = strdup(hex((char *) testdata, testdatasz)); + + return key; } - - /* callback from nsock */ -void l_nsock_pcap_receive_handler(nsock_pool nsp, nsock_event nse, void *userdata){ - int this_event_restored=0; - struct ncap_request *nr = (struct ncap_request *) userdata; +void l_nsock_pcap_receive_handler(nsock_pool nsp, nsock_event nse, + void *userdata) +{ + int this_event_restored = 0; - - switch(nse_status(nse)) { - case NSE_STATUS_SUCCESS:{ - char *key = ncap_request_do_callback(nse, nr->yield->thread, nr->ncap_cback_ref); - - /* processes threads that receive every packet */ - this_event_restored += ncap_request_set_results(nse, ""); - - /* process everything that matches test */ - this_event_restored += ncap_request_set_results(nse, key); - free(key); + struct ncap_request *nr = (struct ncap_request *) userdata; + switch (nse_status(nse)) + { + case NSE_STATUS_SUCCESS: + { + char *key = + ncap_request_do_callback(nse, nr->yield->thread, nr->ncap_cback_ref); - if(!this_event_restored){ - /* okay, we received event but it wasn't handled by the process - * that requested this event. We must query for new event with - * smaller timeout */ - struct timeval now = *nsock_gettimeofday(); - - /*event was successfull so I assert it occured before pr->end_time*/ - int timeout = TIMEVAL_MSEC_SUBTRACT(nr->end_time, now); - if(timeout < 0) /* funny to receive event that should be timeouted in the past. But on windows it can happen*/ - timeout = 0; - nr->nseid = nsock_pcap_read_packet(nsp, - nse_iod(nse), - l_nsock_pcap_receive_handler, - timeout, nr); - /* no need to cancel or delete current nse :) */ - } - return; - } - default: - /* event timeouted */ - ncap_request_map_del(nr); /* delete from map */ - ncap_request_set_result(nse, nr); - if(nr->suspended) /* restore thread */ - ncap_restore_lua(nr); - return; - } + /* processes threads that receive every packet */ + this_event_restored += ncap_request_set_results(nse, ""); + + /* process everything that matches test */ + this_event_restored += ncap_request_set_results(nse, key); + free(key); + + if (!this_event_restored) + { + /* okay, we received event but it wasn't handled by the process that + * requested this event. We must query for new event with smaller + * timeout */ + struct timeval now = *nsock_gettimeofday(); + + /* event was successfull so I assert it occured before pr->end_time */ + int timeout = TIMEVAL_MSEC_SUBTRACT(nr->end_time, now); + + if (timeout < 0) /* funny to receive event that should be + * timeouted in the past. But on windows + * it can happen */ + timeout = 0; + nr->nseid = nsock_pcap_read_packet(nsp, + nse_iod(nse), l_nsock_pcap_receive_handler, timeout, nr); + /* no need to cancel or delete current nse :) */ + } + return; + } + default: + /* event timeouted */ + ncap_request_map_del(nr); /* delete from map */ + ncap_request_set_result(nse, nr); + if (nr->suspended) /* restore thread */ + ncap_restore_lua(nr); + return; + } } - /* get data from nsock_event, and set result on ncap_requests which mach key */ -int ncap_request_set_results(nsock_event nse, const char *key) { - int this_event_restored = 0; - - std::string skey = key; - - ncap_request_map_iterator i; - ncap_request_map_ii ii; - - ii = ncap_request_map.equal_range(skey); - for(i = ii.first; i != ii.second; i++) { - /* tests are successfull, so just restore process */ - ncap_request *nr = i->second; - if(nr->nseid == nse_id(nse)) - this_event_restored = 1; - - ncap_request_set_result(nse, nr); - if(nr->suspended) - ncap_restore_lua(nr); - } - ncap_request_map.erase(ii.first, ii.second); - - return this_event_restored; +int ncap_request_set_results(nsock_event nse, const char *key) +{ + int this_event_restored = 0; + + std::string skey = key; + + ncap_request_map_iterator i; + + ncap_request_map_ii ii; + + ii = ncap_request_map.equal_range(skey); + for (i = ii.first; i != ii.second; i++) + { + /* tests are successfull, so just restore process */ + ncap_request *nr = i->second; + + if (nr->nseid == nse_id(nse)) + this_event_restored = 1; + + ncap_request_set_result(nse, nr); + if (nr->suspended) + ncap_restore_lua(nr); + } + ncap_request_map.erase(ii.first, ii.second); + + return this_event_restored; } /* get data from nsock_event, and set result ncap_request */ -void ncap_request_set_result(nsock_event nse, struct ncap_request *nr) { - enum nse_status status = nse_status(nse); - nr->received = true; +void ncap_request_set_result(nsock_event nse, struct ncap_request *nr) +{ + enum nse_status status = nse_status(nse); - switch (status) { - case NSE_STATUS_SUCCESS:{ - nr->r_success = true; - - const unsigned char *l2_data, *l3_data; - size_t l2_len, l3_len, packet_len; - nse_readpcap(nse, &l2_data, &l2_len, &l3_data, &l3_len, - &packet_len, NULL); - char *packet = (char*) safe_malloc(l2_len + l3_len); - nr->r_layer2 = (unsigned char*)memcpy(&packet[0], l2_data, l2_len); - nr->r_layer3 = (unsigned char*)memcpy(&packet[l2_len], l3_data, l3_len); - nr->r_layer2_len = l2_len; - nr->r_layer3_len = l3_len; - nr->packetsz = packet_len; - break;} - case NSE_STATUS_ERROR: - case NSE_STATUS_TIMEOUT: - case NSE_STATUS_CANCELLED: - case NSE_STATUS_KILL: - case NSE_STATUS_EOF: - nr->r_success = false; - nr->r_status = strdup( nse_status2str(status) ); - break; - case NSE_STATUS_NONE: - default: - fatal("%s: In: %s:%i This should never happen.", - NSOCK_WRAPPER, __FILE__, __LINE__); - } + nr->received = true; - if(nr->nseid != nse_id(nse)){ /* different event, cancel*/ - nsock_event_cancel(nsp, nr->nseid, 0); /* Don't send CANCELED event, just cancel */ - nr->nseid = 0; - }else{ /* this event -> do nothing */ - } - - return; + switch (status) + { + case NSE_STATUS_SUCCESS: + { + nr->r_success = true; + + const unsigned char *l2_data, *l3_data; + + size_t l2_len, l3_len, packet_len; + + nse_readpcap(nse, &l2_data, &l2_len, &l3_data, &l3_len, + &packet_len, NULL); + char *packet = (char *) safe_malloc(l2_len + l3_len); + + nr->r_layer2 = (unsigned char *) memcpy(&packet[0], l2_data, l2_len); + nr->r_layer3 = (unsigned char *) memcpy(&packet[l2_len], l3_data, l3_len); + nr->r_layer2_len = l2_len; + nr->r_layer3_len = l3_len; + nr->packetsz = packet_len; + break; + } + case NSE_STATUS_ERROR: + case NSE_STATUS_TIMEOUT: + case NSE_STATUS_CANCELLED: + case NSE_STATUS_KILL: + case NSE_STATUS_EOF: + nr->r_success = false; + nr->r_status = strdup(nse_status2str(status)); + break; + case NSE_STATUS_NONE: + default: + fatal("%s: In: %s:%i This should never happen.", + NSOCK_WRAPPER, __FILE__, __LINE__); + } + + if (nr->nseid != nse_id(nse)) + { /* different event, cancel */ + nsock_event_cancel(nsp, nr->nseid, 0); /* Don't send CANCELED event, just + * cancel */ + nr->nseid = 0; + } else + { /* this event -> do nothing */ + } + + return; } - /* if lua thread was suspended, restore it. If it wasn't, just return results * (push them on the stack and return) */ -int ncap_restore_lua(ncap_request *nr){ - lua_State *L = nr->yield->thread; +int ncap_restore_lua(ncap_request * nr) +{ + lua_State *L = nr->yield->thread; - if(nr->r_success){ - lua_pushboolean(L, true); - lua_pushnumber(L, nr->packetsz); - lua_pushlstring(L, (char*)nr->r_layer2, nr->r_layer2_len); - lua_pushlstring(L, (char*)nr->r_layer3, nr->r_layer3_len); - }else{ - lua_pushnil(L); - lua_pushstring(L, nr->r_status); - lua_pushnil(L); - lua_pushnil(L); - } - bool suspended = nr->suspended; - //nr->L = NULL; // FIXME ?? - nr->ncap_cback_ref = 0; /* this ref is freed in different place (on udata->ncap_cback_ref) */ - if(nr->key) free(nr->key); - if(nr->r_status) free(nr->r_status); - if(nr->r_layer2) free(nr->r_layer2); - /* dont' free r_layer3, it's in the same block as r_layer2*/ + if (nr->r_success) + { + lua_pushboolean(L, true); + lua_pushnumber(L, nr->packetsz); + lua_pushlstring(L, (char *) nr->r_layer2, nr->r_layer2_len); + lua_pushlstring(L, (char *) nr->r_layer3, nr->r_layer3_len); + } else + { + lua_pushnil(L); + lua_pushstring(L, nr->r_status); + lua_pushnil(L); + lua_pushnil(L); + } + bool suspended = nr->suspended; - free(nr); - - if(suspended) /* lua process is suspended */ - nse_restore(L, 4); - else /* not suspended, just pass output */ - return 4; - return 0; + // nr->L = NULL; // FIXME ?? + nr->ncap_cback_ref = 0; /* this ref is freed in different place + * (on udata->ncap_cback_ref) */ + if (nr->key) + free(nr->key); + if (nr->r_status) + free(nr->r_status); + if (nr->r_layer2) + free(nr->r_layer2); + /* dont' free r_layer3, it's in the same block as r_layer2 */ + + free(nr); + + if (suspended) /* lua process is suspended */ + nse_restore(L, 4); + else /* not suspended, just pass output */ + return 4; + return 0; } +/****************** DNET ******************************************************/ +static int l_dnet_open_ethernet(lua_State * L); +static int l_dnet_close_ethernet(lua_State * L); +static int l_dnet_send_ethernet(lua_State * L); -/****************** DNET ******************************************************/ -static int l_dnet_open_ethernet(lua_State *L); -static int l_dnet_close_ethernet(lua_State *L); -static int l_dnet_send_ethernet(lua_State *L); - -static luaL_reg l_dnet [] = { - {"ethernet_open", l_dnet_open_ethernet}, - {"ethernet_close", l_dnet_close_ethernet}, - {"ethernet_send", l_dnet_send_ethernet}, - {NULL, NULL} +static luaL_reg l_dnet[] = { + {"ethernet_open", l_dnet_open_ethernet}, + {"ethernet_close", l_dnet_close_ethernet}, + {"ethernet_send", l_dnet_send_ethernet}, + {NULL, NULL} }; -int l_dnet_open(lua_State *L) { - luaL_newmetatable(L, "dnet"); - lua_createtable(L, 0, 5); - luaL_register(L, NULL, l_dnet); - lua_setfield(L, -2, "__index"); - lua_pushliteral(L, ""); - lua_setfield(L, -2, "__metatable"); // protect metatable - lua_pop(L, 1); - return NSOCK_WRAPPER_SUCCESS; +int l_dnet_open(lua_State * L) +{ + luaL_newmetatable(L, "dnet"); + lua_createtable(L, 0, 5); + luaL_register(L, NULL, l_dnet); + lua_setfield(L, -2, "__index"); + lua_pushliteral(L, ""); + lua_setfield(L, -2, "__metatable"); // protect metatable + lua_pop(L, 1); + return NSOCK_WRAPPER_SUCCESS; } -struct l_dnet_udata { - char *interface; - eth_t *eth; +struct l_dnet_udata +{ + char *interface; + eth_t *eth; }; -int l_dnet_new(lua_State *L) { - struct l_dnet_udata* udata; - udata = (struct l_dnet_udata*) lua_newuserdata(L, sizeof(struct l_dnet_udata)); - luaL_getmetatable(L, "dnet"); - lua_setmetatable(L, -2); - udata->interface= NULL; - udata->eth = NULL; +int l_dnet_new(lua_State * L) +{ + struct l_dnet_udata *udata; - return 1; + udata = + (struct l_dnet_udata *) lua_newuserdata(L, sizeof(struct l_dnet_udata)); + luaL_getmetatable(L, "dnet"); + lua_setmetatable(L, -2); + udata->interface = NULL; + udata->eth = NULL; + + return 1; } -int l_dnet_get_interface_link(lua_State *L) { - const char* interface_name = luaL_checkstring(L, 1); - - struct interface_info *ii = getInterfaceByName((char*)interface_name); - if(!ii){ - lua_pushnil(L); - return 1; - } - const char *s= NULL; - switch(ii->device_type){ - case devt_ethernet: - s = "ethernet"; - break; - case devt_loopback: - s = "loopback"; - break; - case devt_p2p: - s = "p2p"; - break; - case devt_other: - default: - s = NULL; - break; - } - if(s) - lua_pushstring(L, s); - else - lua_pushnil(L); - - return 1; +int l_dnet_get_interface_link(lua_State * L) +{ + const char *interface_name = luaL_checkstring(L, 1); + + struct interface_info *ii = getInterfaceByName((char *) interface_name); + + if (!ii) + { + lua_pushnil(L); + return 1; + } + const char *s = NULL; + + switch (ii->device_type) + { + case devt_ethernet: + s = "ethernet"; + break; + case devt_loopback: + s = "loopback"; + break; + case devt_p2p: + s = "p2p"; + break; + case devt_other: + default: + s = NULL; + break; + } + if (s) + lua_pushstring(L, s); + else + lua_pushnil(L); + + return 1; } -typedef struct{ - int references; - eth_t *eth; +typedef struct +{ + int references; + eth_t *eth; } dnet_eth_map; +std::map < std::string, dnet_eth_map * >dnet_eth_cache; -std::map dnet_eth_cache; +eth_t *ldnet_eth_open_cached(const char *device) +{ + assert(device && *device); -eth_t *ldnet_eth_open_cached(const char *device) { - assert(device && *device); - - std::string key = device; - dnet_eth_map *dem = dnet_eth_cache[key]; - if(dem != NULL){ - dem->references++; - return dem->eth; - } - - dem = (dnet_eth_map *)safe_zalloc(sizeof(dnet_eth_map)); - dem->eth = eth_open(device); - if(!dem->eth) - fatal("Unable to open dnet on ethernet interface %s",device); - dem->references = 1; - dnet_eth_cache[key] = dem; - return dem->eth; + std::string key = device; + dnet_eth_map *dem = dnet_eth_cache[key]; + + if (dem != NULL) + { + dem->references++; + return dem->eth; + } + + dem = (dnet_eth_map *) safe_zalloc(sizeof(dnet_eth_map)); + dem->eth = eth_open(device); + if (!dem->eth) + fatal("Unable to open dnet on ethernet interface %s", device); + dem->references = 1; + dnet_eth_cache[key] = dem; + return dem->eth; } /* See the description for eth_open_cached */ -void ldnet_eth_close_cached(const char *device) { - std::string key = device; - dnet_eth_map *dem = dnet_eth_cache[key]; - assert(dem); - dem->references--; - if(dem->references==0){ - dnet_eth_cache.erase(key); - eth_close(dem->eth); - free(dem); - } - return; +void ldnet_eth_close_cached(const char *device) +{ + std::string key = device; + dnet_eth_map *dem = dnet_eth_cache[key]; + + assert(dem); + dem->references--; + if (dem->references == 0) + { + dnet_eth_cache.erase(key); + eth_close(dem->eth); + free(dem); + } + return; } -static int l_dnet_open_ethernet(lua_State *L){ - l_dnet_udata* udata = (l_dnet_udata*) luaL_checkudata(L, 1, "dnet"); - const char* interface_name = luaL_checkstring(L, 2); +static int l_dnet_open_ethernet(lua_State * L) +{ + l_dnet_udata *udata = (l_dnet_udata *) luaL_checkudata(L, 1, "dnet"); - struct interface_info *ii = getInterfaceByName((char*)interface_name); - if(!ii || ii->device_type!=devt_ethernet){ - luaL_argerror(L, 2, "device is not valid ethernet interface"); - return 0; - } - udata->interface= strdup(interface_name); - udata->eth = ldnet_eth_open_cached(interface_name); - - return 0; + const char *interface_name = luaL_checkstring(L, 2); + + struct interface_info *ii = getInterfaceByName((char *) interface_name); + + if (!ii || ii->device_type != devt_ethernet) + { + luaL_argerror(L, 2, "device is not valid ethernet interface"); + return 0; + } + udata->interface = strdup(interface_name); + udata->eth = ldnet_eth_open_cached(interface_name); + + return 0; } -static int l_dnet_close_ethernet(lua_State *L){ - l_dnet_udata* udata = (l_dnet_udata*) luaL_checkudata(L, 1, "dnet"); - if(!udata->interface || !udata->eth){ - luaL_argerror(L, 1, "dnet is not valid opened ethernet interface"); - return 0; - } +static int l_dnet_close_ethernet(lua_State * L) +{ + l_dnet_udata *udata = (l_dnet_udata *) luaL_checkudata(L, 1, "dnet"); - udata->eth = NULL; - ldnet_eth_close_cached(udata->interface); - free(udata->interface); - udata->interface = NULL; - return 0; + if (!udata->interface || !udata->eth) + { + luaL_argerror(L, 1, "dnet is not valid opened ethernet interface"); + return 0; + } + + udata->eth = NULL; + ldnet_eth_close_cached(udata->interface); + free(udata->interface); + udata->interface = NULL; + return 0; } -static int l_dnet_send_ethernet(lua_State *L){ - l_dnet_udata* udata = (l_dnet_udata*) luaL_checkudata(L, 1, "dnet"); - size_t packetsz = 0; - const char* packet = luaL_checklstring(L, 2, &packetsz); +static int l_dnet_send_ethernet(lua_State * L) +{ + l_dnet_udata *udata = (l_dnet_udata *) luaL_checkudata(L, 1, "dnet"); - if(!udata->interface || !udata->eth){ - luaL_argerror(L, 1, "dnet is not valid opened ethernet interface"); - return 0; - } - eth_send(udata->eth, packet, packetsz); - return 0; + size_t packetsz = 0; + + const char *packet = luaL_checklstring(L, 2, &packetsz); + + if (!udata->interface || !udata->eth) + { + luaL_argerror(L, 1, "dnet is not valid opened ethernet interface"); + return 0; + } + eth_send(udata->eth, packet, packetsz); + return 0; }