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

📄 pcap-new.c

📁 用来监视网络通信数据的源代码和应用程序,方便网络程序底层开发.
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * Copyright (c) 2002 - 2003
 * NetGroup, Politecnico di Torino (Italy)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * 
 * 1. Redistributions of source code must retain the above copyright 
 * notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the following disclaimer in the 
 * documentation and/or other materials provided with the distribution. 
 * 3. Neither the name of the Politecnico di Torino nor the names of its 
 * contributors may be used to endorse or promote products derived from 
 * this software without specific prior written permission. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

#include <pcap-int.h>	// for the details of the pcap_t structure
#include <pcap-remote.h>
#include <sockutils.h>
#include <errno.h>	// for the errno variable
#include <stdlib.h>		// for malloc(), free(), ...
#include <string.h>		// for strstr, etc



/*
	\brief Global variable; needed to keep the message due to an error that we want to discard.
	
	This can happen, for instance, because we already have an error message and we want to keep 
	the first one.
*/
char fakeerrbuf[PCAP_ERRBUF_SIZE + 1];


//! Keeps a list of all the opened connections in the active mode.
extern struct activehosts *activeHosts;


/*!
	\brief Keeps the main socket identifier when we want to accept a new remote connection (active mode only).

	See the documentation of pcap_remoteact_accept() and pcap_remoteact_cleanup() for more details.
*/
SOCKET sockmain;






/****************************************************
 *                                                  *
 * Function bodies                                  *
 *                                                  *
 ****************************************************/


/*! \ingroup remote_func
	\brief It creates a list of network devices that can be opened with pcap_open().
	
	This function is a superset of the old 'pcap_findalldevs()', which is obsolete, and which
	allows listing only the devices present on the local machine.
	Vice versa, pcap_findalldevs_ex() allows listing the devices present on a remote 
	machine as well. Moreover, pcap_findalldevs_ex() is platform independent, since it
	relies on the standard pcap_findalldevs() to get addresses on the local machine.

	In case the function has to list the interfaces on a remote machine, it opens a new control
	connection toward that machine, it retrieves the interfaces, and it drops the connection.
	However, if this function detects that the remote machine is in 'active' mode,
	the connection is not dropped (see the 'sockctrl' parameters for more details).
	In the same way, if we're in active mode and the connection is already opened, it
	uses the existing socket.

	This function can rely on the pcap_createsrcstr() to create the string that keeps
	the capture device according to	the new syntax, and the pcap_parsesrcstr() for the
	other way round.

	\param host: a char* buffer that keeps the address of the remote host on which 
	we want to see the interface list.
	It can be NULL: in this case the function queries the local host for the locally
	installed interfaces. The address can be both numeric (e.g. '10.11.12.13', '1:2:3::4')
	and literal (e.g. 'foo.bar.com').

	\param auth: a pointer to a pcap_rmtauth structure. This pointer keeps the information
	required to authenticate the RPCAP connection to the remote host.
	This parameter is not meaningful in case of a query to the local host: in that case
	it can be NULL.

	\param sockctrl: Socket to be used for the control connection.
	This parameter is meaningful only if the control connection is already open when the 
	pcap_findalldevs() is called. This can be the case in which the 'ative' mode is used, 
	in which the capturing machine opens a control connection toward the client in order 
	to bypass in-middle firewalls. In that case, the control connection is already open, 
	and we have to use this one instead of opening a new one.

	In case this parameter is non-zero, the 'host' and 'port' parameters are meaningless:
	the software will always try to retrieve the network adapters using this control
	connection, despite the value assumed by 'host' and 'port'.
	In case this parameter is non-zero, the socket is not closed at the end of the function
	and it remains open for future use.

	\param port: a char* buffer (e.g. "2003") that keeps the network port on which we 
	want to connect to.
	It can be NULL: in this case the function uses the standard port, defined in 
	RPCAP_DEFAULT_NETPORT.

	\param alldevs: a 'struct pcap_if_t' pointer, which will be properly allocated inside
	this function. When the function returns, it is set to point to the first element 
	of the interface list; each element of the list is of type 'struct pcap_if_t'.

	\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 list of the devices 
	is returned in the 'alldevs' variable.
	When the function returns correctly, 'alldevs' cannot be NULL. In other words, this 
	function returns '-1' also in case the system does not have any interface to list.

	The error message is returned in the 'errbuf' variable. An error could be due to 
	several reasons:
	- libpcap/WinPcap was not installed on the local/remote host
	- the user does not have enough privileges to list the devices
	- a network problem
	- the RPCAP version negotiation failed
	- other errors (not enough memory and others).
	
	\warning There may be network devices that cannot be opened with pcap_open() by the process
	calling pcap_findalldevs(), because, for example, that process might not have
	sufficient privileges to open them for capturing; if so, those devices will not 
	appear on the list.

	\warning The interface list must be deallocated manually by using the pcap_freealldevs().
*/
int pcap_findalldevs_ex(char *host, char *port, SOCKET sockctrl, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf) 
{
unsigned int nread= 0;		// number of bytes of the payload read from the socket
struct addrinfo hints;		// temp variable needed to resove hostnames into to socket representation
struct addrinfo *addrinfo;	// temp variable needed to resove hostnames into to socket representation
struct rpcap_header header;	// structure that keeps the general header of the rpcap protocol
int i,j;		// temp variables
int naddr;		// temp var needed to avoid problems with IPv6 addresses
int retval;		// store the return value of the functions
int nif;		// Number of interfaces listed
int active= 0;	// 'true' if we the other end-party is in active mode


	// We have to perform two controls here, because the user can call this function in two ways:
	//   pcap_findalldevs_ex(NULL, ...) ==> address == NULL
	//   pcap_findalldevs_ex("", ...) ==> address[0] == 0
	if ( (host == NULL) || (host[0] == 0) )
	{
		// The user wants to retrieve adapters from a local host
		if (pcap_findalldevs(alldevs, errbuf) == -1)
			return -1;
		if ( (alldevs == NULL) || (*alldevs == NULL) )
		{
			snprintf(errbuf, PCAP_ERRBUF_SIZE,
				"No interfaces found! Make sure libpcap/WinPcap is properly installed"
				" on the local machine.");
			return -1;
		}
		return 0;
	}

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

	// Check for active mode
	if ( (retval= rpcap_remoteact_getsock(host, errbuf)) == -1)
		return -1;

	if (retval)
	{
		sockctrl= retval;
		active= 1;
	}
	else	// we're not in active mode; let's opening a new control connection (if needed)
	{
		addrinfo= NULL;

		memset(&hints, 0, sizeof(struct addrinfo) );
		hints.ai_family = PF_UNSPEC;
		hints.ai_socktype = SOCK_STREAM;

		if ( (port == NULL) || (port[0] == 0) )
		{
			// the user chose not to specify the port
			if (sock_validaddr(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf) == -1)
				return -1;
		}
		else
		{
			if (sock_validaddr(host, port, &hints, &addrinfo, errbuf) == -1)
				return -1;
		}

		if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf)) == -1)
			goto error;

		// addrinfo is no longer used
		freeaddrinfo(addrinfo);
		addrinfo= NULL;

		if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1)
		{
			// Control connection has to be closed only in case the remote machine is in passive mode
			if (!active)
				sock_close(sockctrl, fakeerrbuf);
			return -1;
		}
	}

	// RPCAP findalldevs command
	rpcap_createhdr(&header, RPCAP_MSG_FINDALLIF_REQ, 0, 0);

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

	if ( sock_recv(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1)
		goto error;

	// Checks if the message is correct
	retval= rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_FINDALLIF_REPLY, RPCAP_MSG_ERROR, 0);

	if (retval != RPCAP_MSG_FINDALLIF_REPLY)		// the message is not the one expected
	{
		switch (retval)
		{
			case -3:	// Unrecoverable network error
			case -2:	// The other endpoint send a message that is not allowed here
			case -1:	// The other endpoint has a version number that is not compatible with our
				break;

			case RPCAP_MSG_ERROR:		// The other endpoint reported an error
				break;

			default:
			{
				snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error");
				break;
			};
		}

		if (!active)
			sock_close(sockctrl, fakeerrbuf);

		return -1;
	}

	// read the number of interfaces
	nif= ntohs(header.value);

	// loop until all interfaces have been received
	for (i= 0; i < nif; i++)
	{
	struct rpcap_findalldevs_if findalldevs_if;
	pcap_if_t *dev;		// Previous device into the pcap_if_t chain

		// receive the findalldevs structure from remote hsot
		if ( (nread+= sock_recv(sockctrl, (char *) &findalldevs_if, 
			sizeof(struct rpcap_findalldevs_if), errbuf) ) == -1)
			goto error;

		findalldevs_if.namelen= ntohs(findalldevs_if.namelen);
		findalldevs_if.desclen= ntohs(findalldevs_if.desclen);
		findalldevs_if.naddr= ntohs(findalldevs_if.naddr);

		// allocate the main structure
		if (i == 0)
		{
			(*alldevs)= (pcap_if_t *) malloc(sizeof(pcap_if_t) );
			dev= (*alldevs);
		}
		else
		{
			dev->next= (pcap_if_t *) malloc(sizeof(pcap_if_t) );
			dev= dev->next;
		}

		// check that the malloc() didn't fail
		if (dev == NULL)
		{
			snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
			goto error;
		}
		dev->next= NULL;
		dev->addresses= NULL;

		// allocate mem for name and description
		if (findalldevs_if.namelen)
		{
			dev->name= (char *) malloc(findalldevs_if.namelen + 1);
			if (dev->name == NULL)
			{
				snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
				goto error;
			}
			// Retrieve adapter name and description
			if ( (nread+= sock_recv(sockctrl, dev->name, findalldevs_if.namelen, errbuf) ) == -1)
				goto error;
			dev->name[findalldevs_if.namelen]= 0;
		}
		else
			dev->name= NULL;

		if (findalldevs_if.desclen)
		{
			dev->description= (char *) malloc(findalldevs_if.desclen + 1);
			if (dev->description == NULL)
			{
				snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
				goto error;
			}
			// Retrieve adapter name and description

⌨️ 快捷键说明

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