⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 daemon.c

📁 winpcap
💻 C
📖 第 1 页 / 共 4 页
字号:

	if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &filter, sizeof(struct rpcap_filter), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
	{
		// to avoid blocking on the sock_discard()
		*plen= *nread;
		return -1;
	}

	bf_prog.bf_len= ntohl(filter.nitems);

	if (ntohs(filter.filtertype) != RPCAP_UPDATEFILTER_BPF)
	{
		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported");
		return -1;
	}

	bf_insn= (struct bpf_insn *) malloc ( sizeof(struct bpf_insn) * bf_prog.bf_len);
	if (bf_insn == NULL)
	{
		snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
		return -1;
	}

	bf_prog.bf_insns= bf_insn;

	for (i= 0; i < bf_prog.bf_len; i++)
	{
		if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &insn, 
			sizeof(struct rpcap_filterbpf_insn), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
			return -1;

		bf_insn->code= ntohs(insn.code);
		bf_insn->jf= insn.jf;
		bf_insn->jt= insn.jt;
		bf_insn->k= ntohl(insn.k);

		bf_insn++;
	}

	if (bpf_validate(bf_prog.bf_insns, bf_prog.bf_len) == 0)
	{
		snprintf(errbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions");
		return -1;
	}

	if (pcap_setfilter(fp, &bf_prog) )
	{
		snprintf(errbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", fp->errbuf);
		return -1;
    }

	return 0;
}



int daemon_updatefilter(pcap_t *fp, uint32 plen)
{
struct rpcap_header header;			// keeps the answer to the updatefilter command
unsigned int nread;

	nread= 0;

	if ( daemon_unpackapplyfilter(fp, &nread, &plen, fp->errbuf) )
		goto error;

	// Check if all the data has been read; if not, discard the data in excess
	if (nread != plen)
	{
		if (sock_discard(fp->rmt_sockctrl, plen - nread, NULL, 0) )
		{
			nread= plen;		// just to avoid to call discard again in the 'error' section
			goto error;
		}
	}

	// A response is needed, otherwise the other host does not know that everything went well
	rpcap_createhdr( &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);

	if ( sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fp->errbuf, PCAP_ERRBUF_SIZE) )
		goto error;

	return 0;


error:
	if (nread != plen)
		sock_discard(fp->rmt_sockctrl, plen - nread, NULL, 0);

	rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_UPDATEFILTER, NULL);

	return -1;
}



/*!
	\brief Received the sampling parameters from remote host and it stores in the pcap_t structure.
*/
int daemon_setsampling(SOCKET sockctrl, struct rpcap_sampling *samp_param, int plen, char *errbuf)
{
struct rpcap_header header;
struct rpcap_sampling rpcap_samp;
int nread;					// number of bytes of the payload read from the socket


	if ( ( nread= sock_recv(sockctrl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling), 
			SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
		goto error;


	// Save these settings in the pcap_t 
	samp_param->method= rpcap_samp.method;
	samp_param->value= ntohl(rpcap_samp.value);


	// A response is needed, otherwise the other host does not know that everything went well
	rpcap_createhdr( &header, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);

	if ( sock_send(sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) )
		goto error;

	if (nread != plen)
		sock_discard(sockctrl, plen - nread, NULL, 0);

	return 0;

error:
	if (nread != plen)
		sock_discard(sockctrl, plen - nread, NULL, 0);

	rpcap_senderror(sockctrl, errbuf, PCAP_ERR_SETSAMPLING, NULL);

	return -1;
}



int daemon_getstats(pcap_t *fp)
{
char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
int sendbufidx= 0;					// index which keeps the number of bytes currently buffered
struct pcap_stat stats;				// local statistics
struct rpcap_stats *netstats;		// statistics sent on the network

	if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 
		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
		goto error;

	rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));

	netstats= (struct rpcap_stats *) &sendbuf[sendbufidx];

	if ( sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
		goto error;

	if (pcap_stats(fp, &stats) )
		goto error;

	netstats->ifdrop= htonl(stats.ps_ifdrop);
	netstats->ifrecv= htonl(stats.ps_recv);
	netstats->krnldrop= htonl(stats.ps_drop);
	netstats->svrcapt= htonl(fp->md.TotCapt);

	// Send the packet
	if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
		goto error;

	return 0;

error:
	rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_GETSTATS, NULL);
	return -1;
}




int daemon_getstatsnopcap(SOCKET sockctrl, unsigned int ifdrops, unsigned int ifrecv, 
						  unsigned int krnldrop, unsigned int svrcapt, char *errbuf)
{
char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
int sendbufidx= 0;					// index which keeps the number of bytes currently buffered
struct rpcap_stats *netstats;		// statistics sent on the network

	if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
		goto error;

	rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));

	netstats= (struct rpcap_stats *) &sendbuf[sendbufidx];

	if ( sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
		goto error;

	netstats->ifdrop= htonl(ifdrops);
	netstats->ifrecv= htonl(ifrecv);
	netstats->krnldrop= htonl(krnldrop);
	netstats->svrcapt= htonl(svrcapt);

	// Send the packet
	if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
		goto error;

	return 0;

error:
	rpcap_senderror(sockctrl, errbuf, PCAP_ERR_GETSTATS, NULL);
	return -1;
}




void *daemon_thrdatamain(void *ptr)
{
char errbuf[PCAP_ERRBUF_SIZE + 1];	// error buffer
pcap_t *fp;							// pointer to a 'pcap' structure
int retval;							// general variable used to keep the return value of other functions
struct rpcap_pkthdr *net_pkt_header;// header of the packet
struct pcap_pkthdr *pkt_header;		// pointer to the buffer that contains the header of the current packet
u_char *pkt_data;					// pointer to the buffer that contains the current packet
char *sendbuf;						// temporary buffer in which data to be sent is buffered
int sendbufidx;						// index which keeps the number of bytes currently buffered

	fp= (pcap_t *) ptr;

	fp->md.TotCapt= 0;			// counter which is incremented each time a packet is received

	// Initialize errbuf
	memset(errbuf, 0, sizeof(errbuf) );

	// Some platforms (e.g. Win32) allow creating a static variable with this size
	// However, others (e.g. BSD) do not, so we're forced to allocate this buffer dynamically
	sendbuf= (char *) malloc (sizeof(char) * RPCAP_NETBUF_SIZE);
	if (sendbuf == NULL)
	{
		snprintf(errbuf, sizeof(errbuf) - 1, "Unable to create the buffer for this child thread");
		goto error;
	}

	// Modify thread params so that it can be killed at any time
	if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) )
		goto error;
	if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) )
		goto error;

	// Retrieve the packets
	while ((retval = pcap_next_ex(fp, &pkt_header, (const u_char **) &pkt_data)) >= 0)	// cast to avoid a compiler warning
	{
		if (retval == 0)	// Read timeout elapsed
			continue;

		sendbufidx= 0;

		// Bufferize the general header
		if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
			RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
			goto error;

		rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_PACKET, 0,
			(uint16) (sizeof(struct rpcap_pkthdr) + pkt_header->caplen) );

		net_pkt_header= (struct rpcap_pkthdr *) &sendbuf[sendbufidx];

		// Bufferize the pkt header
		if ( sock_bufferize(NULL, sizeof(struct rpcap_pkthdr), NULL, &sendbufidx,
			RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
			goto error;

		net_pkt_header->caplen= htonl(pkt_header->caplen);
		net_pkt_header->len= htonl(pkt_header->len);
		net_pkt_header->npkt= htonl( ++(fp->md.TotCapt) );
		net_pkt_header->timestamp_sec= htonl(pkt_header->ts.tv_sec);
		net_pkt_header->timestamp_usec= htonl(pkt_header->ts.tv_usec);

		// Bufferize the pkt data
		if ( sock_bufferize((char *) pkt_data, pkt_header->caplen, sendbuf, &sendbufidx,
			RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
			goto error;

		// Send the packet
		if ( sock_send(fp->rmt_sockdata, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
			goto error;

	}

	if (retval == -1)
	{
		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(fp) );
		rpcap_senderror(fp->rmt_sockctrl, errbuf, PCAP_ERR_READEX, NULL);
		goto error;
	}

error:

	SOCK_ASSERT(errbuf, 1);
 	closesocket(fp->rmt_sockdata);
	fp->rmt_sockdata= 0;

	free(sendbuf);

	return NULL;
}



/*!
	\brief It serializes a network address.

	It accepts a 'sockaddr_storage' structure as input, and it converts it appropriately into a format
	that can be used to be sent on the network. Basically, it applies all the hton()
	conversion required to the input variable.

	\param sockaddrin: a 'sockaddr_storage' pointer to the variable that has to be
	serialized. This variable can be both a 'sockaddr_in' and 'sockaddr_in6'.

	\param sockaddrout: a 'sockaddr_storage' pointer to the variable that will contain
	the serialized data. This variable has to be allocated by the user.

	\return None

	\warning This function supports only AF_INET and AF_INET6 address families.
*/
void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage *sockaddrout)
{
	memset(sockaddrout, 0, sizeof(struct sockaddr_storage) );

	// There can be the case in which the sockaddrin is not available
	if (sockaddrin == NULL) return;

	// Warning: we support only AF_INET and AF_INET6
	if (sockaddrin->ss_family == AF_INET)
	{
	struct sockaddr_in *sockaddr;

		sockaddr= (struct sockaddr_in *) sockaddrin;
		sockaddr->sin_family= htons(sockaddr->sin_family);
		sockaddr->sin_port= htons(sockaddr->sin_port);
		memcpy(sockaddrout, sockaddr, sizeof(struct sockaddr_in) );
	}
	else
	{
	struct sockaddr_in6 *sockaddr;
	
		sockaddr= (struct sockaddr_in6 *) sockaddrin;
		sockaddr->sin6_family= htons(sockaddr->sin6_family);
		sockaddr->sin6_port= htons(sockaddr->sin6_port);
		sockaddr->sin6_flowinfo= htonl(sockaddr->sin6_flowinfo);
		sockaddr->sin6_scope_id= htonl(sockaddr->sin6_scope_id);
		memcpy(sockaddrout, sockaddr, sizeof(struct sockaddr_in6) );
	}
}





/*!
	\brief Suspends a pthread for msec milliseconds.

	This function is provided since pthreads do not have a suspend() call.
*/
void pthread_suspend(int msec)
{
#ifdef WIN32
	Sleep(msec);
#else
struct timespec abstime;
struct timeval now;

	pthread_cond_t cond;
	pthread_mutex_t mutex;
	pthread_mutexattr_t attr;

	pthread_mutexattr_init(&attr);
	pthread_mutex_init(&mutex, &attr);
	pthread_mutex_lock(&mutex);

	pthread_cond_init(&cond, NULL);

	gettimeofday(&now, NULL);
	
	abstime.tv_sec = now.tv_sec + msec/1000;
	abstime.tv_nsec = now.tv_usec * 1000 + (msec%1000) * 1000 * 1000;

	pthread_cond_timedwait(&cond, &mutex, &abstime);

	pthread_mutex_destroy(&mutex);
	pthread_cond_destroy(&cond);
#endif
}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -