relayd.c
上传用户:yzh0222
上传日期:2018-03-09
资源大小:4k
文件大小:12k
源码类别:

Telnet服务器

开发平台:

Windows_Unix

  1. /**
  2.  * relayd.c -- a relay daemon (using one targethost/port)
  3.  * --
  4.  * $Id: relayd.c,v 1.6 2001/08/14 06:54:54 leo Exp $
  5.  *
  6.  * This is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * "The Java Telnet Applet" is distributed in the hope that it will be
  12.  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this software; see the file COPYING.  If not, write to the
  18.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19.  * Boston, MA 02111-1307, USA.
  20.  */
  21. /* relayd.c (c) 1996,1997 Marcus Meissner <marcus@mud.de> */
  22. /* Compile with: cc -o relayd relayd.c
  23.  *           or: gcc -o relayd relayd.c
  24.  * Solaris: (g)cc -o relayd relayd.c -lsocket -lnsl
  25.  */
  26. /* this program expects the string:
  27.  * "relay <hostname> <port>" or "relay <hostname>"
  28.  * after connecting. It will then try to connect to the specified host
  29.  * if failures occur, it will terminate the connection.
  30.  */
  31. /* adjust this to a reasonable limit */
  32. #define MAXUSERS  120
  33. /* message printed if all slots are used ... */
  34. #define FAILMESSAGE "Sorry, all slots are full.rn"
  35. /* string printed before connection */
  36. #define RELAYHEADER ""
  37. #include <stdio.h>
  38. #ifdef _WIN32
  39. #include <stdlib.h>
  40. #include <errno.h>
  41. #include <signal.h>
  42. #include <winsock.h>
  43. #include <io.h>
  44. #define ioctl ioctlsocket
  45. #define write(h,buf,size) send(h,buf,size,0)
  46. #define read(a,b,c) recv(a,b,c,0)
  47. #define close _lclose
  48. #define EINPROGRESS WSAEWOULDBLOCK
  49. #else
  50. #include <unistd.h>
  51. #include <sys/time.h>
  52. #include <sys/socket.h>
  53. #include <sys/errno.h>
  54. #include <sys/signal.h>
  55. #include <sys/fcntl.h>
  56. #include <sys/ioctl.h>
  57. #include <netinet/in.h>
  58. #include <arpa/inet.h>
  59. #include <netdb.h>
  60. #endif
  61. #include <memory.h>
  62. #include <malloc.h>
  63. #include <string.h>
  64. #include <sys/types.h>
  65. #if defined(sun) && defined(__GNUC__)
  66. int socket(int,int,int);
  67. int shutdown(int,int);
  68. int close(int);
  69. int bind(int,struct sockaddr*,int);
  70. int listen(int,int);
  71. int select(int,fd_set *,fd_set*,fd_set*,struct timeval*);
  72. int accept(int,struct sockaddr*,int*);
  73. int connect(int,struct sockaddr*,int);
  74. int recvfrom(int,char*,int,int,struct sockaddr*,int*);
  75. /*void perror(char*); SLOWLARIS HASS*/
  76. /*int sendto(int,char*,int,int,struct sockaddr*,int); SLOWLARIS HASS*/
  77. #endif
  78. #ifdef hpux
  79. /* redefinition... to avoid prototype in <time.h> */
  80. #define FD_CAST int
  81. #endif
  82. #ifndef FD_CAST
  83. #define FD_CAST fd_set
  84. #endif
  85. extern int errno;
  86. char  *inbuf[MAXUSERS],*outbuf[MAXUSERS];
  87. int insize[MAXUSERS],outsize[MAXUSERS];
  88. int incur[MAXUSERS],outcur[MAXUSERS];
  89. int outfd[MAXUSERS],infd[MAXUSERS];
  90. struct  sockaddr_in inaddr[MAXUSERS],outaddr[MAXUSERS];
  91. #ifdef _WIN32
  92. #define perror xperror
  93. void xperror(char *str) {
  94. fprintf(stderr,"%s: %dn",str,GetLastError());
  95. }
  96. #endif
  97. static int
  98. fd_make_nonblocking(int fd) {
  99.   int     isnonblock=0;
  100. #ifdef FIONBIO
  101.   if (!isnonblock) {
  102.     unsigned long     b;
  103.     b=1;
  104.     if (-1==ioctl(fd,FIONBIO,&b)) {
  105.       perror("ioctl FIONBIO");
  106.     } else
  107.       isnonblock=1;
  108.   }
  109. #endif
  110. #ifdef O_NDELAY
  111.   if (!isnonblock) {
  112.     int     flags;
  113.     if (-1==(flags=fcntl(fd,F_GETFL))) {
  114.       perror("fcntl F_GETFL");
  115.     } else {
  116.       flags|=O_NDELAY;
  117.       if (-1==fcntl(fd,F_SETFL,flags)) {
  118.         perror("fcntl F_SETFL  O_NDELAY");
  119.       } else
  120.         isnonblock=1;
  121.     }
  122.   }
  123. #endif
  124. #ifdef O_NONBLOCK
  125.   if (!isnonblock) {
  126.     int     flags;
  127.     if (-1==(flags=fcntl(fd,F_GETFL))) {
  128.       perror("fcntl F_GETFL");
  129.     } else {
  130.       flags|=O_NONBLOCK;
  131.       if (-1==fcntl(fd,F_SETFL,flags)) {
  132.         perror("fcntl F_SETFL  O_NONBLOCK");
  133.       } else
  134.         isnonblock=1;
  135.     }
  136.   }
  137. #endif
  138.   return isnonblock;
  139. }
  140. void
  141. clean_connection(i)
  142. int i;
  143. {
  144.   if (outfd[i]>=0) {
  145.     if (-1==close(outfd[i]))
  146.       perror("close");
  147.     outfd[i]=-1;
  148.   }
  149.   if (infd[i]>=0) {
  150.     if (-1==close(infd[i]))
  151.       perror("close");
  152.     infd[i]=-1;
  153.   }
  154.   incur[i]=outcur[i]=0;
  155.   outbuf[i][0]=inbuf[i][0]='';
  156. }
  157. /* Turn into a daemon. It is easy, isn't it? */
  158. void
  159. daemonize() {
  160. #ifndef _WIN32
  161.     switch (fork()) {
  162.     default: /* parent dies */
  163. exit(0);
  164.     case -1:
  165.      perror("fork");
  166. exit(1);
  167.     case 0: /* son lives */
  168. /* close all common descriptors and reopen them with /dev/null */
  169. close(0);close(1);close(2);
  170. open("/dev/null",O_RDONLY);
  171. open("/dev/null",O_WRONLY);
  172. open("/dev/null",O_WRONLY);
  173. setsid(); /* become session leader to detach from controlling tty */
  174. return; /* and return */
  175.     }
  176. #endif
  177. }
  178. void
  179. usage() {
  180.    fprintf(stderr,"Usage: relayd <listenport> <targethost> [<targetport>]n");
  181. }
  182. int
  183. main(argc,argv)
  184. int argc;
  185. char  **argv;
  186. {
  187.   int i,j,res;
  188.   int acfd;
  189.   struct  sockaddr_in acsa;
  190.   char  readbuf[1000],relaystring[1000];
  191.   struct  in_addr targetaddr;
  192.   struct  hostent *hp;
  193.   char *targethost;
  194.   int  port,targetport;
  195.   
  196. #ifdef _WIN32 
  197.   {
  198. WSADATA wsad;
  199. WSAStartup(0x0101,&wsad);
  200.   }
  201. #endif
  202. #ifdef SIGPIPE
  203.   signal(SIGPIPE,SIG_IGN);
  204. #endif  
  205.   switch (argc) {
  206.   default:
  207.   case 1:
  208.   case 2:
  209.     usage();
  210.     exit(1);
  211.   case 3:
  212.     if (!sscanf(argv[1],"%d",&port)) {
  213.       usage();
  214.       exit(1);
  215.     }
  216.     targethost = argv[2];
  217.     targetport = 23;
  218.     break;
  219.   case 4:
  220.     if (!sscanf(argv[1],"%d",&port)) {
  221.       usage();exit(1);
  222.     }
  223.     if (!sscanf(argv[3],"%d",&targetport)) {
  224.       usage();exit(1);
  225.     }
  226.     targethost=argv[2];
  227.     break;
  228.   }
  229. #ifndef _WIN32 
  230.   /* Turn into a daemon */
  231.   daemonize();
  232. #endif
  233.   strcpy(relaystring,FAILMESSAGE);
  234.   if (-1==(acfd=socket(PF_INET,SOCK_STREAM,0))) {
  235.     perror("socket(accept_socket)");
  236.     exit(1);
  237.   }
  238.   for (i=MAXUSERS;i--;) {
  239.     inbuf[i]=malloc(10000*sizeof(char));
  240.     outbuf[i]=malloc(10000*sizeof(char));
  241.     inbuf[i][0]='';outbuf[i][0]='';
  242.     insize[i]=10000;incur[i]=0;
  243.     outsize[i]=10000;outcur[i]=0;
  244.     outfd[i]=infd[i]=-1;
  245.   }
  246. #ifdef SO_REUSEADDR
  247.   {
  248.     int reuseit=1;
  249.     if (-1==setsockopt(acfd,SOL_SOCKET,SO_REUSEADDR,(char*)&reuseit,sizeof(reuseit)))
  250. perror("setsockopt SOL_SOCKET SO_REUSEADDR");
  251.   }
  252. #endif
  253.   acsa.sin_family=AF_INET;
  254.   acsa.sin_port=htons(port);
  255.   acsa.sin_addr.s_addr=INADDR_ANY;
  256.   if (-1==bind(acfd,(struct sockaddr*)&acsa,sizeof(struct sockaddr_in))) {
  257.     perror("bind");
  258.     exit(1);
  259.   }
  260.   /* 5 is usual the maximum anyway */
  261.   if (-1==listen(acfd,5)) {
  262.     perror("listen");
  263.     exit(1);
  264.   }
  265.   while (1) {
  266.     fd_set  readfds,writefds;
  267.     int width;
  268.     width=3;
  269.     if (acfd>=width)
  270.       width=acfd+1;
  271. restart_select:
  272.     FD_ZERO(&readfds);FD_ZERO(&writefds);
  273.     FD_SET(acfd,&readfds);
  274.     for (i=MAXUSERS;i--;) {
  275.       if (outfd[i]>=0) {
  276.         /*need to do that... else it will cause load 1*/
  277.         if (incur[i])
  278.           FD_SET(outfd[i],&writefds);
  279.         FD_SET(outfd[i],&readfds);
  280.         if (outfd[i]>=width)
  281.           width=outfd[i]+1;
  282.       }
  283.       if (infd[i]>=0) {
  284.         /*need to do that... else it will cause load 1*/
  285.         if (outcur[i])
  286.           FD_SET(infd[i],&writefds);
  287.         FD_SET(infd[i],&readfds);
  288.         if (infd[i]>=width)
  289.           width=infd[i]+1;
  290.       }
  291.     }
  292.     if (-1==select(   width,
  293.           (FD_CAST*)&readfds,
  294.           (FD_CAST*)&writefds,
  295.           NULL,/*no exceptfds.*/
  296.           0)
  297.     ) {
  298.       if (errno!=EINTR)
  299.         perror("select");
  300.       else
  301.         goto  restart_select;
  302.     }
  303.     if (FD_ISSET(acfd,&readfds)) {
  304.       int afd;
  305.       int aclen;
  306.       struct  sockaddr_in conaddr;
  307.       aclen=sizeof(struct sockaddr_in);
  308.       if (-1==(afd=accept(acfd,(struct sockaddr*)&conaddr,&aclen)))
  309.         perror("accept");
  310.       for (i=MAXUSERS;i--;)
  311.         if ((infd[i]==-1) && (outfd[i]==-1))
  312.           break;
  313.       if (i==-1) {
  314.         write(afd,relaystring,strlen(relaystring));
  315.         close(afd);
  316.       } else {
  317.         char  sendbuf[200];
  318.         infd[i]=afd;
  319.         memcpy(&inaddr[i],&conaddr,sizeof(struct sockaddr_in));
  320.         /* outfd setting delayed until we get
  321.          * to the first line
  322.          */
  323.         hp=gethostbyname(targethost);
  324.         if (!hp) {/* not found */
  325.           clean_connection(i);
  326.           continue;
  327.         }
  328.         memcpy(&targetaddr,hp->h_addr_list[0],sizeof(struct in_addr));
  329.         outaddr[i].sin_family=AF_INET;
  330.         outaddr[i].sin_port=htons(targetport);
  331.         memcpy(&(outaddr[i].sin_addr),&targetaddr,4);
  332.         strcpy(sendbuf,RELAYHEADER);
  333.         outcur[i]=strlen(sendbuf);
  334.         memcpy(outbuf[i],sendbuf,strlen(sendbuf)+1);
  335.         if (-1==(outfd[i]=socket(PF_INET,SOCK_STREAM,0)))
  336.           perror("socket(connect_socket)");
  337. #ifndef _WIN32
  338.         (void)fd_make_nonblocking(outfd[i]);
  339. #endif        
  340. if (  (-1==connect( outfd[i],
  341.             (struct sockaddr*)&outaddr[i],
  342.             sizeof(struct sockaddr_in))
  343. #ifdef _WIN32
  344.         ) && (WSAGetLastError()!=WSAEWOULDBLOCK)
  345. #else  
  346.         ) && (errno!=EINPROGRESS)
  347. #endif
  348.         ) {
  349. #ifdef _WIN32
  350. sprintf(readbuf,"Connect to %s failed: %dn",targethost,GetLastError());
  351. #else
  352.           sprintf(readbuf,"Connect to %s failed.n",targethost);
  353. #endif
  354.           perror("connect");
  355.           if (-1==write(infd[i],readbuf,strlen(readbuf)))
  356.             perror("write");
  357.           clean_connection(i);
  358.           continue;
  359.         }
  360.         inbuf[i][0]='';
  361.         incur[i]=0;
  362.       }
  363.     }
  364.     for (i=MAXUSERS;i--;) {
  365.       if ((infd[i]>=0) && FD_ISSET(infd[i],&readfds)) {
  366.         do {
  367.           if (-1==(res=read(infd[i],readbuf,1000))) {
  368.             if (errno==EINTR)
  369.               continue;
  370.             /* user side has broken the connection */
  371.             clean_connection(i);
  372.             break;
  373.           }
  374.           break;
  375.         } while (1);
  376.         if (res==0) /* EOF */
  377.           clean_connection(i);
  378.         if (res>0) {
  379.           readbuf[res]='';
  380.           while (incur[i]+res>=insize[i]) {
  381.             inbuf[i]=realloc(inbuf[i],insize[i]*2);
  382.             insize[i]*=2;
  383.           }
  384.           memcpy(inbuf[i]+incur[i],readbuf,res+1);
  385.           incur[i]+=res;
  386.         }
  387.       }
  388.       if ((outfd[i]>=0) && FD_ISSET(outfd[i],&readfds)) {
  389.         do {
  390.           if (-1==(res=read(outfd[i],readbuf,1000))) {
  391.             if (errno==EINTR)
  392.               continue;
  393.             /* the mudside has broken the
  394.              * connection. we still have
  395.              * to transmit the rest of
  396.              * the text
  397.              */
  398.             outfd[i]=-1;
  399.             break;
  400.           }
  401.           break;
  402.         } while (1);
  403.         if (res==0)
  404.           clean_connection(i);
  405.         if (res>0) {
  406.           /* 0 is not automagically appended. */
  407.           readbuf[res]='';
  408.           while (outcur[i]+res>=outsize[i]) {
  409.             outbuf[i]=realloc(outbuf[i],outsize[i]*2);
  410.             outsize[i]*=2;
  411.           }
  412.           memcpy(outbuf[i]+outcur[i],readbuf,res+1);
  413.           printf("%s",readbuf); //yys
  414.           outcur[i]+=res;
  415.         }
  416.       }
  417.       if ((infd[i]>=0) && FD_ISSET(infd[i],&writefds)) {
  418.         j=outcur[i];
  419.         if (-1==(res=write(infd[i],outbuf[i],j))) {
  420.           if (errno!=EINTR) {
  421.             clean_connection(i);
  422.           }
  423.         }
  424.         if (res>0) {
  425.           memcpy(outbuf[i],outbuf[i]+res,outcur[i]-res);
  426.           outcur[i]-=res;
  427.         }
  428.       }
  429.       if ((outfd[i]>=0) && FD_ISSET(outfd[i],&writefds)) {
  430.         j=incur[i];
  431.         if (-1==(res=write(outfd[i],inbuf[i],j))) {
  432.           if (errno!=EINTR) {
  433.             outfd[i]=-1;
  434.             /*clean_connection(i);*/
  435.           }
  436.         }
  437.         if (res>0) {
  438.           memcpy(inbuf[i],inbuf[i]+res,incur[i]-res);
  439.           incur[i]-=res;
  440.         }
  441.       }
  442.     }
  443.   }
  444. }