Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

tcpproxy.cc

Go to the documentation of this file.
00001 /****************************************************************************
00002 * File: tcpproxy.cc
00003 ****************************************************************************/
00004 
00005 #include "rcs_defs.hh"          /* EXTERN_C_STD_HEADERS */
00006 #include "sokintrf.h"           /* dl_ioctl() */
00007 #include "linklist.hh"          /* RCS_LINKED_LIST */
00008 #include "rcs_prnt.hh"          /* rcs_print_error() */
00009 #include "tcp_opts.hh"          /* SET_TCP_NODELAY */
00010 
00011 
00012 #ifdef EXTERN_C_STD_HEADERS
00013 extern "C"
00014 {
00015 #endif
00016 
00017 #include <string.h>             /* memset(), strerror() */
00018 #include <errno.h>              /* errno */
00019 #include <signal.h>             // SIGPIPE, signal()
00020 #include <stdlib.h>             // strtol()
00021 
00022 #ifdef EXTERN_C_STD_HEADERS
00023 }
00024 #endif
00025 
00026 
00027 extern "C"
00028 {
00029 #include "recvn.h"              /* recvn() */
00030 #include "sendn.h"              /* sendn() */
00031 }
00032 
00033 class TCP_PROXY_ENTRY
00034 {
00035 public:
00036   SOCKET client_socket;
00037   SOCKET server_socket;
00038   struct sockaddr_in client_address;
00039 };
00040 
00041 static int last_pipe_error_id = 0;
00042 
00043 static void
00044 handle_pipe_error (int id)
00045 {
00046   last_pipe_error_id = id;
00047   rcs_print_error ("SIGPIPE intercepted.\n");
00048 }
00049 
00050 int tcpproxy_quit = 0;
00051 static int last_sigint_id = 0;
00052 
00053 static void
00054 handle_sigint (int id)
00055 {
00056   last_sigint_id = id;
00057   tcpproxy_quit = 1;
00058 }
00059 
00060 #ifndef VXWORKS
00061 struct hostent *server_host_entry;
00062 #endif
00063 
00064 
00065 #ifdef VXWORKS
00066 extern "C" int tcpproxy (long local_port, char *remote_host,
00067                          long remote_port);
00068 
00069 int
00070 tcpproxy (long local_port, char *remote_host, long remote_port)
00071 {
00072 #else
00073 
00074 int
00075 main (int argc, char **argv)
00076 {
00077   set_rcs_print_destination (RCS_PRINT_TO_STDOUT);
00078 
00079   if (argc < 3)
00080     {
00081       rcs_print_error ("insufficient arguments (%d)\n", argc);
00082       rcs_print_error
00083         ("usage: tcpproxy local-port remote-host [remote-port]\n");
00084       rcs_print_error ("  Some interesting ports to try:\n");
00085       rcs_print_error ("    \tEcho:   \t7\n");
00086       rcs_print_error ("    \tFTP:    \t21\n");
00087       rcs_print_error ("    \tTelnet: \t23\n");
00088       rcs_print_error ("    \tHTTP:   \t80\n");
00089       exit (-1);
00090     }
00091 
00092   long local_port = strtol (argv[1], NULL, 0);
00093   char *remote_host = argv[2];
00094   long remote_port = 0;
00095 
00096 
00097   if (argc > 3)
00098     {
00099       remote_port = strtol (argv[3], NULL, 0);
00100     }
00101   else
00102     {
00103       remote_port = local_port;
00104     }
00105 
00106 #endif
00107 
00108   RCS_LINKED_LIST *proxy_sockets = NULL;
00109   struct sockaddr_in proxy_socket_address;
00110   struct sockaddr_in proxy_client_socket_address;
00111   struct sockaddr_in server_socket_address;
00112 
00113   if (load_socket_interface () < 0)
00114     {
00115       rcs_print_error ("Can't load socket interface.\n");
00116       exit (-1);
00117     }
00118   proxy_sockets = new RCS_LINKED_LIST;
00119 
00120 
00121   /* Get the IP address of the server using it's remote_host. */
00122   server_socket_address.sin_family = AF_INET;
00123 #ifndef VXWORKS
00124   dl_gethostbyname (remote_host, &server_host_entry);
00125   if (NULL == server_host_entry)
00126     {
00127       rcs_print_error ("Couldn't get host address for (%s).\n", remote_host);
00128 #if defined(_WINDOWS)
00129       rcs_print_error ("WSA error = %d\n", dl_WSAGetLastError ());
00130 #endif
00131       exit (-1);
00132     }
00133 #ifdef __MSDOS__
00134   server_socket_address.sin_addr.s_addr =
00135     *((u_long *) server_host_entry->h_addr_list[0]);
00136 #else
00137   server_socket_address.sin_addr.s_addr =
00138     *((int *) server_host_entry->h_addr_list[0]);
00139 #endif
00140 #else
00141   server_socket_address.sin_addr.s_addr = hostGetByName (remote_host);
00142   if (server_socket_address.sin_addr.s_addr == ERROR)
00143     {
00144       rcs_print_error ("TCPMEM: Couldn't get host address for (%s).\n",
00145                        remote_host);
00146       exit (-1);
00147     }
00148 #endif
00149   server_socket_address.sin_port = dl_htons ((unsigned short) remote_port);
00150 
00151   memset (&proxy_socket_address, 0, sizeof (proxy_socket_address));
00152   proxy_socket_address.sin_family = AF_INET;
00153   proxy_socket_address.sin_addr.s_addr = dl_htonl (INADDR_ANY);
00154   proxy_socket_address.sin_port = dl_htons (local_port);
00155 
00156   rcs_print_debug (PRINT_CMS_CONFIG_INFO,
00157                    "Registering server on TCP port %d.\n",
00158                    dl_ntohs (proxy_socket_address.sin_port));
00159   if (proxy_socket_address.sin_port == 0)
00160     {
00161       rcs_print_error ("server can not register on port number 0.\n");
00162       exit (-1);
00163     }
00164   SOCKET connection_socket;
00165 
00166   if ((long) (connection_socket = dl_socket (AF_INET, SOCK_STREAM, 0)) <= 0)
00167     {
00168       rcs_print_error ("socket error: %d -- %s\n", errno, strerror (errno));
00169       rcs_print_error ("Server can not open stream socket.\n");
00170       exit (-1);
00171     }
00172 
00173   if (set_tcp_socket_options (connection_socket) < 0)
00174     {
00175       exit (-1);
00176     }
00177   if (dl_bind (connection_socket, (struct sockaddr *) &proxy_socket_address,
00178                sizeof (proxy_socket_address)) < 0)
00179     {
00180       rcs_print_error ("bind error: %d -- %s\n", errno, strerror (errno));
00181       rcs_print_error
00182         ("Server can not bind the connection socket on port %d.\n",
00183          dl_ntohs (proxy_socket_address.sin_port));
00184       exit (-1);
00185     }
00186   if (dl_listen (connection_socket, 5) < 0)
00187     {
00188       rcs_print_error ("listen error: %d -- %s\n", errno, strerror (errno));
00189       rcs_print_error ("TCP Server: error on call to listen for port %d.\n",
00190                        dl_ntohs (server_socket_address.sin_port));
00191       exit (-1);
00192     }
00193 
00194   unsigned long bytes_ready;
00195   int ready_descriptors;
00196   fd_set read_fd_set, write_fd_set;
00197   FD_ZERO (&read_fd_set);
00198   FD_ZERO (&write_fd_set);
00199   RCS_FD_SET (connection_socket, &read_fd_set);
00200   SOCKET maxfdpl;
00201   maxfdpl = connection_socket + 1;
00202   TCP_PROXY_ENTRY *current_entry;
00203 
00204 #ifndef DOS_WINDOWS
00205   signal (SIGPIPE, handle_pipe_error);
00206 #endif
00207   signal (SIGINT, handle_sigint);
00208   rcs_print
00209     ("Running TCP proxy  for:\n (TCP port %d) \n(connection_socket = %d)\n(remote_host = %s)\n(server_IP_address = %s)\n(remote_port = %d)",
00210      dl_ntohs (proxy_socket_address.sin_port), connection_socket, remote_host,
00211      dl_inet_ntoa (server_socket_address.sin_addr), remote_port);
00212 
00213   char temp_buffer[4096];
00214 
00215   while (!tcpproxy_quit)
00216     {
00217       ready_descriptors =
00218         dl_select (maxfdpl,
00219                    &read_fd_set,
00220                    &write_fd_set, (fd_set *) NULL, (timeval *) NULL);
00221       if (ready_descriptors < 0)
00222         {
00223           rcs_print_error
00224             ("select(%d,%d,%d,NULL,NULL) error.(errno = %d | %s)\n", maxfdpl,
00225              read_fd_set, write_fd_set, errno, strerror (errno));
00226           continue;
00227         }
00228       current_entry = (TCP_PROXY_ENTRY *) proxy_sockets->get_head ();
00229       while (NULL != current_entry)
00230         {
00231           if (dl_fd_isset (current_entry->client_socket, &read_fd_set))
00232             {
00233               ready_descriptors--;
00234               dl_ioctlsocket (current_entry->client_socket, FIONREAD,
00235                               &bytes_ready);
00236               if (bytes_ready == 0)
00237                 {
00238                   rcs_print ("Socket closed by host with IP address %s.\n",
00239                              dl_inet_ntoa (current_entry->client_address.
00240                                            sin_addr));
00241                   dl_closesocket (current_entry->server_socket);
00242                   dl_closesocket (current_entry->client_socket);
00243                   if (dl_fd_isset
00244                       (current_entry->server_socket, &read_fd_set))
00245                     {
00246                       RCS_FD_CLR (current_entry->server_socket, &read_fd_set);
00247                     }
00248                   if (dl_fd_isset
00249                       (current_entry->client_socket, &read_fd_set))
00250                     {
00251                       RCS_FD_CLR (current_entry->client_socket, &read_fd_set);
00252                     }
00253                   proxy_sockets->delete_current_node ();
00254                   current_entry =
00255                     (TCP_PROXY_ENTRY *) proxy_sockets->get_next ();
00256                   continue;
00257                 }
00258               else
00259                 {
00260                   while (bytes_ready > 0)
00261                     {
00262                       if (bytes_ready > 4096)
00263                         {
00264                           recvn (current_entry->client_socket, temp_buffer,
00265                                  4096, 0, -1, NULL);
00266                           sendn (current_entry->server_socket, temp_buffer,
00267                                  4096, 0, -1);
00268                           bytes_ready -= 4096;
00269                         }
00270                       else
00271                         {
00272                           recvn (current_entry->client_socket, temp_buffer,
00273                                  bytes_ready, 0, -1, NULL);
00274                           sendn (current_entry->server_socket, temp_buffer,
00275                                  bytes_ready, 0, -1);
00276                           bytes_ready = 0;
00277                           break;
00278                         }
00279                     }
00280                 }
00281             }
00282           else
00283             {
00284               RCS_FD_SET (current_entry->client_socket, &read_fd_set);
00285             }
00286           if (dl_fd_isset (current_entry->server_socket, &read_fd_set))
00287             {
00288               ready_descriptors--;
00289 #ifdef WIN32
00290               dl_ioctlsocket (current_entry->server_socket, FIONREAD,
00291                               &bytes_ready);
00292 #else
00293 #ifndef VXWORKS
00294               ioctl (current_entry->server_socket, FIONREAD,
00295                      (caddr_t) & bytes_ready);
00296 #else
00297               ioctl (current_entry->server_socket, FIONREAD,
00298                      (int) &bytes_ready);
00299 #endif
00300 #endif
00301               if (bytes_ready == 0)
00302                 {
00303                   rcs_print ("Socket closed by host with IP address %s.\n",
00304                              dl_inet_ntoa (server_socket_address.sin_addr));
00305                   dl_closesocket (current_entry->server_socket);
00306                   dl_closesocket (current_entry->client_socket);
00307                   if (dl_fd_isset
00308                       (current_entry->server_socket, &read_fd_set))
00309                     {
00310                       RCS_FD_CLR (current_entry->server_socket, &read_fd_set);
00311                     }
00312                   if (dl_fd_isset
00313                       (current_entry->client_socket, &read_fd_set))
00314                     {
00315                       RCS_FD_CLR (current_entry->client_socket, &read_fd_set);
00316                     }
00317                   proxy_sockets->delete_current_node ();
00318                   current_entry =
00319                     (TCP_PROXY_ENTRY *) proxy_sockets->get_next ();
00320                   continue;
00321                 }
00322               else
00323                 {
00324                   while (bytes_ready > 0)
00325                     {
00326                       if (bytes_ready > 4096)
00327                         {
00328                           recvn (current_entry->server_socket, temp_buffer,
00329                                  4096, 0, -1, NULL);
00330                           sendn (current_entry->client_socket, temp_buffer,
00331                                  4096, 0, -1);
00332                           bytes_ready -= 4096;
00333                         }
00334                       else
00335                         {
00336                           recvn (current_entry->server_socket, temp_buffer,
00337                                  bytes_ready, 0, -1, NULL);
00338                           sendn (current_entry->client_socket, temp_buffer,
00339                                  bytes_ready, 0, -1);
00340                           bytes_ready = 0;
00341                           break;
00342                         }
00343                     }
00344                 }
00345             }
00346           else
00347             {
00348               RCS_FD_SET (current_entry->server_socket, &read_fd_set);
00349             }
00350           current_entry = (TCP_PROXY_ENTRY *) proxy_sockets->get_next ();
00351         }
00352       if (dl_fd_isset (connection_socket, &read_fd_set)
00353           && ready_descriptors > 0)
00354         {
00355           ready_descriptors--;
00356           current_entry = new TCP_PROXY_ENTRY;
00357           if (NULL == current_entry)
00358             {
00359               continue;
00360             }
00361           current_entry->server_socket = dl_socket (AF_INET, SOCK_STREAM, 0);
00362           if (((long) current_entry->server_socket) <= 0)
00363             {
00364               rcs_print_error ("Error from socket() (errno = %d:%s)\n",
00365                                errno, strerror (errno));
00366               delete current_entry;
00367               continue;
00368             }
00369           proxy_client_socket_address.sin_family = AF_INET;
00370           proxy_client_socket_address.sin_addr.s_addr = dl_htonl (INADDR_ANY);
00371           proxy_client_socket_address.sin_port = dl_htons (0);
00372 
00373           if (dl_bind (current_entry->server_socket,
00374                        (struct sockaddr *) &proxy_client_socket_address,
00375                        sizeof (proxy_client_socket_address)) < 0)
00376             {
00377 #if defined(_Windows) && !defined(USE_PCNFS)
00378               rcs_print_error (" bind error %d\n", dl_WSAGetLastError ());
00379 #else
00380               rcs_print_error (" bind error %d = %s\n", errno,
00381                                strerror (errno));
00382 #endif
00383               delete current_entry;
00384               continue;
00385             }
00386           if (dl_connect (current_entry->server_socket,
00387                           (struct sockaddr *) &server_socket_address,
00388                           sizeof (server_socket_address)) < 0)
00389             {
00390 #if defined(_WINDOWS) && !defined(USE_PCNFS)
00391               rcs_print_error ("Couldn't connect. Error = (%d)\n",
00392                                dl_WSAGetLastError ());
00393 #else
00394               rcs_print_error ("Couldn't connect. Error = (%d:%s)\n",
00395                                errno, strerror (errno));
00396 #endif
00397               delete current_entry;
00398               current_entry = NULL;
00399               continue;
00400             }
00401           int client_address_length;
00402           client_address_length = sizeof (current_entry->client_address);
00403           current_entry->client_socket = dl_accept (connection_socket,
00404                                                     (struct sockaddr *)
00405                                                     &
00406                                                     (current_entry->
00407                                                      client_address),
00408                                                     &client_address_length);
00409           if (((long) current_entry->client_socket) <= 0)
00410             {
00411 #if defined(_WINDOWS) && !defined(USE_PCNFS)
00412               rcs_print_error ("accept error = (%d)\n",
00413                                dl_WSAGetLastError ());
00414 #else
00415               rcs_print_error ("accept error = (%d:%s)\n",
00416                                errno, strerror (errno));
00417 #endif
00418               continue;
00419             }
00420           rcs_print ("Socket opened by host with IP address %s.\n",
00421                      dl_inet_ntoa (current_entry->client_address.sin_addr));
00422           if (NULL != proxy_sockets)
00423             {
00424               proxy_sockets->store_at_tail (current_entry,
00425                                             sizeof (TCP_PROXY_ENTRY), 0);
00426             }
00427           if (maxfdpl < current_entry->client_socket + 1)
00428             {
00429               maxfdpl = current_entry->client_socket + 1;
00430             }
00431           if (maxfdpl < current_entry->server_socket + 1)
00432             {
00433               maxfdpl = current_entry->server_socket + 1;
00434             }
00435           RCS_FD_SET (current_entry->server_socket, &read_fd_set);
00436           RCS_FD_SET (current_entry->client_socket, &read_fd_set);
00437         }
00438       else
00439         {
00440           RCS_FD_SET (connection_socket, &read_fd_set);
00441         }
00442       if (0 != ready_descriptors)
00443         {
00444           rcs_print_error ("%d descriptors ready but not serviced.\n",
00445                            ready_descriptors);
00446         }
00447     }
00448 
00449 
00450   current_entry = (TCP_PROXY_ENTRY *) proxy_sockets->get_head ();
00451   while (NULL != current_entry)
00452     {
00453       dl_closesocket (current_entry->server_socket);
00454       dl_closesocket (current_entry->client_socket);
00455       current_entry = (TCP_PROXY_ENTRY *) proxy_sockets->get_next ();
00456     }
00457   dl_closesocket (connection_socket);
00458   delete proxy_sockets;
00459   exit (0);
00460 }

Generated on Sun Dec 2 15:56:53 2001 for rcslib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001