Projects/Software/TunTapIO/rawsock.c

/**********************************************************************
 * rsio - raw socket to stdin/out proxy                               *
 * Written by: Ivo Smits                              *
 * Compile using: gcc rawsock.c -o rsio                               *
 * Many thanks to:                                                    *
 * - http://www.blug.linux.no/rfc1149/                               *
 * - http://linux.about.com/od/commands/l/blcmdl2_select.htm         *
 * - http://bochs.sourceforge.net/ (the iodev/eth_linux.cc module)   *
 * - http://linux.about.com/od/commands/l/blcmdl2_select.htm         *
 * - http://bochs.sourceforge.net/ (the iodev/eth_linux.cc module)   *

#include 
 * 1) include 
 * 2) include 
 * 3) include 
 * 4) include 
 * 5) ifndef HAVE_NETINET_IN_H
 * 1) endif


 * 1) include 


 * 1) include 
 * 2) include 


 * 1) include 
 * 2) include 
 * 3) include 
 * 4) include 
 * 5) include 
 * 6) include 
 * 7) include 
 * 8) include <linux/types.h>
 * 9) include <linux/filter.h>
 * 10) include <linux/if_ether.h>

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

//Parse command line arguments if (argc > 1) { if (strcmp(argv[1], "-h") == 0) { fprintf(stderr, "rsio - raw socket to stdio proxy\n"); fprintf(stderr, "Usage: %s INTF [-raw|-ip] [CLEN] [-prom]\n", argv[0]); fprintf(stderr, " INTF:  the name of the network interface to connect to\n"); fprintf(stderr, " -raw:  raw ethernet communication (default)\n"); fprintf(stderr, " -tun:  IP level communication\n"); fprintf(stderr, " CLEN:  capture size (should be the same as the mtu, default: %d)\n", ETH_FRAME_LEN); fprintf(stderr, " -prom: enable promiscious mode (warning, won't be disabled)\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 sock; //The socket

int CaptureLen = ETH_FRAME_LEN; {		int linktype = 0; //Default to ethernet packets (0=ethernet, 1=IP) if (argc > 2 && strcmp(argv[2], "-ip") == 0) linktype = 1;

if (linktype == 1) CaptureLen = ETH_DATA_LEN;

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

//Open the socket! int socktype, sockproto; if (linktype == 1) { fprintf(stderr, "Warning: IP mode does not catch sent packets!\n"); socktype = SOCK_DGRAM; sockproto = htons(ETH_P_IP); } else { socktype = SOCK_RAW; sockproto = htons(ETH_P_ALL); }		if ((sock = socket(PF_PACKET, socktype, sockproto)) == -1) { fprintf(stderr, "Failed to create socket: %s\n", strerror(errno)); exit(1); }	}
 * 1) warning "ToDo: add some more protocols from /usr/include/linux/if_ether.h!"
 * 1) warning "IP mode does not catch sent packets!"

//Bind to given interface by name {		const char *dev; //Device to connect to		strcpy(dev, argv[1]);

//Translate interface name to index struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, dev); if (ioctl(sock, SIOCGIFINDEX, &ifr) == -1) { fprintf(stderr, "Failed to get index for interface: '%s'\n", dev); close(sock); exit(1); }

// Bind to given interface struct sockaddr_ll sll; memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = ifr.ifr_ifindex; if (bind(sock, (struct sockaddr *)&sll, (socklen_t)sizeof(sll)) == -1) { fprintf(stderr, "Could not bind to interface '%s': %s\n", dev, strerror(errno)); close(sock); exit(1); }

if (argc > 5 && strcmp(argv[5], "-prom") == 0) { register int Ret; if (Ret = ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { fprintf(stderr, "Failed to get interface flags: '%s'\n", Ret); close(sock); exit(1); }			ifr.ifr_flags |= IFF_PROMISC; if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) { fprintf(stderr, "Failed to set interface flags for promisc mode: '%s'\n", Ret); close(sock); exit(1); }			fprintf(stderr, "Promiscious mode enabled!\n"); }	}
 * 1) warning "Disable promiscious mode on exit! (signal handler?)"

fprintf(stderr, "Proxy ready for action!\n");

fd_set fdsRead, fdsWrite; //FileDescriptor sets for select unsigned char RBuf[CaptureLen], WBuf[CaptureLen]; //Data buffers int RBufLen = 0, WBufLen = 0; //Packet length int PLen; //Start an infinite loop while (1) { if (WBufLen < 0 || RBufLen < 0) { fprintf(stderr, "WBufLen < 0 or RBufLen < 0 :|\n"); exit(2); }

FD_ZERO(&fdsRead);			//Clear FD set if (RBufLen == 0) FD_SET(sock, &fdsRead);	//Add socket if (WBufLen == 0) FD_SET(0, &fdsRead);		//Add stdin

FD_ZERO(&fdsWrite);			//Clear FD set if (WBufLen > 0) FD_SET(sock, &fdsWrite);	//Add socket if (RBufLen > 0) FD_SET(1, &fdsWrite);		//Add stdout

if (select(sock + 1, &fdsRead, &fdsWrite, NULL, NULL) < 0) { if (errno == EAGAIN || errno == EINTR) { continue; //Retry select } else { fprintf(stderr, "An unhandled error occured in select: %d", errno); exit(5); }		}

//Read from socket if (FD_ISSET(sock, &fdsRead) && RBufLen == 0) { RBufLen = read(sock, RBuf, CaptureLen); if (RBufLen == 0) { fprintf(stderr, "End of file on socket\n"); exit(0); } else if (RBufLen < 0) { fprintf(stderr, "Some error occured while reading from socket: %d\n", RBufLen); exit(4); }			if (DumpStats != 0) fprintf(stderr, "R: %d\n", RBufLen); }		//Write to socket if (FD_ISSET(sock, &fdsWrite) && WBufLen > 0) { write(sock, WBuf, WBufLen); if (DumpStats != 0) fprintf(stderr, "W: %d\n", WBufLen); WBufLen = 0; }

//Read from stdin (FD 0) if (FD_ISSET(0, &fdsRead) && WBufLen == 0) { if (IncludePLen == 1) { WBufLen = read(0, &PLen, 4); }			if (IncludePLen == 0 || PLen > CaptureLen) { PLen = CaptureLen; }			if (IncludePLen == 0 || WBufLen > 0) { WBufLen = read(0, WBuf, PLen); }			if (WBufLen == 0) { fprintf(stderr, "End of file on stdin\n"); exit(0); } else if (WBufLen < 0) { fprintf(stderr, "Some error occured while reading stdin: %d\n", WBufLen); exit(4); }		}		//Write to stdout (FD 1) if (FD_ISSET(1, &fdsWrite) && RBufLen > 0) { if (IncludePLen == 1) write(1, &RBufLen, 4); write(1, RBuf, RBufLen); RBufLen = 0; }	} }