Projects/Software/TunTapIO/rawsock.c: Difference between revisions
Jump to navigation
Jump to search
(Nieuwe pagina aangemaakt met '<pre> /********************************************************************** * rsio - raw socket to stdin/out proxy * * Written by: Ivo...') |
m (1 revision imported) |
(No difference)
| |
Latest revision as of 15:49, 9 November 2022
/**********************************************************************
* rsio - raw socket to stdin/out proxy *
* Written by: Ivo Smits <Ivo@UFO-Net.nl> *
* *
* 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) *
* *
**********************************************************************/
#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>
// 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;
#warning "ToDo: add some more protocols from /usr/include/linux/if_ether.h!"
if (linktype == 1) {
fprintf(stderr, "Warning: IP mode does not catch sent packets!\n");
#warning "IP mode does not catch sent packets!"
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);
}
}
//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);
}
#warning "Disable promiscious mode on exit! (signal handler?)"
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");
}
}
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;
}
}
}