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 + -
显示快捷键?