Projects/Software/TunTapIO/pcap.c

From Qontrol.nl Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
/**********************************************************************
* rsfio - filtered raw socket to stdin/out proxy                      *
* Written by: Ivo Smits <Ivo@UFO-Net.nl>                              *
*                                                                     *
* Compile using: gcc pcap.c -o lpcio -lpcap                           *
*                                                                     *
* Many thanks to:                                                     *
*  - http://www.blug.linux.no/rfc1149/                                *
*  - http://linux.about.com/od/commands/l/blcmdl2_select.htm          *
*  - http://www.linuxjournal.com/article/4659                         *
*  - http://www.tcpdump.org/pcap.htm                                  *
*  - http://www.winpcap.org/docs/man/html/                            *
*  - http://www.tcpdump.org/lists/workers/2005/06/msg00102.html       *
*                                                                     *
**********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h> 
#ifndef HAVE_NETINET_IN_H
	#include <netinet/in.h>
#endif

#include <sys/ioctl.h>

#include <errno.h>
#include <dirent.h>

#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <linux/types.h>
#include <linux/filter.h>
#include <linux/if_ether.h>

#include <pcap.h>

int DumpStats = 1;
int IncludePLen = 1;

void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);

// The main program, this is where all the magic happens
int main(int argc, char** argv) {

	//Parse command line arguments
	if (argc > 1) {
		if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
			fprintf(stderr, "rsio - raw socket to stdio proxy\n");
			fprintf(stderr, "Usage: %s INTF [CLEN] [FILTR]\n", argv[0]);
			fprintf(stderr, "  INTF:  the name of the network interface to connect to\n");
			fprintf(stderr, "  CLEN:  capture size (should be the same as the mtu, default: %d)\n", ETH_FRAME_LEN);
			fprintf(stderr, "  FILTR: tcpdump style filter expression (man tcpdump)\n");
			fprintf(stderr, "Note that the arguments should be in exactly THIS order.\n");
			fprintf(stderr, "Report bugs to <Ivo@UFO-Net.nl>\n");
			exit(0);
		}
	} else {
		//Application won't run without arguments
		//fprintf(stderr, "Try: %s -h\n", argv[0]);
		//exit(1);
	}

	int CaptureLen = ETH_FRAME_LEN;
	//Different capture length?
	if (argc > 2) CaptureLen = atoi(argv[2]);
	if (CaptureLen < 1) {
		fprintf(stderr, "Capture length %d invalid!\n", CaptureLen);
		exit(1);
	}
	fprintf(stderr, "Max packet length: %d\n", CaptureLen);

	char *dev, errbuf[PCAP_ERRBUF_SIZE];

	if (argc > 1) {
		dev = argv[1];
	} else {
		if ((dev = pcap_lookupdev(errbuf)) == NULL) {
			fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
			exit(1);
		}
	}
	fprintf(stderr, "Device: %s\n", dev);

	pcap_t *pcap;
	if ((pcap = pcap_open_live(dev, CaptureLen, 1, 0, errbuf)) == NULL) {
		fprintf(stderr, "Couldn't open device: %s\n", errbuf);
		exit(1);
	}

	if (argc > 3) {
		fprintf(stderr, "Filter: %s\n", argv[3]);
		struct bpf_program *bpfprog;
		if (pcap_compile(pcap, &bpfprog, argv[3], 0, 0) == -1) {
			fprintf(stderr, "Couldn't compile filter: %s\n", pcap_geterr(pcap));
			exit(1);
		}
		
		if (pcap_setfilter(pcap, &bpfprog) == -1) {
			fprintf(stderr, "Couldn't install filter: %s\n", pcap_geterr(pcap));
			exit(1);
		}
	}

	fprintf(stderr, "Starting capture!\n");
	pcap_loop(pcap, -1, got_packet, NULL);

	fprintf(stderr, "PCap finished: shutting down!\n");
	pcap_close(pcap);
}

void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
	if (DumpStats != 0) fprintf(stderr, "R: %d\n", header->caplen);
	if (IncludePLen == 1) write(1, &header->caplen, 4);
	write(1, packet, header->caplen);
}