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

📄 pcap-remote.c

📁 tcp数据流重放工具
💻 C
📖 第 1 页 / 共 5 页
字号:
			{
				sock_geterror("accept(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
				goto error;
			}

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

	// Let's save the socket of the data connection
	fp->rmt_sockdata= sockdata;

	// Allocates WinPcap/libpcap user buffer, which is a socket buffer in case of a remote capture
	// It has the same size of the one used on the other side of the connection
	fp->bufsize= ntohl(startcapreply.bufsize);

	// Let's get the actual size of the socket buffer
	itemp= sizeof(sockbufsize);

	res= getsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &itemp);
	if (res == -1)
	{
		sock_geterror("pcap_startcapture_remote()", fp->errbuf, PCAP_ERRBUF_SIZE);
		SOCK_ASSERT(fp->errbuf, 1);
	}

	/*
		Warning: on some kernels (e.g. linux), the size of the user buffer does not take
		into account the pcap_header and such, and it is set equal to the snaplen.
		In my view, this is wrong (the meaning of the bufsize becames a bit strange).
		So, here bufsize is the whole size of the user buffer.
		In case the bufsize returned is too small, let's adjust it accordingly.
	*/
	if (fp->bufsize <= fp->snapshot)
		fp->bufsize+= sizeof (struct pcap_pkthdr);

	// if the current socket buffer is smaller than the desired one
	if (sockbufsize < fp->bufsize)
	{
		// Loop until the buffer size is OK or the original socket buffer size is larger than this one
		while (1)
		{
			res= setsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *) &(fp->bufsize), sizeof(fp->bufsize) );

			if (res == 0)
				break;

			// If something goes wrong, half the buffer size (checking that it does not become smaller than
			// the current one)
			fp->bufsize/= 2;

			if (sockbufsize >= fp->bufsize)
			{
				fp->bufsize= sockbufsize;
				break;
			}
		}
	}

	// Let's allocate the packet; this is required in order to put the packet somewhere when 
	// extracting data from the socket
	// Since buffering has already been done in the socket buffer, here we need just a buffer,
	// whose size is equal to the pcap header plus the snapshot length
	fp->bufsize= fp->snapshot + sizeof (struct pcap_pkthdr);

	fp->buffer = (u_char *) malloc(fp->bufsize);
	if (fp->buffer == NULL)
	{
		snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
		goto error;
	}


	// Checks if all the data has been read; if not, discard the data in excess
	if (nread != ntohl(header.plen))
	{
		if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE) == 1)
			goto error;
	}
	return 0;

error:
// When the connection has been established, we have to close it. So, at the
// beginning of this function, if an error occur we return immediately with
// a return NULL; when the connection is established, we have to come here 
// ('goto error;') in order to close everything properly.

	// Checks if all the data has been read; if not, discard the data in excess
	if (nread != ntohl(header.plen))
		sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE);

	if ((sockdata) && (sockdata != -1))		// we can be here because sockdata said 'error'
		sock_close(sockdata, fakeerrbuf, PCAP_ERRBUF_SIZE);

	if (!active)
		sock_close(fp->rmt_sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE);

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

	return -1;
}





/*!
	\brief Takes a bpf program and sends it to the other host.

	This function can be called in two cases:
	- the pcap_startcapture() is called (we have to send the filter along with
	the 'start capture' command)
	- we want to udpate the filter during a capture (i.e. the pcap_setfilter()
	is called when the capture is still on)

	This function serializes the filter into the sending buffer ('sendbuf', passed
	as a parameter) and return back. It does not send anything on the network.

	\param fp: the pcap_t descriptor of the device currently opened.

	\param sendbuf: the buffer on which the serialized data has to copied.

	\param sendbufidx: it is used to return the abounf of bytes copied into the buffer.

	\param prog: the bpf prgoram we hve to copy.

	\return '0' if everything is fine, '-1' otherwise. The error message (if one)
	is returned into the 'errbuf' field of the pcap_t structure.
*/
int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog)
{
struct rpcap_filter *filter;
struct rpcap_filterbpf_insn *insn;
struct bpf_insn *bf_insn;
unsigned int i;

	filter= (struct rpcap_filter *) sendbuf;

	if ( sock_bufferize(NULL, sizeof(struct rpcap_filter), NULL, sendbufidx, 
		RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) )
		return -1;

	filter->filtertype= htons(RPCAP_UPDATEFILTER_BPF);
	filter->nitems= htonl( (int32) prog->bf_len);

	if ( sock_bufferize(NULL, prog->bf_len * sizeof(struct rpcap_filterbpf_insn), 
		NULL, sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) )
		return -1;
	
	insn= (struct rpcap_filterbpf_insn *) (filter + 1);
	bf_insn= prog->bf_insns;

	for (i= 0; i < prog->bf_len; i++)
	{
		insn->code= htons(bf_insn->code);
		insn->jf= bf_insn->jf;
		insn->jt= bf_insn->jt;
		insn->k= htonl(bf_insn->k);

		insn++;
		bf_insn++;
	}
	return 0;
}





/*!	\ingroup remote_pri_func

	\brief Update a filter on a remote host.

	This function is called when the user wants to update a filter.
	In case we're capturing from the network, it sends the filter to the other peer.
	This function is *not* called automatically when the user calls the pcap_setfilter().
	There will be two cases:
	- the capture is already on: in this case, pcap_setfilter() calls pcap_updatefilter_remote()
	- the capture has not started yet: in this case, pcap_setfilter() stores the filter into
	the pcap_t structure, and then the filter is sent with the pcap_startcap().

	Parameters and return values are exactly the same of the pcap_setfilter().

	\warning This function *does not* clear the packet currently into the buffers. Therefore,
	the user has to expect to receive some packets that are related to the previous filter.
	If you want to discard all the packets before applying a new filter, you have to close 
	the current capture session and start a new one.
*/
int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog)
{
int retval;						// general variable used to keep the return value of other functions
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_header header;		// To keep the reply message


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

	rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_UPDATEFILTER_REQ, 0,
		sizeof(struct rpcap_filter) + prog->bf_len * sizeof(struct rpcap_filterbpf_insn));

	if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, prog) )
		return -1;

	if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) )
		return -1;

	// Waits for the answer
	if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
		return -1;

	// Checks if the message is correct
	retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0);

	if (retval != RPCAP_MSG_UPDATEFILTER_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;

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

	if (ntohl(header.plen) != 0)	// the message has an unexpected size
	{
		if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen), fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
			return -1;
	}

	return 0;
}




/*!
	\ingroup remote_pri_func

	\brief Send a filter to a remote host.

	This function is called when the user wants to set a filter.
	In case we're capturing from the network, it sends the filter to the other peer.
	This function is called automatically when the user calls the pcap_setfilter().

	Parameters and return values are exactly the same of the pcap_setfilter().
*/
int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog)
{
	if (!fp->rmt_capstarted)
	{
		// copy filter into the pcap_t structure
		if (install_bpf_program(fp, prog) == -1)
			return -1;
		return 0;
	}

	// we have to update a filter during run-time
	if (pcap_updatefilter_remote(fp, prog) )
		return -1;

	return 0;
}



/*!
	\ingroup remote_pri_func

	\brief Set sampling parameters in the remote host.

	This function is called when the user wants to set activate sampling on the remote host.

	Sampling parameters are defined into the 'pcap_t' structure.

	\param fp: the pcap_t descriptor of the device currently opened.

	\return '0' if everything is OK, '-1' is something goes wrong. The error message is returned
	in the 'errbuf' member of the pcap_t structure.
*/
int pcap_setsampling_remote(pcap_t *p)
{
int retval;						// general variable used to keep the return value of other functions
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_header header;		// To keep the reply message
struct rpcap_sampling *sampling_pars;	// Structure that is needed to send sampling parameters to the remote host

	// If no samping is requested, return 'ok'
	if (p->rmt_samp.method == PCAP_SAMP_NOSAMP)
		return 0;

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

	rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_SETSAMPLING_REQ, 0, sizeof(struct rpcap_sampling) );

	// Fill the structure needed to open an adapter remotely
	sampling_pars= (struct rpcap_sampling *) &sendbuf[sendbufidx];

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

	memset(sampling_pars, 0, sizeof(struct rpcap_sampling) );

	sampling_pars->method= p->rmt_samp.method;
	sampling_pars->value= htonl(p->rmt_samp.value);

	if ( sock_send(p->rmt_sockctrl, sendbuf, sendbufidx, p->errbuf, PCAP_ERRBUF_SIZE) )
		return -1;

	// Waits for the answer
	if (sock_recv(p->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
		return -1;

	// Checks if the message is correct
	retval= rpcap_checkmsg(p->errbuf, p->rmt_sockctrl, &header, RPCAP_MSG_SETSAMPLING_REPLY, 0);

	if (retval != RPCAP_MSG_SETSAMPLING_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
			case RPCAP_MSG_ERROR:
				// Do nothing; just exit from here; the error code is already into the errbuf
				return -1;

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

	if (ntohl(header.plen) != 0)	// the message has an unexpected size
	{
		if (sock_discard(p->rmt_sockctrl, ntohl(header.plen), p->errbuf, PCAP_ERRBUF_SIZE) == -1)
			return -1;
	}

	return 0;

}



⌨️ 快捷键说明

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