nse_nsock.cc
来自「Ubuntu packages of security software。 相」· CC 代码 · 共 1,410 行 · 第 1/3 页
CC
1,410 行
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;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?