Beispiel #1
0
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;
}
Beispiel #2
0
int daemon_endcapture(pcap_t *fp, pthread_t *threaddata, char *errbuf)
{
struct rpcap_header header;
SOCKET sockctrl;

	if (threaddata)
	{
		pthread_cancel(*threaddata);
		threaddata= 0;
	}
	if (fp->rmt_sockdata)
	{
		sock_close(fp->rmt_sockdata, NULL, 0);
		fp->rmt_sockdata= 0;
	}

	sockctrl= fp->rmt_sockctrl;

	pcap_close(fp);
	fp= NULL;

	rpcap_createhdr( &header, RPCAP_MSG_ENDCAP_REPLY, 0, 0);

	if ( sock_send(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
		return -1;
	
	return 0;
}
Beispiel #3
0
/*
 * This function sends a RPCAP error to our peer.
 *
 * It has to be called when the main program detects an error.
 * It will send to our peer the 'buffer' specified by the user.
 * This function *does not* request a RPCAP CLOSE connection. A CLOSE
 * command must be sent explicitly by the program, since we do not know
 * whether the error can be recovered in some way or if it is a
 * non-recoverable one.
 *
 * \param sock: the socket we are currently using.
 *
 * \param ver: the protocol version we want to put in the reply.
 *
 * \param errcode: a integer which tells the other party the type of error
 * we had.
 *
 * \param error: an user-allocated (and '0' terminated) buffer that contains
 * the error description that has to be transmitted to our peer. The
 * error message cannot be longer than PCAP_ERRBUF_SIZE.
 *
 * \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, uint8 ver, unsigned short errcode, const char *error, 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, ver, RPCAP_MSG_ERROR, errcode, length);

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

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

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

	return 0;
}
Beispiel #4
0
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) == -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) == -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) == -1)
		goto error;

	return 0;

error:
	rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_GETSTATS, fakeerrbuf);
	return -1;
}
Beispiel #5
0
int daemon_updatefilter(pcap_t *fp, uint32 plen)
{
struct rpcap_header header;			// keeps the answer to the updatefilter command
unsigned int nread;

	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, fakeerrbuf) )
		{
			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) )
		goto error;

	return 0;


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

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

	return -1;
}
Beispiel #6
0
/*!
	\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;
}
Beispiel #7
0
/*
	\param plen: the length of the current message (needed in order to be able
	to discard excess data in the message, if present)
*/
pcap_t *daemon_startcapture(SOCKET sockctrl, pthread_t *threaddata, char *source, int active, struct rpcap_sampling *samp_param, uint32 plen, char *errbuf)
{
char portdata[PCAP_BUF_SIZE];		// temp variable needed to derive the data port
char peerhost[PCAP_BUF_SIZE];		// temp variable needed to derive the host name of our peer
pcap_t *fp= NULL;					// pcap_t main variable
unsigned int nread;					// number of bytes of the payload read from the socket
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

// socket-related variables
SOCKET sockdata= 0;					// socket descriptor of the data connection
struct addrinfo hints;				// temp, needed to open a socket connection
struct addrinfo *addrinfo;			// temp, needed to open a socket connection
struct sockaddr_storage saddr;		// temp, needed to retrieve the network data port chosen on the local machine
socklen_t saddrlen;					// temp, needed to retrieve the network data port chosen on the local machine

pthread_attr_t detachedAttribute;	// temp, needed to set the created thread as detached

// RPCAP-related variables
struct rpcap_startcapreq startcapreq;		// start capture request message
struct rpcap_startcapreply *startcapreply;	// start capture reply message
int serveropen_dp;							// keeps who is going to open the data connection

	addrinfo= NULL;

	if ( (nread= sock_recv(sockctrl, (char *) &startcapreq, sizeof(struct rpcap_startcapreq), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
		return NULL;

	startcapreq.flags= ntohs(startcapreq.flags);

	// Open the selected device
	if ( (fp= pcap_open(source, 
			ntohl(startcapreq.snaplen),
			(startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_PROMISC) ? PCAP_OPENFLAG_PROMISCUOUS : 0 /* local device, other flags not needed */, 
			ntohl(startcapreq.read_timeout),
			NULL /* local device, so no auth */,
			errbuf)) == NULL)
	{
		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_OPEN, NULL);
		return NULL;
	}

	// Apply sampling parameters
	fp->rmt_samp.method= samp_param->method;
	fp->rmt_samp.value= samp_param->value;

	/*
	We're in active mode if:
	- we're using TCP, and the user wants us to be in active mode
	- we're using UDP
	*/
	serveropen_dp= (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_SERVEROPEN) || (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) || active;

	/*
	Gets the sockaddr structure referred to the other peer in the ctrl connection

	We need that because:
	- if we're in passive mode, we need to know the address family we want to use 
	(the same used for the ctrl socket)
	- if we're in active mode, we need to know the network address of the other host 
	we want to connect to
	*/
	saddrlen = sizeof(struct sockaddr_storage);
	if (getpeername(sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
	{
		sock_geterror("getpeername(): ", errbuf, PCAP_ERRBUF_SIZE);
		goto error;
	}

	memset(&hints, 0, sizeof(struct addrinfo) );
	hints.ai_socktype = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
	hints.ai_family = saddr.ss_family;

	// Now we have to create a new socket to send packets
	if (serveropen_dp)		// Data connection is opened by the server toward the client
	{
		sprintf(portdata, "%d", ntohs(startcapreq.portdata) );

		// Get the name of the other peer (needed to connect to that specific network address)
		if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, peerhost, 
				sizeof(peerhost), NULL, 0, NI_NUMERICHOST) )
		{
			sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
			goto error;
		}

		if (sock_initaddress(peerhost, portdata, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
			goto error;

		if ( (sockdata= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
			goto error;
	}
	else		// Data connection is opened by the client toward the server
	{
		hints.ai_flags = AI_PASSIVE;

		// Let's the server socket pick up a free network port for us
		if (sock_initaddress(NULL, "0", &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
			goto error;

		if ( (sockdata= sock_open(addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errbuf, PCAP_ERRBUF_SIZE)) == -1)
			goto error;

		// get the complete sockaddr structure used in the data connection
		saddrlen = sizeof(struct sockaddr_storage);
		if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
		{
			sock_geterror("getsockname(): ", errbuf, PCAP_ERRBUF_SIZE);
			goto error;
		}

		// Get the local port the system picked up
		if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, NULL, 
				0, portdata, sizeof(portdata), NI_NUMERICSERV) )
		{
			sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
			goto error;
		}
	}

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

	// save the socket ID for the next calls
	fp->rmt_sockctrl= sockctrl;	// Needed to send an error on the ctrl connection

	// Now I can set the filter
	if ( daemon_unpackapplyfilter(fp, &nread, &plen, errbuf) )
		goto error;


	// Now, I can send a RPCAP start capture reply message
	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_STARTCAP_REPLY, 0, sizeof(struct rpcap_startcapreply) );

	startcapreply= (struct rpcap_startcapreply *) &sendbuf[sendbufidx];
	
	if ( sock_bufferize(NULL, sizeof(struct rpcap_startcapreply), NULL,
		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
		goto error;

	memset(startcapreply, 0, sizeof(struct rpcap_startcapreply) );
	startcapreply->bufsize= htonl(fp->bufsize);

	if (!serveropen_dp)
	{
		unsigned short port = (unsigned short)strtoul(portdata,NULL,10);
		startcapreply->portdata= htons(port);
	}

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

	if (!serveropen_dp)
	{
	SOCKET socktemp;	// We need another socket, since we're going to accept() a connection

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

		socktemp= accept(sockdata, (struct sockaddr *) &saddr, &saddrlen);
		
		if (socktemp == -1)
		{
			sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
			goto error;
		}

		// Now that I accepted the connection, the server socket is no longer needed
		sock_close(sockdata, errbuf, PCAP_ERRBUF_SIZE);
		sockdata= socktemp;
	}

	fp->rmt_sockdata= sockdata;

	/* GV we need this to create the thread as detached. */
	/* GV otherwise, the thread handle is not destroyed  */
	pthread_attr_init(&detachedAttribute); 
	pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
	
	// Now we have to create a new thread to receive packets
	if ( pthread_create(threaddata, &detachedAttribute, (void *) daemon_thrdatamain, (void *) fp) )
	{
		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
		pthread_attr_destroy(&detachedAttribute);
		goto error;
	}

	pthread_attr_destroy(&detachedAttribute);
	// Check if all the data has been read; if not, discard the data in excess
	if (nread != plen)
		sock_discard(sockctrl, plen - nread, NULL, 0);

	return fp;

error:
	rpcap_senderror(sockctrl, errbuf, PCAP_ERR_STARTCAPTURE, NULL);

	if (addrinfo)
		freeaddrinfo(addrinfo);

	if (threaddata)
		pthread_cancel(*threaddata);

	if (sockdata)
		sock_close(sockdata, NULL, 0);

	// Check if all the data has been read; if not, discard the data in excess
	if (nread != plen)
		sock_discard(sockctrl, plen - nread, NULL, 0);

	if (fp)
	{
		pcap_close(fp);
		fp= NULL;
	}

	return NULL;
}
Beispiel #8
0
/*
	\param plen: the length of the current message (needed in order to be able
	to discard excess data in the message, if present)
*/
int daemon_opensource(SOCKET sockctrl, char *source, int srclen, uint32 plen, char *errbuf)
{
pcap_t *fp= NULL;					// pcap_t main variable
unsigned int nread;					// number of bytes of the payload read from the socket
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_openreply *openreply;	// open reply message


	strcpy(source, PCAP_SRC_IF_STRING);

	if (srclen <= (int) (strlen(PCAP_SRC_IF_STRING) + plen) )
	{
		rpcap_senderror(sockctrl, "Source string too long", PCAP_ERR_OPEN, NULL);
		return -1;
	}

	if ( (nread= sock_recv(sockctrl, &source[strlen(PCAP_SRC_IF_STRING)], plen, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
		return -1;

	// Check if all the data has been read; if not, discard the data in excess
	if (nread != plen)
		sock_discard(sockctrl, plen - nread, NULL, 0);

	// Puts a '0' to terminate the source string
	source[strlen(PCAP_SRC_IF_STRING) + plen]= 0;

	// Open the selected device
	// This is a fake open, since we do that only to get the needed parameters, then we close the device again
	if ( (fp= pcap_open(source, 
			1500 /* fake snaplen */,
			0 /* no promis */, 
			1000 /* fake timeout */,
			NULL /* local device, so no auth */,
			errbuf)) == NULL)
	{
		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_OPEN, NULL);
		return -1;
	}


	// Now, I can send a RPCAP open reply message
	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_OPEN_REPLY, 0, sizeof(struct rpcap_openreply) );

	openreply= (struct rpcap_openreply *) &sendbuf[sendbufidx];
	
	if ( sock_bufferize(NULL, sizeof(struct rpcap_openreply), NULL, &sendbufidx, 
		RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
		goto error;

	memset(openreply, 0, sizeof(struct rpcap_openreply) );
	openreply->linktype= htonl(fp->linktype);
	openreply->tzoff= htonl(fp->tzoff);

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

	// I have to close the device again, since it has been opened with wrong parameters
	pcap_close(fp);
	fp= NULL;

	return 0;

error:
	if (fp)
	{
		pcap_close(fp);
		fp= NULL;
	}

	return -1;
}
Beispiel #9
0
// PORTING WARNING We assume u_int is a 32bit value
int daemon_findalldevs(SOCKET sockctrl, 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
pcap_if_t *alldevs;							// pointer to the heade of the interface chain
pcap_if_t *d;								// temp pointer neede to scan the interface chain
uint16 plen= 0;								// length of the payload of this message
struct pcap_addr *address;					// pcap structure that keeps a network address of an interface
struct rpcap_findalldevs_if *findalldevs_if;// rpcap structure that packet all the data of an interface together
uint16 nif= 0;								// counts the number of interface listed

	// Retrieve the device list
	if (pcap_findalldevs(&alldevs, errbuf) == -1)
	{
		rpcap_senderror(sockctrl, errbuf, PCAP_ERR_FINDALLIF, NULL);
		return -1;
	}

	if (alldevs == NULL)
	{
		rpcap_senderror(sockctrl,
			"No interfaces found! Make sure libpcap/WinPcap is properly installed"
			" and you have the right to access to the remote device.",
			PCAP_ERR_NOREMOTEIF, 
			errbuf);
		return -1;
	}

	// checks the number of interfaces and it computes the total length of the payload
	for (d= alldevs; d != NULL; d= d->next)
	{
		nif++;

		if (d->description)
			plen+= strlen(d->description);
		if (d->name)
			plen+= strlen(d->name);

		plen+= sizeof(struct rpcap_findalldevs_if);

		for (address= d->addresses; address != NULL; address= address->next)
			plen+= ( sizeof(struct sockaddr_storage) * 4);
	}

	// RPCAP findalldevs command
	if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 
		&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
		return -1;

	rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_FINDALLIF_REPLY, nif, plen);

	// send the interface list
	for (d= alldevs; d != NULL; d= d->next)
	{
	uint16 lname, ldescr;

		findalldevs_if= (struct rpcap_findalldevs_if *) &sendbuf[sendbufidx];

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

		memset(findalldevs_if, 0, sizeof(struct rpcap_findalldevs_if) );

		if (d->description) ldescr= (short) strlen(d->description);
		else ldescr= 0;
		if (d->name) lname= (short) strlen(d->name);
		else lname= 0;

		findalldevs_if->desclen= htons(ldescr);
		findalldevs_if->namelen= htons(lname);
		findalldevs_if->flags= htonl(d->flags);

		for (address= d->addresses; address != NULL; address= address->next)
			findalldevs_if->naddr++;

		findalldevs_if->naddr= htons(findalldevs_if->naddr);

		if (sock_bufferize(d->name, lname, sendbuf, &sendbufidx, 
			RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
			return -1;

		if (sock_bufferize(d->description, ldescr, sendbuf, &sendbufidx,
			RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
			return -1;

		// send all addresses
		for (address= d->addresses; address != NULL; address= address->next)
		{
		struct sockaddr_storage *sockaddr;

			sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
			if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL, 
				&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
				return -1;
			daemon_seraddr( (struct sockaddr_storage *) address->addr, sockaddr);

			sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
			if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL, 
				&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
				return -1;
			daemon_seraddr( (struct sockaddr_storage *) address->netmask, sockaddr);

			sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
			if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
				&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
				return -1;
			daemon_seraddr( (struct sockaddr_storage *) address->broadaddr, sockaddr);

			sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
			if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
				&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
				return -1;
			daemon_seraddr( (struct sockaddr_storage *) address->dstaddr, sockaddr);
		}
	}

	// Send a final command that says "now send it!"
	if (sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
		return -1;

	// We do no longer need the device list. Free it
	pcap_freealldevs(alldevs);

	// everything is fine
	return 0;
}
Beispiel #10
0
/*!
	\brief It checks if the authentication credentials supplied by the user are valid.

	This function is called each time the rpcap daemon starts a new serving thread.
	It reads the authentication message from the network and it checks that the 
	user information are valid.

	\param sockctrl: the socket if of the control connection.
	
	\param nullAuthAllowed: '1' if the NULL authentication is allowed.

	\param errbuf: a user-allocated buffer in which the error message (if one) has to be written.

	\return '0' if everything is fine, '-1' if an unrecoverable error occurred.
	The error message is returned in the 'errbuf' variable.
	'-2' is returned in case the authentication failed or in case of a recoverable error (like
	wrong version). In that case, 'errbuf' keeps the reason of the failure. This provides
	a way to know that the connection does not have to be closed.

	In case the message is a 'CLOSE' or an 'ERROR', it returns -3. The error can be due to a
	connection refusal in active mode, since this host cannot be allowed to connect to the remote
	peer.
*/
int daemon_checkauth(SOCKET sockctrl, int nullAuthAllowed, char *errbuf)
{
struct rpcap_header header;			// RPCAP message general header
int retval;							// generic return value
unsigned int nread;					// number of bytes of the payload read from the socket
struct rpcap_auth auth;				// RPCAP authentication header
char *string1, *string2;			// two strings exchanged by the authentication message
unsigned int plen;					// length of the payload
int retcode;						// the value we have to return to the caller

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

	plen= ntohl(header.plen);

	retval= rpcap_checkmsg(errbuf, sockctrl, &header,
		RPCAP_MSG_AUTH_REQ,
		RPCAP_MSG_CLOSE,
		0);

	if (retval != RPCAP_MSG_AUTH_REQ)
	{
		switch (retval)
		{
			case -3:	// Unrecoverable network error
				return -1;	// Do nothing; just exit; the error code is already into the errbuf

			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
				return -2;

			case RPCAP_MSG_CLOSE:
			{
				// Check if all the data has been read; if not, discard the data in excess
				if (ntohl(header.plen) )
				{
					if (sock_discard(sockctrl, ntohl(header.plen), NULL, 0) )
					{
						retcode= -1;
						goto error;
					}
				}		
				return -3;
			};

			case RPCAP_MSG_ERROR:
				return -3;

			default:
			{
				SOCK_ASSERT("Internal error.", 1);
				retcode= -2;
				goto error;
			};
		}
	}

	// If it comes here, it means that we have an authentication request message
	if ( (nread= sock_recv(sockctrl, (char *) &auth, sizeof(struct rpcap_auth), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
	{
		retcode= -1;
		goto error;
	}

	switch (ntohs(auth.type) )
	{
		case RPCAP_RMTAUTH_NULL:
		{
			if (!nullAuthAllowed)
			{
				snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed; NULL autentication not permitted.");
				retcode= -2;
				goto error;
			}
			break;
		}

		case RPCAP_RMTAUTH_PWD:
		{
		int len1, len2;

			len1= ntohs(auth.slen1);
			len2= ntohs(auth.slen2);

			string1= (char *) malloc (len1 + 1);
			string2= (char *) malloc (len2 + 1);

			if ( (string1 == NULL) || (string2 == NULL) )
			{
				snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
				retcode= -1;
				goto error;
			}

			if ( (nread+= sock_recv(sockctrl, string1, len1, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
			{
				retcode= -1;
				goto error;
			}
			if ( (nread+= sock_recv(sockctrl, string2, len2, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
			{
				retcode= -1;
				goto error;
			}

			string1[len1]= 0;
			string2[len2]= 0;

			if (daemon_AuthUserPwd(string1, string2, errbuf) )
			{
				retcode= -2;
				goto error;
			}

			break;
			}

		default:
			snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
			retcode= -2;
			goto error;
	}


	// Check if all the data has been read; if not, discard the data in excess
	if (nread != plen)
	{
		if (sock_discard(sockctrl, plen - nread, NULL, 0) )
		{
			retcode= -1;
			goto error;
		}
	}

	rpcap_createhdr(&header, RPCAP_MSG_AUTH_REPLY, 0, 0);

	// Send the ok message back
	if ( sock_send(sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
	{
		retcode= -1;
		goto error;
	}

	return 0;

error:
	// Check if all the data has been read; if not, discard the data in excess
	if (nread != plen)
		sock_discard(sockctrl, plen - nread, NULL, 0);

	return retcode;
}
Beispiel #11
0
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;
}