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

📄 pcap-remote.c

📁 用来监视网络通信数据的源代码和应用程序,方便网络程序底层开发.
💻 C
📖 第 1 页 / 共 5 页
字号:

	*errbuf= 0;	// Initialize errbuf

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

	// Watch out sockdata to see if it has input
	FD_ZERO(&rfds);

	// We do not have to block here
	tv.tv_sec = 0;
	tv.tv_usec = 0;

	while (1)
	{
		if (fp->cc == 0) 
		{
			u_char *bp= fp->buffer;
			cc= 0;

			while (1)
			{
again:
				FD_SET(fp->rmt_sockdata, &rfds);

				retval = select(1, &rfds, NULL, NULL, &tv);
				if (retval == -1)
				{
					sock_geterror("select(): ", errbuf, PCAP_ERRBUF_SIZE);
						goto error;
				}

				// There is no data waiting
				if (retval == 0)
				{
					// Update the pcap_t pointers so that the user application can read from the buffer
					fp->bp= fp->buffer;
					fp->cc= cc;

					pthread_suspend(100);	// Suspend 100 ms
					break;
				}

				if (!pending)
				{
					// Read the entire message from the network
					if (sock_recv_dgram(fp->rmt_sockdata, netbuf, RPCAP_NETBUF_SIZE, errbuf) == -1)
						goto error;
					header= (struct rpcap_header *) netbuf;

					// Checks if the message is correct
					retval= rpcap_checkmsg(errbuf, fp->rmt_sockdata, (struct rpcap_header *) netbuf, RPCAP_MSG_PACKET, 0);

					if (retval != RPCAP_MSG_PACKET)		// the message is not the one expected
					{
						switch (retval)
						{
							case -3:		// Unrecoverable network error							
								goto error;	// Do nothing; just exit from here; the error code is already into the errbuf

							case -2:		// The other endpoint sent a message that is not allowed here
							case -1:	// The other endpoint has a version number that is not compatible with our
								goto again;

							default:
							{
								SOCK_ASSERT("Internal error", 0);
								goto error;
							};
						}
					}

					// Set a pointer to the RPCAP packet header
					net_pkt_header= (struct rpcap_pkthdr *) (netbuf + sizeof(struct rpcap_header));
				}

				if ( (cc + ntohl(net_pkt_header->caplen) + sizeof(struct pcap_pkthdr) ) <= ( (unsigned) fp->bufsize) )
				{
					unsigned int npkt;
					pending= 0;

					pkt_header= (struct pcap_pkthdr *) bp;
					pkt_header->caplen= ntohl(net_pkt_header->caplen);
					pkt_header->len= ntohl(net_pkt_header->len);
					pkt_header->ts.tv_sec= ntohl(net_pkt_header->timestamp_sec);
					pkt_header->ts.tv_usec= ntohl(net_pkt_header->timestamp_usec);

					// Update the number of packets received correctly
					fp->md.TotCapt++;

					// We're using UDP, so I need to update the counter of the packets dropped by the network
					npkt= ntohl(net_pkt_header->npkt);

					if (fp->md.TotCapt != npkt)
					{
						fp->md.TotNetDrops+= (npkt - fp->md.TotCapt);
						fp->md.TotCapt= npkt;
					}

					// Copies the packet into the data buffer
					memcpy( bp + sizeof(struct pcap_pkthdr), netbuf + sizeof(struct rpcap_header), pkt_header->caplen);

					bp += BPF_WORDALIGN(pkt_header->caplen + sizeof(struct pcap_pkthdr));
					cc += BPF_WORDALIGN(pkt_header->caplen + sizeof(struct pcap_pkthdr));
				}
				else
				{
					pending= 1;

					// Update the pcap_t pointers so that the user application can read from the buffer
					fp->bp= fp->buffer;
					fp->cc= cc;

					break;
				}
			} // end while (1)
		}
		else
		{
			pthread_suspend(100);	// Suspend 100 ms
		}
	}	// end main while(1)

error:
	SOCK_ASSERT("Exiting from the child data thread", 1);
	SOCK_ASSERT(errbuf, 1);

	// Removes the descriptor s from set
	FD_CLR(fp->rmt_sockdata, &rfds);

 	closesocket(fp->rmt_sockdata);
	fp->rmt_sockdata= 0;
	fp->rmt_threaddata= 0;
}






/*********************************************************
 *                                                       *
 * Miscellaneous functions                               *
 *                                                       *
 *********************************************************/


/*!	\ingroup remote_pri_func
	\brief It sends a RPCAP error to the other peer.

	This function has to be called when the main program detects an error. This funcion
	will send on the other peer the 'buffer' specified by the user.
	This function *does not* request a RPCAP CLOSE connection. A CLOSE command must be sent
	explicitely by the program, since we do not know it the error can be recovered in some
	way or it is a non-recoverable one.

	\param sock: the socket we are currently using.

	\param error: an user-allocated (and '0' termined) buffer that contains the error 
	description thas has to be transmitted on the other peer. The error message cannot
	be longer than PCAP_ERRBUF_SIZE.

	\param errcode: a integer which tells the other party the type of error we had;
	currently is is not too much used.

	\param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
	that will contain the error message (in case there is one). It could be network problem.

	\return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
	in the 'errbuf' variable.
*/
int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, 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
uint16 length;

	length= (uint16) strlen(error);

	if (length > PCAP_ERRBUF_SIZE)
		length= PCAP_ERRBUF_SIZE;

	rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_ERROR, errcode, length);

	if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) )
		return -1;

	if ( sock_bufferize(error, length, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) )
		return -1;

	if ( sock_send(sock, sendbuf, sendbufidx, errbuf) )
		return -1;

	return 0;
}



/*!	\ingroup remote_pri_func
	\brief Sends the authentication message.

	It sends the authentication parameters on the control socket.
	Ths function is required in order to open the connection with the other end party.

	\param sock: the socket we are currently using.

	\param auth: authentication parameters that have to be sent.

	\param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
	that will contain the error message (in case there is one). It could be network problem
	ot the fact that the authorization failed.

	\return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
	in the 'errbuf' variable.
	The error message could be also 'the authentication failed'.
*/
int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf)
{
char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data that has to be sent is buffered
int sendbufidx= 0;					// index which keeps the number of bytes currently buffered
uint16 length;						// length of the payload of this message
struct rpcap_auth *rpauth;
uint16 auth_type;
struct rpcap_header header;
int retval;							// temp variable which stores functions return value

	if (auth)
	{
	auth_type= auth->type;

		switch (auth->type)
		{
			case RPCAP_RMTAUTH_NULL:
				length= sizeof (struct rpcap_auth);
				break;

			case RPCAP_RMTAUTH_PWD:
				length= sizeof (struct rpcap_auth);
				if (auth->username) length+= strlen(auth->username);
				if (auth->password) length+= strlen(auth->password);
				break;

			default:
				snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
				return -1;
		}
	}
	else
	{
		auth_type= RPCAP_RMTAUTH_NULL;
		length= sizeof (struct rpcap_auth);
	}


	if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) )
		return -1;

	rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_AUTH_REQ, 0, length);

	rpauth= (struct rpcap_auth *) &sendbuf[sendbufidx];

	if ( sock_bufferize(NULL, sizeof(struct rpcap_auth), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) )
		return -1;

	memset(rpauth, 0, sizeof (struct rpcap_auth) );

	rpauth->type= htons(auth_type);

	if (auth_type == RPCAP_RMTAUTH_PWD)
	{

		if (auth->username)
			rpauth->slen1= strlen(auth->username);
		else
			rpauth->slen1= 0;

		if ( sock_bufferize(auth->username, rpauth->slen1, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) )
			return -1;

		if (auth->password)
			rpauth->slen2= strlen(auth->password);
		else
			rpauth->slen2= 0;

		if ( sock_bufferize(auth->password, rpauth->slen2, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) )
			return -1;

		rpauth->slen1= htons (rpauth->slen1);
		rpauth->slen2= htons (rpauth->slen2);
	}

	if ( sock_send(sock, sendbuf, sendbufidx, errbuf) )
		return -1;

	if ( sock_recv(sock, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1)
		return -1;

	retval= rpcap_checkmsg(errbuf, sock, &header, RPCAP_MSG_AUTH_REPLY, RPCAP_MSG_ERROR, 0);

	if (retval != RPCAP_MSG_AUTH_REPLY)		// the message is not the one expected
	{
		switch (retval)
		{
			case -3:		// Unrecoverable network error
			case -2:		// The other endpoint sent a message that is not allowed here
			case -1:	// The other endpoint has a version number that is not compatible with our
				// Do nothing; just exit from here; the error code is already into the errbuf
				return -1;

			case RPCAP_MSG_ERROR:
			{
				return -1;
			};

			default:
			{
				SOCK_ASSERT("Internal error", 0);
				return -1;
			};
		}
	}

	if (ntohl(header.plen) )
	{
		if (sock_discard(sock, ntohl(header.plen), errbuf) )
			return -1;
	}
	
	return 0;
}



/*!	\ingroup remote_pri_func
	\brief Creates a structure of type rpcap_header.

	This function is provided just because the creation of an rpcap header is quite a common
	task. It accepts all the values that appears into an rpcap_header, and it puts them in
	place using the proper hton() calls.

	\param header: a pointer to a user-allocated buffer which will contain the serialized
	header, ready to be sent on the network.

	\param type: a value (in the host by order) which will be placed into the header.type
	field and that represents the type of the current message.

	\param value: a value (in the host by order) which will be placed into the header.value
	field and that has a message-dependent meaning.

	\param length: a value (in the host by order) which will be placed into the header.length
	field and that represents the payload length of the message.

	\return Nothing. The serialized header is returned into the 'header' variable.
*/
void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length)
{
	memset(header, 0, sizeof (struct rpcap_header) );

	header->ver= RPCAP_VERSION;
	header->type= type;
	header->value= htons(value);
	header->plen= htonl(length);
}



/*!	\ingroup remote_pri_func
	\brief Checks if the header of the received message is correct.
	
	This function is a way to easily check if the message received, in a certain 
	state of the RPCAP protocol Finite State Machine, is valid. This function accepts,
	as a parameter, the list of message types that are allowed in a certain situation,
	and it returns the one which occurs.

	\param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
	that will contain the error message (in case there is one). It could be either problem
	occurred inside this function (e.g. a network problem in ca

⌨️ 快捷键说明

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