home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / qwfwd / qwfwd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  6.3 KB  |  270 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20.  
  21.  
  22. /*
  23.  * udpred - a inetd launched udp port redirector
  24.  *
  25.  * Version:    @(#)udpred.c 0.01   01/15/97
  26.  *
  27.  * Author:    Chris Faherty <chrisf@america.com>
  28.  *
  29.  * syntax:
  30.  *
  31.  * udpred toip toport
  32.  *
  33.  * sample inetd.conf entry:
  34.  *
  35.  * 7000    dgram    udp    wait    root    /usr/sbin/tcpd    /usr/sbin/udpred 192.168.100.16 7000
  36.  *
  37.  *
  38.  *    This program is free software; you can redistribute it and/or
  39.  *    modify it under the terms of the GNU General Public License
  40.  *    as published by the Free Software Foundation; either version
  41.  *    2 of the License, or (at your option) any later version.
  42.  *
  43.  */
  44. #include <stdio.h>
  45. #include <errno.h>
  46. #include <fcntl.h>
  47. #include <signal.h>
  48. #include <stdlib.h>
  49. #include <sys/types.h>
  50. #include <time.h>
  51.  
  52. #ifdef _WIN32
  53. #include <winsock.h>
  54. #else
  55. #include <sys/time.h>
  56. #include <sys/socket.h>
  57. #include <sys/wait.h>
  58. #include <netdb.h>
  59. #include <netinet/in.h>
  60. #include <unistd.h>
  61. #include <syslog.h>
  62.  
  63. #endif
  64.  
  65. int host_port; // port we are listening on
  66.  
  67. typedef struct peer {
  68.     time_t last;
  69.     struct sockaddr_in sin;
  70.     struct sockaddr_in dest;
  71.     int s; // connected socket to remote
  72.     struct peer *next;
  73. } peer_t;
  74.  
  75. peer_t *peers;
  76.  
  77. /*
  78. ====================
  79. NET_Init
  80. ====================
  81. */
  82. void NET_Init (void)
  83. {
  84. #ifdef _WIN32
  85.     static WSADATA          winsockdata;
  86. //    WORD    wVersionRequested;
  87.     int             r;
  88.  
  89. //    wVersionRequested = MAKEWORD(1, 1);
  90.  
  91.     r = WSAStartup (MAKEWORD(2, 1), &winsockdata);
  92.  
  93.     if (r) {
  94.         fprintf(stderr, "Winsock initialization failed.");
  95.         exit(1);
  96.     }
  97.  
  98.     printf("Winsock Initialized\n");
  99. #endif
  100. }
  101.  
  102.  
  103.  
  104. int connectsock(char *host, char *service, char *protocol)
  105. {
  106.     struct hostent *phe;
  107.     struct servent *pse;
  108.     struct protoent *ppe;
  109.     struct sockaddr_in sin;
  110.     int s, type;
  111.  
  112.     memset(&sin, 0, sizeof(sin));
  113.     sin.sin_family = AF_INET;
  114.  
  115. /* Map service name to port number */
  116.     if(pse = getservbyname(service, protocol))
  117.         sin.sin_port = pse->s_port;
  118.     else if((sin.sin_port = htons((u_short)atoi(service))) == 0)
  119.     {
  120.         fprintf(stderr, "udpred: can't get \"%s\" service entry\n", service);
  121.         exit(2);
  122.     }
  123.  
  124. /* Map host name to IP address, allowing for dotted decimal */
  125.     if(phe = gethostbyname(host))
  126.         memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length);
  127.     else if((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
  128.     {
  129.         fprintf(stderr, "udpred: can't get \"%s\" host entry\n", host);
  130.         exit(2);
  131.     }
  132.  
  133. /* Map protocol name to protocol number */
  134.     if((ppe = getprotobyname(protocol)) == 0)
  135.     {
  136.         fprintf(stderr, "udpred: can't get \"%s\" protocol entry\n", protocol);
  137.         exit(2);
  138.     }
  139.  
  140. /* Use protocol to choose a socket type */
  141.     if(strcmp(protocol, "udp") == 0)
  142.         type = SOCK_DGRAM;
  143.     else
  144.         type = SOCK_STREAM;
  145.  
  146. /* Allocate a socket */
  147.     s = socket(PF_INET, type, ppe->p_proto);
  148.     if(s < 0)
  149.     {
  150.         fprintf(stderr, "udpred: can't create socket: %s\n", sys_errlist[errno]);
  151.         exit(2);
  152.     }
  153.  
  154. /* Connect the socket */
  155.     if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
  156.     {
  157.         fprintf(stderr, "udpred: can't connect to %s.%s: %s\n", host, service, sys_errlist[errno]);
  158.         exit(2);
  159.     }
  160.     return s;
  161. }
  162.  
  163. int main(int argc, char *argv[])
  164. {
  165.     fd_set rfds;
  166.     struct timeval tv;
  167.     int retval;
  168.     int i1;
  169.     char buffer[4095];
  170.     struct sockaddr_in fsin;
  171.     int alen;
  172.     peer_t *p;
  173.     int s;
  174.     struct sockaddr_in    address;
  175.  
  176.     if (argc < 3) {
  177.         printf("Usage:  %s <port> <remote server> <remote server port>\n", argv[0]);
  178.         return 1;
  179.     }
  180.  
  181.     NET_Init();
  182.  
  183.     if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
  184.         perror("socket");
  185.         return 1;
  186.     }
  187.  
  188.     address.sin_family = AF_INET;
  189.     address.sin_addr.s_addr = INADDR_ANY;
  190.     address.sin_port = htons((unsigned short)atoi(argv[1]));
  191.     if (bind (s, (void *)&address, sizeof(address)) == -1)
  192.         perror("bind");
  193.  
  194.     while(1)
  195.     {
  196.         FD_ZERO(&rfds);
  197.         FD_SET(s, &rfds);
  198.         i1 = s;
  199.         for (p = peers; p; p = p->next) {
  200.             FD_SET(p->s, &rfds);
  201.             if (p->s >= i1)
  202.                 i1 = p->s + 1;
  203.         }
  204.         /* Wait up to two minutes. */
  205.         tv.tv_sec = 2;
  206.         tv.tv_usec = 0;
  207.         retval = select(i1, &rfds, (fd_set *)0, (fd_set *)0, &tv);
  208.         if(retval > 0)
  209.         {
  210.             if(FD_ISSET(s, &rfds))
  211.             {
  212.                 alen = sizeof(fsin);
  213.                 i1 = recvfrom(s, buffer, 4096, 0, (struct sockaddr *) &fsin, &alen);
  214.                 if(i1 > 0) {
  215.                     for (p = peers; p; p = p->next)
  216.                         if (memcmp(&p->sin.sin_addr, &fsin.sin_addr, sizeof(p->sin.sin_addr)) == 0 &&
  217.                             memcmp(&p->sin.sin_port, &fsin.sin_port, sizeof(p->sin.sin_port)) == 0) 
  218.                         {
  219.                             send(p->s, buffer, i1, 0);
  220.                             time(&p->last);
  221.                             break;
  222.                         }
  223.                     if (p == NULL) { // new peer
  224.                         printf("peer %s:%d added", inet_ntoa(fsin.sin_addr), (int)ntohs(fsin.sin_port));
  225.                         p = malloc(sizeof *p);
  226.                         p->sin = fsin;
  227.                         p->s = connectsock(argv[2], argv[3], "udp");
  228.                         p->next = peers;
  229.                         peers = p;
  230.                         send(p->s, buffer, i1, 0);
  231.                         time(&p->last);
  232.                     }
  233.                 }
  234.             }
  235.             for (p = peers; p; p = p->next)
  236.                 if(FD_ISSET(p->s, &rfds))
  237.                 {
  238.                     i1 = recv(p->s, buffer, 4096, 0);
  239.                     if(i1 > 0) {
  240.                         time(&p->last);
  241.                         sendto(s, buffer, i1, 0, (struct sockaddr *) &p->sin, 
  242.                             sizeof(p->sin)); 
  243.                     }
  244.                 }
  245.         } else {
  246.             peer_t *pp;
  247.  
  248.             pp = NULL;
  249.             p = peers; 
  250.             while (p) {
  251.                 if (time(NULL) - p->last > 300) {
  252.                     if (!pp && !p->next) {
  253.                         printf("peer %s:%d removed (timeout)", inet_ntoa(p->sin.sin_addr), (int)ntohs(p->sin.sin_port));
  254.                         free(p);
  255.                         p = pp = NULL;
  256.                         continue;
  257.                     }
  258.                     pp->next = p->next;
  259.                     printf ("peer %s:%d removed (timeout)", inet_ntoa(p->sin.sin_addr), (int)ntohs(p->sin.sin_port));
  260.                     free(p);
  261.                     p = pp->next;
  262.                 } else {
  263.                     pp = p;
  264.                     p = p->next;
  265.                 }
  266.             }
  267.         }
  268.     }
  269. }
  270.