Logo Search packages:      
Sourcecode: nmap version File versions  Download package

nse_nsock.cc

#include "nse_nsock.h"
#include "nse_auxiliar.h"
#include "nse_macros.h"
#include "nse_string.h"

#include "nse_debug.h"

#include "nsock.h"
#include "nmap_error.h"
/* #include "osscan.h" */
#include "NmapOps.h"

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#include "utils.h"
#include "tcpip.h"

#if HAVE_OPENSSL
#include <openssl/ssl.h>
#endif

#define SCRIPT_ENGINE               "SCRIPT ENGINE"
#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 DEFAULT_TIMEOUT 30000

extern NmapOps o;

// defined in nse_main.cc but also declared here
// to keep the .h files clean
int process_waiting2running(lua_State* l, int resume_arguments);

static int l_nsock_connect(lua_State* l);
static int l_nsock_connect_queued(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 *lua_state);
void l_nsock_send_handler(nsock_pool nsp, nsock_event nse, void *lua_state);
void l_nsock_receive_handler(nsock_pool nsp, nsock_event nse, void *lua_state);
void l_nsock_receive_buf_handler(nsock_pool nsp, nsock_event nse, void *lua_state);

int l_nsock_check_buf(lua_State* l);

int l_nsock_checkstatus(lua_State* l, nsock_event nse);

void l_nsock_trace(nsock_iod nsiod, char* message, int direction);
char* inet_ntop_both(int af, const void* v_addr, char* ipstring);
unsigned short inet_port_both(int af, const void* v_addr);

static luaL_reg l_nsock [] = {
      {"connect", l_nsock_connect_queued},
      {"send", l_nsock_send},
      {"receive", l_nsock_receive},
      {"receive_lines", l_nsock_receive_lines},
      {"receive_bytes", l_nsock_receive_bytes},
      {"receive_buf", l_nsock_receive_buf},
      {"get_info", l_nsock_get_info},
      {"close", l_nsock_close},
      {"set_timeout", l_nsock_set_timeout},
      {"__gc",l_nsock_gc},
      {"pcap_open",           l_nsock_ncap_open},
      {"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},
      {NULL, NULL}
};

static nsock_pool nsp;

/* There can't be more opened descriptors than max_descriptors_allowed
 * (search below) If there are no more free slots, lua thread is
 * freezed and saved to nsock_connect_queue. It's restored when when a
 * descriptor becomes availble (after nsock_close). */
static int nsock_descriptors_used; /* nsock descriptors currently in use */
std::list<lua_State* > nsock_connect_queue; /* list of freezed threads waiting for desc */

/*
 * 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_request{
      int suspended;          /* is the thread suspended? (lua_yield) */
      lua_State *l;           /* lua_State of current process
                         * or NULL if process isn't suspended */ 
      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;
      /*used for buffered reading */
      int bufidx; /*index inside lua's registry */
      int bufused;
      
      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 l_nsock_open(lua_State* l) {
      auxiliar_newclass(l, "nsock", l_nsock);

        nsp = nsp_new(NULL);
      //nsp_settrace(nsp, o.debugging, o.getStartTime());
      if (o.scriptTrace())
            nsp_settrace(nsp, 5, o.getStartTime());

      return NSOCK_WRAPPER_SUCCESS;
}

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));
      auxiliar_setclass(l, "nsock", -1);
      udata->nsiod = NULL;
      udata->ssl_session = NULL;
      udata->timeout = DEFAULT_TIMEOUT;
      udata->bufidx = LUA_NOREF;
      udata->bufused= 0;
      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_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;
            
      }

      return -1;
}


static int l_nsock_connect_queued(lua_State* l) {

  /* We allow at least 10 even max_parallelism is 1 because a single
     script might open a few sockets at once and we don't want it to
     deadlock when it tries to open the 2nd one. */
      const int max_descriptors_allowed = MAX(o.max_parallelism, 10);
      
      
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);
      
      if(udata->nsiod!=NULL){
            /*should a script try to connect a socket, which is already connected
             * we close the old connection, since it would have no access to it 
             * anyways
             */
            if(o.scriptTrace()){
                  log_write(LOG_STDOUT,"%s: Trying to connect already connected socket - closing!\n",SCRIPT_ENGINE);
            }
            l_nsock_close(l);
            lua_pop(l,1);
      }
      
      
      if(nsock_descriptors_used >= max_descriptors_allowed){
            /* wait for free descriptor */
            nsock_connect_queue.push_back(l);

            /* I must know how many arguments are passed to nsock_connect. 
             * is there a better way? */
            int arguments = 3;
            const char *how = luaL_optstring(l, 4, "");
            if(how != ""){
                  arguments = 4;
                  int port = luaL_optinteger(l, 5, -1);
                  if(port!=-1)
                        arguments = 5;
            }
            
            if(o.scriptTrace())
                  log_write(LOG_STDOUT, "NSOCK_connect_queued: thread queued (%i args) %p\n", arguments, (void *)l); 

            return lua_yield(l, arguments);
      }
      return l_nsock_connect(l);
}

void l_nsock_connect_queued_handler(nsock_pool nsp, nsock_event nse, void *lua_state) {
      lua_State* l = (lua_State*) lua_state;
      /* well, this is really hackish, we can't just do process_waiting2running, because
       * nsock_connect() can do lua_yield().
       * Instead, we first execute nsock_connect, and if it returns lua_yield() (ie. -1)
       * than we don't do process_waiting2running. 
       * So, in summary we can do two lua_yield() on thread (one in l_nsock_connect_queued,
       * second in l_nsock_connect). But it works for me. */
      int r = l_nsock_connect(l);
      if(r != -1)
            process_waiting2running((lua_State*) lua_state, 0);
}


static int l_nsock_connect(lua_State* l) {
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);
      const char* addr = luaL_checkstring(l, 2);
      unsigned short port = (unsigned short) luaL_checkint(l, 3);
      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) {
            error = gai_strerror(error_id);
            lua_pushboolean(l, false);
            lua_pushstring(l, error);
            return 2;
      }

      udata->nsiod = nsi_new(nsp, NULL);
      nsock_descriptors_used++;

      switch (how[0]) {
            case 't':
                  if (strcmp(how, "tcp")) goto error;
                  nsock_connect_tcp(nsp, udata->nsiod, l_nsock_connect_handler, 
                              udata->timeout, l, 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, 
                              l, 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, l, dest->ai_addr, dest->ai_addrlen, port, 
                              udata->ssl_session);
                  break;
#else
                  lua_pushboolean(l, false);
                  lua_pushstring(l, "Sorry, you don't have OpenSSL\n");
                  return 2;
#endif
            default:
                  goto error;
                  break;
      }

      freeaddrinfo(dest);
      return lua_yield(l, 0);

error:
      freeaddrinfo(dest);
      luaL_argerror(l, 4, "invalid connection method");
      return 0;
}

void l_nsock_connect_handler(nsock_pool nsp, nsock_event nse, void *lua_state) {
      lua_State* l = (lua_State*) lua_state;

      if(o.scriptTrace()) {
            l_nsock_trace(nse_iod(nse), "CONNECT", TO);
      }

      if(l_nsock_checkstatus(l, nse) == NSOCK_WRAPPER_SUCCESS) {
            process_waiting2running((lua_State*) lua_state, 1);
      } else {
            process_waiting2running((lua_State*) lua_state, 2);
      }
}

static int l_nsock_send(lua_State* l) {
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);
      const char* string = luaL_checkstring(l, 2);
      size_t string_len = lua_objlen (l, 2);
      char* hexified;
      
      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()) {
            hexified = nse_hexify((const void*)string, string_len);
            l_nsock_trace(udata->nsiod, hexified, TO);
            free(hexified);
      }

      nsock_write(nsp, udata->nsiod, l_nsock_send_handler, udata->timeout, l, string, string_len);
      return lua_yield(l, 0);
}

void l_nsock_send_handler(nsock_pool nsp, nsock_event nse, void *lua_state) {
      lua_State* l = (lua_State*) lua_state;
      
      if(l_nsock_checkstatus(l, nse) == NSOCK_WRAPPER_SUCCESS) {
            process_waiting2running((lua_State*) lua_state, 1);
      } else {
            process_waiting2running((lua_State*) lua_state, 2);
      }
}

static int l_nsock_receive(lua_State* l) {
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);
      l_nsock_clear_buf(l, udata);

      if(udata->nsiod == NULL) {
            lua_pushboolean(l, false);
            lua_pushstring(l, "Trying to receive through a closed socket\n");
            return 2;   
      }

      nsock_read(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, l);

      return lua_yield(l, 0);
}

static int l_nsock_receive_lines(lua_State* l) {
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);
      int nlines = (int) luaL_checknumber(l, 2);

      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;   
      }

      nsock_readlines(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, l, nlines);

      return lua_yield(l, 0);
}

static int l_nsock_receive_bytes(lua_State* l) {
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);
      int nbytes = (int) luaL_checknumber(l, 2);
      
      l_nsock_clear_buf(l, udata);

      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, l, nbytes);

      return lua_yield(l, 0);
}

void l_nsock_receive_handler(nsock_pool nsp, nsock_event nse, void *lua_state) {
      lua_State* l = (lua_State*) lua_state;
      char* rcvd_string;
      int rcvd_len = 0;
      char* hexified;

      if(l_nsock_checkstatus(l, nse) == NSOCK_WRAPPER_SUCCESS) {
            rcvd_string = nse_readbuf(nse, &rcvd_len);

            if(o.scriptTrace()) {
                  hexified = nse_hexify((const void*) rcvd_string, (size_t) rcvd_len);
                  l_nsock_trace(nse_iod(nse), hexified, FROM);
                  free(hexified);
            }

            lua_pushlstring(l, rcvd_string, rcvd_len);
            process_waiting2running((lua_State*) lua_state, 2);
      } else {
            process_waiting2running((lua_State*) lua_state, 2);
      }
}

void l_nsock_trace(nsock_iod nsiod, 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);

      if(!nsi_is_pcap(nsiod)){
            status =  nsi_getlastcommunicationinfo(nsiod, &protocol, &af,
                  &local, &remote, sizeof(sockaddr)); 
            log_write(LOG_STDOUT, "SCRIPT ENGINE: %s %s:%d %s %s:%d | %s\n", 
                  (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, "SCRIPT ENGINE: %s | %s\n", 
                  (direction == TO)? ">" : "<", 
                  message); 
      }
}

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);

            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;
      } 
#endif
      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;      
      }
#ifdef HAVE_IPV6
      else if(af == AF_INET6) {
            port = ((struct sockaddr_in6*) v_addr)->sin6_port;    
      }
#endif
      else {
            port = 0;
      }
      
      return ntohs(port);
}

static int l_nsock_get_info(lua_State* l) {
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);
      int status;

      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);

      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_gc(lua_State* l){
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);
      if(udata->nsiod == NULL) { //socket obviously got closed already - so no finalization needed
            return 0;   
      }else{
      //FIXME - check wheter close returned true!!
            l_nsock_close(l);
      }
      return 0;
}

static int l_nsock_close(lua_State* l) {
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);

      /* 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;
#endif

      nsi_delete(udata->nsiod, NSOCK_PENDING_NOTIFY);
      nsock_descriptors_used--;
      /* handle threads that are waiting for free sockets*/
      if(nsock_connect_queue.size()){
            lua_State *nl = nsock_connect_queue.front();
            nsock_connect_queue.pop_front();
            /* we can't restore lua thread here. instead create timer event with
             * short timeout 0, and restore thread there*/
            nsock_timer_create(nsp, l_nsock_connect_queued_handler, 0, (void*) nl);
      }


      udata->nsiod = NULL;

      lua_pushboolean(l, true);
      return 1;
}

static int l_nsock_set_timeout(lua_State* l) {
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);
      int timeout = (unsigned short) luaL_checkint(l, 2);

      udata->timeout = timeout;

      return 0;
}

/* buffered I/O */
static int l_nsock_receive_buf(lua_State* l) {
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);
      if(lua_gettop(l)==2){ 
            /*we were called with 2 arguments only - push the default third one*/
            lua_pushboolean(l,true);
      }
      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, l);
      }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
                   */
                  return lua_yield(l,3);
            }
            return 2;
      }
      /*yielding with 3 arguments since we need them when the callback arrives */
      return lua_yield(l, 3);
}

void l_nsock_receive_buf_handler(nsock_pool nsp, nsock_event nse, void *lua_state) {
      lua_State* l = (lua_State*) lua_state;
      char* rcvd_string;
      int rcvd_len = 0;
      char* hexified;
      int tmpidx;
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);
      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()) {
                  hexified = nse_hexify((const void*) rcvd_string, (size_t) rcvd_len);
                  l_nsock_trace(nse_iod(nse), hexified, FROM);
                  free(hexified);
            }
            /* 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;
            }
            process_waiting2running((lua_State*) lua_state, 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;
                  process_waiting2running((lua_State*) lua_state, 2);
            }else{ /*buffer should be empty */
                  process_waiting2running((lua_State*) lua_state, 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*) auxiliar_checkclass(l, "nsock", 1);
      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, l);
            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;
}

/****************** NCAP_SOCKET ***********************************************/ 
#ifdef WIN32
/* From tcpip.cc. Gets pcap device name from dnet name. */
bool DnetName2PcapName(const char *dnetdev, char *pcapdev, int pcapdevlen);
#endif

/* fuckin' C++ maps stuff */
/* here we store ncap_sockets */
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];
}

/* 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;
}

/* receive sthing from socket_map */
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;
}

/* (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*) auxiliar_checkclass(l, "nsock", 1);
      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);

      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*) auxiliar_checkclass(l, "nsock", 1);
      struct ncap_socket *ns = udata->ncap_socket;

      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;   
      }

      assert(ns->references > 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);
      }

      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; i<strsz && i<(sizeof(buf)/2-1); i++, s++){
            buf[i*2  ] = x[ *s/16 ];
            buf[i*2+1] = x[ *s%16 ];
      }
      buf[i*2] = '\0';
      return(buf);
}

/****************** NCAP_REQUEST **********************************************/ 

int ncap_restore_lua(ncap_request *nr);
void ncap_request_set_result(nsock_event nse, struct ncap_request *nr);
int ncap_request_set_results(nsock_event nse, char *key);
void l_nsock_pcap_receive_handler(nsock_pool nsp, nsock_event nse, void *userdata);

/* next map, this time it's multimap "key"(from callback)->suspended_lua_threads */
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);
}


/* add to multimap */
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   
 * */
static int l_nsock_ncap_register(lua_State *l){
      l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);
      size_t testdatasz;
      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->l     = l;
      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. 
 * If packet is already captured, this function will return immidietly.
 * 
 * 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*) auxiliar_checkclass(l, "nsock", 1);
      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;
      
      /* 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);

      lua_call(l, 3, 1);
      
      /* get string from top of the stack*/
      size_t testdatasz;
      const char* testdata = lua_tolstring(l, -1, &testdatasz); 
      // lua_pop(l, 1);/* just in case [nope, it's not needed]*/
      
      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;

      
      switch(nse_status(nse)) {
      case NSE_STATUS_SUCCESS:{
            char *key = ncap_request_do_callback(nse, nr->l, 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);


            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, 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;

      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*) 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->l;

      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;
      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 */
            return process_waiting2running(l, 4);
      else              /* not suspended, just pass output */
            return 4;
}




/****************** 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}
};

int l_dnet_open(lua_State* l) {
      auxiliar_newclass(l, "dnet", l_dnet);
      return NSOCK_WRAPPER_SUCCESS;
}

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));
      auxiliar_setclass(l, "dnet", -1);
      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;
      }
      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;
} dnet_eth_map;


std::map<std::string, dnet_eth_map *> dnet_eth_cache;

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;
}

/* 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;
}

static int l_dnet_open_ethernet(lua_State* l){
      l_dnet_udata* udata = (l_dnet_udata*) auxiliar_checkclass(l, "dnet", 1);
      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*) auxiliar_checkclass(l, "dnet", 1);
      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*) auxiliar_checkclass(l, "dnet", 1);
      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;
}

int l_clock_ms(lua_State* l){
      struct timeval tv;
      gettimeofday(&tv, NULL);
      // no rounding error 
      // unless the number is greater than 100,000,000,000,000
      double usec = 0.0; //MAX_INT*1000 =    4 294 967 296 000 <- miliseconds since epoch should fit
      usec = tv.tv_sec*1000; 
      usec += (int)(tv.tv_usec/1000);     // make sure it's integer.
      
      lua_pushnumber(l, usec);
      return 1;
}





Generated by  Doxygen 1.6.0   Back to index