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

📄 pcap-new.c

📁 用来监视网络通信数据的源代码和应用程序,方便网络程序底层开发.
💻 C
📖 第 1 页 / 共 4 页
字号:
{
// 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) == -1)
		return -1;

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


	if ( (sockmain= sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf)) == -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, fakeerrbuf);
		sock_close(sockctrl, fakeerrbuf);
		return -1;
	}

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

	// Send authentication to the remote machine
	if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1)
	{
		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
		sock_close(sockctrl, fakeerrbuf);
		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, fakeerrbuf);
		sock_close(sockctrl, fakeerrbuf);
		return -1;
	}

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

	return sockctrl;
}



/*!	\ingroup remote_func

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

				if (sock_close(temp->sockctrl, errbuf) )
				{
					// 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 remote_func
	\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 remote_func

	\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)
	{
		// Get the numeric for of the name of the connecting host
		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 + -