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

📄 pcap-new.c

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

	\brief It blocks until a network connection is accepted (active mode only).

	This function has been defined to allow the client dealing with the 'active mode'.
	In other words, in the 'active mode' the server opens the connection toward the
	client, so that the client has to open a socket in order to wait for connections.
	When a new connection is accepted, the RPCAP protocol starts as usual; the only 
	difference is that the connection is initiated by the server.

	This function accepts only ONE connection, then it closes the waiting socket. This means
	that if some error occurs, the application has to call it again in order to accept another
	connection.

	This function returns when a new connection (coming from a valid host 'connectinghost')
	is accepted; it returns error otherwise.

	\param address: a string that keeps the network address we have to bind to; 
	usually it is NULL (it means 'bind on all local addresses').

	\param port: a string that keeps the network port on which we have to bind to; usually
	it is NULL (it means 'bind on the predefined port', i.e. RPCAP_DEFAULT_NETPORT_ACTIVE).

	\param hostlist: a string that keeps the host name of the host from whom we are
	expecting a connection; it can be NULL (it means 'accept connection from everyone').
	Host names are separated by a whatever character in the RPCAP_HOSTLIST_SEP list.

	\param connectinghost: a user-allocated buffer that will contain the name of the host
	is trying to connect to us.
	This variable must be at least RPCAP_HOSTLIST_SIZE bytes..

	\param auth: a pointer to a pcap_rmtauth structure. This pointer keeps the information
	required to authenticate the RPCAP connection to the remote host.

	\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).

	\return The SOCKET identifier of the new control connection if everything is fine,
	a negative number if some errors occurred. The error message is returned into the errbuf variable.
	In case it returns '-1', this means 'everything is fine', but the host cannot be admitted.
	In case it returns '-2', in means 'unrecoverable error' (for example it is not able to bind the 
	socket, or something like that).
	In case it returns '-3', it means 'authentication failed'. The authentication check is performed
	only if the connecting host is among the ones that are allowed to connect to this host.

	The host that is connecting to us is returned into the hostlist variable, which ust be allocated
	by the user. This variable contains the host name both in case the host is allowed, 
	and in case the connection is refused.

	\warning Although this function returns the socket established by the new control connection,
	this value should not be used. This value will be stored into some libpcap internal
	variables and it will be managed automatically by the library. In other words, all the
	following calls to findalldevs() and pcap_open() will check if the host is among one that
	already has a control connection in place; if so, that one will be used.

	\warning This function has several problems if used inside a thread, which is stopped
	when this call is blocked into the accept(). In this case, the socket on which we accept
	connections is not freed (thread termination is a very dirty job), so that we are no
	longer able to accept other connections until the program (i.e. the process) stops.
	In order to solve the problem, call the pcap_remoteact_cleanup().
*/
SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf)
{
// socket-related variables
struct addrinfo hints;			// temporary struct to keep settings needed to open the new socket
struct addrinfo *addrinfo;		// keeps the addrinfo chain; required to open a new socket
struct sockaddr_storage from;	// generic sockaddr_storage variable
socklen_t fromlen;				// keeps the length of the sockaddr_storage variable
SOCKET sockctrl;				// keeps the main socket identifier
struct activehosts *temp, *prev;	// temp var needed to scan he host list chain

	*connectinghost= 0;		// just in case

	// Prepare to open a new server socket
	memset(&hints, 0, sizeof(struct addrinfo));
									// WARNING Currently it supports only ONE socket family among ipv4 and IPv6 
	hints.ai_family = AF_INET;		// PF_UNSPEC to have both IPv4 and IPv6 server
	hints.ai_flags = AI_PASSIVE;	// Ready to a bind() socket
	hints.ai_socktype = SOCK_STREAM;

	// Warning: this call can be the first one called by the user.
	// For this reason, we have to initialize the WinSock support.
	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
		return -1;

	// Do the work
	if ((port == NULL) || (port[0] == 0) )
	{	
		if (sock_initaddress(address, RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
		{
			SOCK_ASSERT(errbuf, 1);
			return -2;
		}
	}
	else
	{
		if (sock_initaddress(address, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
		{
			SOCK_ASSERT(errbuf, 1);
			return -2;
		}
	}


	if ( (sockmain= sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf, PCAP_ERRBUF_SIZE)) == -1)
	{
		SOCK_ASSERT(errbuf, 1);
		return -2;
	}

	// Connection creation
	fromlen = sizeof(struct sockaddr_storage);

	sockctrl= accept(sockmain, (struct sockaddr *) &from, &fromlen);

	// We're not using sock_close, since we do not want to send a shutdown
	// (which is not allowed on a non-connected socket)
	closesocket(sockmain);
	sockmain= 0;

	if (sockctrl == -1)
	{
		sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
		return -2;
	}

	// Get the numeric for of the name of the connecting host
	if (getnameinfo( (struct sockaddr *) &from, fromlen, connectinghost, RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) )
	{
		sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
		sock_close(sockctrl, NULL, 0);
		return -1;
	}

	// checks if the connecting host is among the ones allowed
	if (sock_check_hostlist((char *) hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
	{
		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
		sock_close(sockctrl, NULL, 0);
		return -1;
	}

	// Send authentication to the remote machine
	if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1)
	{
		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
		sock_close(sockctrl, NULL, 0);
		return -3;
	}

	// Checks that this host does not already have a cntrl connection in place

	// Initialize pointers
	temp= activeHosts;
	prev= NULL;
	
	while (temp)
	{
		// This host already has an active connection in place, so I don't have to update the host list
		if (sock_cmpaddr(&temp->host, &from) == 0)
			return sockctrl;

		prev= temp;
		temp= temp->next;
	}

	// The host does not exist in the list; so I have to update the list
	if (prev)
	{
		prev->next= (struct activehosts *) malloc (sizeof (struct activehosts) );
		temp= prev->next;
	}
	else
	{
		activeHosts= (struct activehosts *) malloc (sizeof (struct activehosts) );
		temp= activeHosts;
	}

	if (temp == NULL)
	{
		snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, NULL);
		sock_close(sockctrl, NULL, 0);
		return -1;
	}

	memcpy(&temp->host, &from, fromlen);
	temp->sockctrl= sockctrl;
	temp->next= NULL;

	return sockctrl;
}



/*!
	\ingroup wpcapfunc

	\brief It drops an active connection (active mode only).

	This function has been defined to allow the client dealing with the 'active mode'.
	This function closes an active connection that is still in place and it purges
	the host name from the 'activeHost' list.
	From this point on, the client will not have any connection with that host in place.

	\param host: a string that keeps the host name of the host for which we want to
	close the active connection.

	\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).

	\return '0' if everything is fine, '-1' if some errors occurred. The error message is 
	returned into the errbuf variable.
*/
int pcap_remoteact_close(const char *host, char *errbuf)
{
struct activehosts *temp, *prev;	// temp var needed to scan the host list chain
struct addrinfo hints, *addrinfo, *ai_next;	// temp var needed to translate between hostname to its address
int retval;

	temp= activeHosts;
	prev= NULL;

	// retrieve the network address corresponding to 'host'
	addrinfo = NULL;
	memset(&hints, 0, sizeof (struct addrinfo) );
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype= SOCK_STREAM;

	retval = getaddrinfo(host, "0", &hints, &addrinfo);
	if (retval != 0)
	{
		snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
		return -1;
	}

	while (temp)
	{
		ai_next= addrinfo;
		while(ai_next)
		{
			if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr ) == 0)
			{
			struct rpcap_header header;

				// Close this connection
				rpcap_createhdr( &header, RPCAP_MSG_CLOSE, 0, 0);

				// I don't check for errors, since I'm going to close everything
				sock_send(temp->sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE);

				if (sock_close(temp->sockctrl, errbuf, PCAP_ERRBUF_SIZE) )
				{
					// To avoid inconsistencies in the number of sock_init()
					sock_cleanup();

					return -1;
				}

				if (prev)
					prev->next= temp->next;
				else
					activeHosts= temp->next;

				freeaddrinfo(addrinfo);

				free(temp);

				// To avoid inconsistencies in the number of sock_init()
				sock_cleanup();

				return 0;
			}

			ai_next= ai_next->ai_next;
		}
		prev= temp;
		temp= temp->next;
	}

	if (addrinfo)
		freeaddrinfo(addrinfo);

	// To avoid inconsistencies in the number of sock_init()
	sock_cleanup();

	snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host you want to close the active connection is not known");
	return -1;
}


/*!
	\ingroup wpcapfunc

	\brief Cleans the socket that is currently used in waiting active connections.

	This function does a very dirty job. The fact is that is the waiting socket is not
	freed if the pcap_remoteaccept() is killed inside a new thread. This function is
	able to clean the socket in order to allow the next calls to pcap_remoteact_accept() to work.
	
	This function is useful *only* if you launch pcap_remoteact_accept() inside a new thread,
	and you stops (not very gracefully) the thread (for example because the user changed idea,
	and it does no longer want to wait for an active connection).
	So, basically, the flow should be the following:
	- launch a new thread
	- call the pcap_remoteact_accept
	- if this new thread is killed, call pcap_remoteact_cleanup().
	
	This function has no effects in other cases.

	\return None.
*/
void pcap_remoteact_cleanup()
{
	// Very dirty, but it works
	if (sockmain)
	{
		closesocket(sockmain);

		// To avoid inconsistencies in the number of sock_init()
		sock_cleanup();
	}

}


/*!
	\ingroup wpcapfunc

	\brief Returns the hostname of the host that have an active connection with us (active mode only).

	This function has been defined to allow the client dealing with the 'active mode'.
	This function returns the list of hosts that are currently having an active connection
	with us. This function is useful in order to delete an active connection that is still
	in place.

	\param hostlist: a user-allocated string that will keep the list of host that are 
	currently connected with us.

	\param sep: the character that has to be sued as a separator between the hosts (','  for example).

	\param size: size of the hostlist buffer.

	\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).

	\return '0' if everything is fine, '-1' if some errors occurred. The error message is 
	returned into the errbuf variable.
*/
int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf)
{
struct activehosts *temp;	// temp var needed to scan the host list chain
int len;
char hoststr[RPCAP_HOSTLIST_SIZE + 1];

	temp= activeHosts;

	len= 0;
	*hostlist= 0;

	while (temp)
	{
//int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen)

		// Get the numeric form of the name of the connecting host
		if (sock_getascii_addrport( (struct sockaddr_storage *) &temp->host,hoststr, 
				RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST, errbuf, PCAP_ERRBUF_SIZE) != -1)
//		if (getnameinfo( (struct sockaddr *) &temp->host, sizeof (struct sockaddr_storage), hoststr, 
//				RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) )
		{
//			sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
			return -1;
		}

		len= len + strlen(hoststr) + 1 /* the separator */;

		if (len >= size)
		{
			snprintf(errbuf, PCAP_ERRBUF_SIZE, "The string you provided is not able to keep "
				"the hostnames for all the active connections");
			return -1;
		}

		strcat(hostlist, hoststr);
		hostlist[len - 1]= sep;
		hostlist[len]= 0;

		temp= temp->next;
	}

	return 0;
}

⌨️ 快捷键说明

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