Author: Gte <gte@atomicrevs.demon.co.uk>
authorBleep <twhelvey1@home.com>
Thu, 13 Apr 2000 02:54:14 +0000 (02:54 +0000)
committerBleep <twhelvey1@home.com>
Thu, 13 Apr 2000 02:54:14 +0000 (02:54 +0000)
Log message:
Add port bouncer to tools directory

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@157 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

ChangeLog
tools/Bounce/Bounce.cpp [new file with mode: 0755]
tools/Bounce/Bounce.h [new file with mode: 0755]
tools/Bounce/bounce.conf [new file with mode: 0644]
tools/Bounce/build [new file with mode: 0755]

index f10aee727dff61f06bd7f57a119a82729aefb11c..da0b3af87e9ed3cc102ff0468a3b2a3428f0f78e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+2000-04-12  Greg Sikorski <gte@atomicrevs.demon.co.uk>
+       * Add port bouncer for http (x/w)
+
 2000-04-12  Kevin L. Mitchell  <klmitch@mit.edu>
 
        * ircd/s_conf.c (find_kill): replaced call to find_gline() with a
 #
 # ChangeLog for ircu2.10.11
 #
-# $Id: ChangeLog,v 1.74 2000-04-13 02:29:53 kev Exp $
+# $Id: ChangeLog,v 1.75 2000-04-13 02:54:14 bleep Exp $
 #
 # Insert new changes at beginning of the change list.
 #
diff --git a/tools/Bounce/Bounce.cpp b/tools/Bounce/Bounce.cpp
new file mode 100755 (executable)
index 0000000..8750967
--- /dev/null
@@ -0,0 +1,311 @@
+#include "Bounce.h"
+
+/*
+ *  Lacking Comments. :)
+ *  12/04/2000 --Gte
+ */
+
+int main() {
+  Bounce* application = new Bounce();
+
+  /*
+   *  Ignore SIGPIPE.
+   */
+  struct sigaction act; 
+  act.sa_handler = SIG_IGN;
+  act.sa_flags = 0;
+  sigemptyset(&act.sa_mask);
+  sigaction(SIGPIPE, &act, 0);
+
+  /*
+   *  Create new application object, bind listeners and begin
+   *  polling them.
+   */
+  application->bindListeners();
+
+  while (1) {
+    application->checkSockets();
+  } 
+}
+
+void Bounce::bindListeners() { 
+  FILE* configFd;
+  char tempBuf[256];
+  int localPort = 0;
+  int remotePort = 0;
+  char* remoteServer;
+  char* vHost; 
+  /*
+   *  Open config File.
+   */
+  
+  if(!(configFd = fopen("bounce.conf", "r")))
+  {
+    printf("Error, unable to open config.\n");
+    exit(0);
+  } 
+
+  while (fgets(tempBuf, 256, configFd) != NULL) { 
+    if((tempBuf[0] != '#') && (tempBuf[0] != '\r')) {
+    switch(tempBuf[0])
+    {
+      case 'P': { /* Add new port listener */ 
+      strtok(tempBuf, ":");
+      vHost = strtok(NULL, ":");
+      localPort = atoi(strtok(NULL, ":"));
+      remoteServer = strtok(NULL, ":");
+      remotePort = atoi(strtok(NULL, ":")); 
+
+      Listener* newListener = new Listener();
+      strcpy(newListener->myVhost, vHost); 
+      strcpy(newListener->remoteServer, remoteServer);
+      newListener->remotePort = remotePort;
+      newListener->localPort = localPort;
+      printf("Adding new Listener: Local: %s:%i, Remote: %s:%i\n", vHost, localPort, remoteServer, remotePort);
+
+      newListener->beginListening();
+      listenerList.insert(listenerList.begin(), newListener); 
+      break;
+      }
+    }
+    } 
+  } 
+}
+
+void Bounce::checkSockets() { 
+/*
+ *  Build up a Select FD set, and Select() 'em.
+ */
+  typedef std::list<Listener*> listenerContainer;
+  typedef listenerContainer::iterator listIter;
+
+  typedef std::list<Connection*> connectionContainer;
+  typedef connectionContainer::iterator connIter; 
+
+  struct timeval tv;
+  fd_set readfds; 
+  tv.tv_sec = 0;
+  tv.tv_usec = 1000;
+  int tempFd = 0;
+  int tempFd2 = 0;
+  int highestFd = 0;
+  int delCheck = 0;
+  char* tempBuf;
+
+  FD_ZERO(&readfds);
+
+  listIter a = listenerList.begin();
+  while(a != listenerList.end())
+  { 
+    tempFd = (*a)->fd; 
+    FD_SET(tempFd, &readfds);
+    if (highestFd < tempFd) highestFd = tempFd;
+    a++;
+  }
+
+  connIter b = connectionsList.begin();
+  while(b != connectionsList.end())
+  { 
+    tempFd = (*b)->localSocket->fd;
+    tempFd2 = (*b)->remoteSocket->fd;
+    FD_SET(tempFd, &readfds);
+    if (highestFd < tempFd) highestFd = tempFd;
+    FD_SET(tempFd2, &readfds);
+    if (highestFd < tempFd2) highestFd = tempFd2;
+    b++;
+  }
+
+  select(highestFd+1, &readfds, NULL, NULL, &tv); 
+
+  /*
+   *  Check all connections for reading/writing
+   *  First check Local FD's.
+   */
+  b = connectionsList.begin();
+  while(b != connectionsList.end())
+  { 
+    tempFd = (*b)->localSocket->fd;
+    if (FD_ISSET(tempFd, &readfds))
+    { 
+      tempBuf = (*b)->localSocket->read();
+      if ((tempBuf[0] == 0)) // Connection closed on one of our sockets.
+      {
+        close((*b)->localSocket->fd);
+        close((*b)->remoteSocket->fd); 
+        printf("Closing FD: %i\n", (*b)->localSocket->fd);
+        printf("Closing FD: %i\n", (*b)->remoteSocket->fd); 
+        delete(*b);
+        delCheck = 1;
+        b = connectionsList.erase(b); 
+      } else {
+        (*b)->remoteSocket->write(tempBuf, (*b)->localSocket->lastReadSize); 
+      }
+    } 
+  if (!delCheck) b++;
+  delCheck = 0;
+  } 
+
+  /*
+   *  Now check Remote FD's..
+   */
+  b = connectionsList.begin();
+  while(b != connectionsList.end())
+  { 
+    tempFd = (*b)->remoteSocket->fd;
+    if (FD_ISSET(tempFd, &readfds))
+    {
+      tempBuf = (*b)->remoteSocket->read();
+      if ((tempBuf[0] == 0)) // Connection closed on one of our sockets.
+      {
+        close((*b)->localSocket->fd);
+        close((*b)->remoteSocket->fd); 
+        printf("Closing FD: %i\n", (*b)->localSocket->fd);
+        printf("Closing FD: %i\n", (*b)->remoteSocket->fd);
+        delete(*b);
+        delCheck = 1;
+        b = connectionsList.erase(b); 
+      } else {
+        (*b)->localSocket->write(tempBuf, (*b)->remoteSocket->lastReadSize);
+      }
+    }
+  if (!delCheck) b++;
+  delCheck = 0;
+  } 
+  /*
+   *  Check all listeners for new connections.
+   */
+  a = listenerList.begin();
+  while(a != listenerList.end())
+  { 
+    tempFd = (*a)->fd; 
+    if (FD_ISSET(tempFd, &readfds))
+    { 
+      recieveNewConnection(*a);
+    }
+    a++;
+  } 
+
+}
+
+void Bounce::recieveNewConnection(Listener* listener)
+{
+  Connection* newConnection = new Connection(); 
+  newConnection->localSocket = listener->handleAccept();
+
+  Socket* remoteSocket = new Socket();
+  newConnection->remoteSocket = remoteSocket; 
+  if(remoteSocket->connectTo(listener->remoteServer, listener->remotePort)) { 
+    connectionsList.insert(connectionsList.begin(), newConnection);
+  } else {
+    newConnection->localSocket->write("Unable to connect to remote host..\n");
+    close(newConnection->localSocket->fd);
+    delete(newConnection);
+    delete(remoteSocket);
+  } 
+}
+Socket* Listener::handleAccept() {
+  int new_fd = 0;
+  int sin_size = sizeof(struct sockaddr_in);
+
+  Socket* newSocket = new Socket();
+  new_fd = accept(fd, (struct sockaddr*)&newSocket->address, (socklen_t*)&sin_size);
+  newSocket->fd = new_fd; 
+  return newSocket;
+}
+void Listener::beginListening() {
+  struct sockaddr_in my_addr;
+  int bindRes;
+  int optval;
+  optval = 1;
+
+  fd = socket(AF_INET, SOCK_STREAM, 0); /* Check for no FD's left?! */
+
+  my_addr.sin_family = AF_INET;
+  my_addr.sin_port = htons(localPort);
+  my_addr.sin_addr.s_addr = inet_addr(myVhost);
+  bzero(&(my_addr.sin_zero), 8);
+
+  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+
+  bindRes = bind(fd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
+  if(bindRes == 0)
+  {
+    listen(fd, 10);
+  } else { 
+     /*
+      *  If we can't bind a listening port, we might aswell drop out.
+      */
+     printf("Unable to bind to %s:%i!\n", myVhost, localPort);
+     exit(0);
+   } 
+}
+
+Socket::Socket() {
+  fd = -1;
+  lastReadSize = 0;
+}
+
+int Socket::write(char *message, int len)
+{ 
+   if (fd == -1) return 0; 
+   int amount = ::write(fd, message, len); 
+   printf("Wrote %i Bytes.\n", amount);
+   return amount; 
+}
+
+int Socket::write(char *message)
+{ 
+   if (fd == -1) return 0; 
+   int amount = ::write(fd, message, strlen(message)); 
+   printf("Wrote %i Bytes.\n", amount);
+   return amount; 
+}
+
+
+int Socket::connectTo(char *hostname, unsigned short portnum) { 
+  struct hostent     *hp;
+  if ((hp = gethostbyname(hostname)) == NULL) { 
+     return 0; 
+  }          
+
+  memset(&address,0,sizeof(address));
+  memcpy((char *)&address.sin_addr,hp->h_addr,hp->h_length);
+  address.sin_family= hp->h_addrtype;
+  address.sin_port= htons((u_short)portnum);
+
+  if ((fd = socket(hp->h_addrtype,SOCK_STREAM,0)) < 0)
+    return 0; 
+  if (connect(fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
+    close(fd);
+    fd = -1; 
+    return 0;
+  } 
+  return(1);
+}
+
+char* Socket::read()
+{ 
+  int amountRead = 0;
+  static char buffer[4096];
+
+  amountRead = ::read(fd, &buffer, 4096);
+
+  if ((amountRead == -1)) buffer[0] = '\0';
+  buffer[amountRead] = '\0';
+
+  printf("Read %i Bytes.\n", amountRead);
+  /* Record this incase we're dealing with binary data with 0's in it. */
+  lastReadSize = amountRead;
+  return (char *)&buffer;
+}
diff --git a/tools/Bounce/Bounce.h b/tools/Bounce/Bounce.h
new file mode 100755 (executable)
index 0000000..5529786
--- /dev/null
@@ -0,0 +1,89 @@
+#include <sys/types.h> 
+#include <sys/time.h>
+#include <sys/wait.h> 
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h> 
+#include <ctype.h>
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <stdio.h> 
+#include <stdlib.h> 
+#include <errno.h> 
+#include <string.h> 
+#include <netdb.h> 
+#include <ctype.h>
+#include <time.h>
+#include <list>
+using std::list; 
+
+
+/*
+ *  "Bounce" Class.
+ */
+
+class Listener;
+class Connection;
+class Bounce
+{
+public:
+  list<Listener*> listenerList; // List of Listeners.
+  list<Connection*> connectionsList; // List of 'Connections'. 
+
+  void bindListeners(); //Binds Listening Ports.
+  void checkSockets(); // Polls all sockets.
+  void recieveNewConnection(Listener*);
+};
+
+/*
+ *  "Socket" Class.
+ */
+
+class Socket 
+{
+public:
+  int fd; 
+  int lastReadSize;
+  struct sockaddr_in address;
+  int connectTo(char*, unsigned short);
+  int write(char*, int); 
+  int write(char*); 
+  char* read();
+  Socket();
+};
+
+/*
+ *  "Listener" Class.
+ */
+
+class Bounce;
+class Listener
+{
+public:
+  int fd; 
+  int remotePort;
+  int localPort;
+  char myVhost[15];
+  char remoteServer[15];
+
+  void beginListening();
+  Socket* handleAccept();
+};
+
+/*
+ *  "Connection" Class.
+ */
+
+class Connection 
+{ 
+public:
+  Socket* localSocket;
+  Socket* remoteSocket;
+};
+
diff --git a/tools/Bounce/bounce.conf b/tools/Bounce/bounce.conf
new file mode 100644 (file)
index 0000000..6b2fbdb
--- /dev/null
@@ -0,0 +1,6 @@
+# Format: P:<Local vhost>:<Local Port>:<Remote Address>:<Remote Port>
+# IP's only for now :)
+
+P:192.168.10.5:2000:192.168.10.1:80
+P:192.168.10.5:3000:4.33.94.3:80
+P:192.168.10.5:4000:209.207.224.42:80
diff --git a/tools/Bounce/build b/tools/Bounce/build
new file mode 100755 (executable)
index 0000000..49f6b05
--- /dev/null
@@ -0,0 +1 @@
+g++ -O3 -ggdb -Wall -Wmissing-declarations -o Bounce Bounce.cpp