home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 21 / IOPROG_21.ISO / SOFT / APIRC.ZIP / aprelay.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-15  |  6.7 KB  |  357 lines

  1. #ident "@(#) aprelay.c 0.1 06/15/1998 "
  2.  
  3. /********************************************************/
  4. /*      Copyright (C) 1998 ID NET - Nancy - FRANCE      */
  5. /*             P.Toilon (zorthrax@id-net.fr)            */
  6. /*    This relay is released into the Public Domain     */
  7. /*    The original file 'apircrly.c' has 6901 bytes     */
  8. /********************************************************/
  9.  
  10. #include <stdio.h>
  11. #include <netdb.h>
  12. #include <sys/time.h>
  13. #include <sys/socket.h>
  14. #include <netinet/in.h>
  15. #define hd(h) ((h<'A')?(h-'0'):(((h&0xdf)-'A')+10))
  16.  
  17. /* Change it to #undef UNIX if under Windows */
  18. #undef  UNIX
  19. /* Max simultaneous users on the relay */
  20. #define MAXUSERS 128
  21. /* Local listener socket timeout in seconds */
  22. #define LCTIMEOUT 120
  23. /* Max length of negociation frame before connecting to remote */
  24. #define MAXFRAME 128
  25.  
  26. struct usr
  27. {
  28.     int fd;
  29.     int fdo;
  30. }    usr[MAXUSERS];
  31.  
  32. char oc;
  33. fd_set rfds,fds;
  34. struct sockaddr_in uin;
  35. int FIRST,mfd,maxfd,osz;
  36. short eoframe[MAXUSERS];
  37. char *cpass,*cserv,*cport,*arg,*strchr();
  38. char *fptr[MAXUSERS],frame[MAXUSERS][MAXFRAME];
  39.  
  40. void htod4(saddr,i1,i2,i3,i4)
  41. long saddr;
  42. int *i1,*i2,*i3,*i4;
  43. {
  44.     char xsaddr[32];
  45.  
  46.     sprintf(xsaddr,"%.8x",saddr);
  47.  
  48.     *i4=hd(xsaddr[0])*16+hd(xsaddr[1]);
  49.     *i3=hd(xsaddr[2])*16+hd(xsaddr[3]);
  50.     *i2=hd(xsaddr[4])*16+hd(xsaddr[5]);
  51.     *i1=hd(xsaddr[6])*16+hd(xsaddr[7]);
  52. }
  53.  
  54. /*
  55. ** addrcmp("194.206.115.0",0x0673cec2) -> 0
  56. ** addrcmp("194.206.115.0",0x0673cec2) -> 0
  57. ** (0x0673cec2 corresponding to 194.206.115.6)
  58. **
  59. ** Allow to select incoming users on an accept(fd,&in,&sz).
  60. ** E.g.: addrcmp("194.206.115.0",in.sin_addr.s_addr)
  61. */
  62. int addrcmp(faddr,saddr)
  63. char *faddr;
  64. long saddr;
  65. {
  66.     int fi[4],si[4],cpt;
  67.     char caddr[32],*cn2,*cn3,*cn4;
  68.  
  69.     strcpy(caddr,faddr);
  70.  
  71.     if(!isdigit(*caddr) || !(cn2=strchr(caddr,'.')) || !isdigit(*++cn2) ||
  72.                     !(cn3=strchr(cn2,'.')) || !isdigit(*++cn3) ||
  73.                         !(cn4=strchr(cn3,'.')) || !isdigit(*++cn4))
  74.                             return(-1);
  75.  
  76.     *(cn2-1)=*(cn3-1)=*(cn4-1)='\0';
  77.  
  78.     if((fi[0]=atoi(caddr))>255 || (fi[1]=atoi(cn2))>255 ||
  79.         (fi[2]=atoi(cn3))>255 || (fi[3]=atoi(cn4))>255)
  80.             return(-1);
  81.  
  82.     htod4(saddr,&si[0],&si[1],&si[2],&si[3]);
  83.  
  84.     for(cpt=0;cpt<4;cpt++)
  85.         if(fi[cpt] && si[cpt]!=fi[cpt])
  86.             return(-1);
  87.  
  88.     return(0);
  89. }
  90.  
  91. int open_remote_server_socket(server,port)
  92. char *server;
  93. int port;
  94. {
  95.     int fd;
  96.     struct hostent *rmt;
  97.     struct sockaddr_in out;
  98.  
  99.     if((fd=socket(AF_INET,SOCK_STREAM,0))<0)
  100.         return(-1);
  101.  
  102.     if(!(rmt=gethostbyname(server)))
  103.     {
  104.         close(fd);
  105.         return(-1);
  106.     }
  107.  
  108.     memcpy(&out.sin_addr,rmt->h_addr,rmt->h_length);
  109.  
  110.     out.sin_family=AF_INET;
  111.     out.sin_port=htons(port);
  112.  
  113.     if(connect(fd,(struct sockaddr *)&out,sizeof out)<0)
  114.     {
  115.         close(fd);
  116.         return(-1);
  117.     }
  118.  
  119.     return(fd);
  120. }
  121.  
  122. int open_listener_socket(port,maxusers,timeout)
  123. int port,maxusers,timeout;
  124. {
  125.     time_t tvey;
  126.     struct sockaddr_in in;
  127.     int fd,rt,sz=sizeof(struct sockaddr_in);
  128.  
  129.     if((fd=socket(AF_INET,SOCK_STREAM,0))<0)
  130.         return(-1);
  131.  
  132.     memset(&in,0,sz);
  133.     in.sin_family=AF_INET;
  134.     in.sin_addr.s_addr=INADDR_ANY;
  135.     in.sin_port=htons(port);
  136.  
  137.     time(&tvey);
  138.  
  139.     while((rt=bind(fd,(struct sockaddr *)&in,sz))<0 && (time(0)-tvey)<timeout)
  140.         sleep(1);
  141.  
  142.     if(rt<0 || listen(fd,maxusers)<0)
  143.     {
  144.         close(fd);
  145.         return(-1);
  146.     }
  147.  
  148.     return(fd);
  149. }
  150.  
  151. int sd(fd,str)
  152. int fd;
  153. char *str;
  154. {
  155.     return(send(fd,str,strlen(str),0));
  156. }
  157.  
  158. int getnewusernum()
  159. {
  160.     int i;
  161.  
  162.     for(i=0;i<MAXUSERS;i++)
  163.         if(usr[i].fd==-1)
  164.             return(i);
  165.     return(-1);
  166. }
  167.  
  168. int getmaxfdvalue(fd)
  169. int fd;
  170. {
  171.     int i,j;
  172.  
  173.     for(i=0,j=-1;i<MAXUSERS;i++)
  174.     {
  175.         if(usr[i].fd>j)
  176.             j=usr[i].fd;
  177.         if(usr[i].fdo>j)
  178.             j=usr[i].fdo;
  179.     }
  180.  
  181.     if(fd>j)
  182.         j=fd;
  183.  
  184.     return(j);
  185. }
  186.  
  187. /*
  188. ** accept sent a broken pipe (signal 13)
  189. ** We go back into accept_user()
  190. */
  191. void b_accept()
  192. {
  193.     FIRST=0;
  194.     accept_user();
  195. }
  196.  
  197. accept_user()
  198. {
  199.     int i,newfd;
  200.  
  201.     /*
  202.     ** To avoid the accept() brokenpipe
  203.     */
  204.     signal(13,b_accept);
  205.  
  206.     if(FIRST)
  207.     {
  208.         for(i=0;i<MAXUSERS;i++)
  209.         {
  210.             usr[i].fd=-1;
  211.             usr[i].fdo=-1;
  212.         }
  213.  
  214.         FD_ZERO(&fds);
  215.         FD_ZERO(&rfds);
  216.         FD_SET((maxfd=mfd),&fds);
  217.     }
  218.  
  219.     while(1)
  220.     {
  221.         rfds=fds;
  222.         select(maxfd+1,&rfds,NULL,NULL,0);
  223.  
  224.         if(FD_ISSET(mfd,&rfds))
  225.         {
  226.             if((newfd=accept(mfd,(struct sockaddr *)&uin,&osz))>=0)
  227.             {
  228.                 if(arg && addrcmp(arg,uin.sin_addr.s_addr)==-1)
  229.                 {
  230.                     sd(newfd,"Sorry, your host is not allowed !\n\r");
  231.                     close(newfd);
  232.                 }
  233.                 else if((i=getnewusernum())==-1)
  234.                 {
  235.                     sd(newfd,"Sorry, all relay sockets are busy !\n\r");
  236.                     close(newfd);
  237.                 }
  238.                 else
  239.                 {
  240.                     usr[i].fd=newfd;
  241.                     usr[i].fdo=-1;
  242.                     fptr[i]=frame[i];
  243.                     eoframe[i]=0;
  244.                     sd(usr[i].fd,"Apirc relay v1.0\r\n\n");
  245.                     FD_SET(usr[i].fd,&fds);
  246.                     maxfd=getmaxfdvalue(mfd);
  247.                 }
  248.             }
  249.         }
  250.         else for(i=0;i<MAXUSERS;i++)
  251.         {
  252.             if(usr[i].fd!=-1 && FD_ISSET(usr[i].fd,&rfds))
  253.             {
  254.                 if(!recv(usr[i].fd,&oc,1,0))    /* If disconnected */
  255.                 {
  256.                     FD_CLR(usr[i].fd,&fds);
  257.                     close(usr[i].fd);
  258.                     usr[i].fd=-1;
  259.                     if(usr[i].fdo!=-1)
  260.                     {
  261.                         FD_CLR(usr[i].fdo,&fds);
  262.                         close(usr[i].fdo);
  263.                         usr[i].fdo=-1;
  264.                     }
  265.                     maxfd=getmaxfdvalue(mfd);
  266.                 }
  267.                 else if(usr[i].fdo!=-1)    /* connected to remote serv */
  268.                     send(usr[i].fdo,&oc,1,0);
  269.                 else if(!eoframe[i])    /* remove this cond for direct relay */
  270.                 {
  271.                     /* too big negociation frame */
  272.                     if((fptr[i]-frame[i])>=MAXFRAME)
  273.                     {
  274.                         FD_CLR(usr[i].fd,&fds);
  275.                         close(usr[i].fd);
  276.                         usr[i].fd=-1;
  277.                         maxfd=getmaxfdvalue(mfd);
  278.                     }
  279.                     else if(oc=='º')
  280.                     {
  281.                         *(fptr[i]-1)='\0';    /* On the last ':' */
  282.                         cpass=frame[i];
  283.                         *(cserv=strchr(frame[i],':'))='\0';
  284.                         *(cport=strchr(++cserv,':'))='\0';
  285.                         cport++;
  286.                         eoframe[i]=1;
  287.                     }
  288.                     /* Still not º in "xUi.HjGF/g:irc.id-net.fr:6667:º" */
  289.                     else if(oc>0)
  290.                         *(fptr[i])++ = oc;
  291.                 }
  292.                 else    /* We just received the complete frame, let's connect */
  293.                 {
  294.                     if((usr[i].fdo=open_remote_server_socket(cserv,atoi(cport)))<0)
  295.                     {
  296.                         sd(usr[i].fd,"Server unavailable\r\n");
  297.                         FD_CLR(usr[i].fd,&fds);    /* On libere */
  298.                         close(usr[i].fd);
  299.                         usr[i].fd=-1;
  300.                         maxfd=getmaxfdvalue(mfd);
  301.                     }
  302.                     else
  303.                     {
  304.                         FD_SET(usr[i].fdo,&fds);
  305.                         maxfd=getmaxfdvalue(mfd);
  306.                         send(usr[i].fdo,&oc,1,0);    /* 1st byte sent to th server */
  307.                     }
  308.                 }
  309.             }
  310.  
  311.             if(usr[i].fdo!=-1 && FD_ISSET(usr[i].fdo,&rfds))
  312.             {
  313.                 if(!recv(usr[i].fdo,&oc,1,0))    /* If disconnected */
  314.                 {
  315.                     FD_CLR(usr[i].fd,&fds);
  316.                     FD_CLR(usr[i].fdo,&fds);
  317.                     close(usr[i].fd);
  318.                     close(usr[i].fdo);
  319.                     usr[i].fd=-1;
  320.                     usr[i].fdo=-1;
  321.                     maxfd=getmaxfdvalue(mfd);
  322.                 }
  323.                 else
  324.                     send(usr[i].fd,&oc,1,0);
  325.             }
  326.         }
  327.     }
  328. }
  329.  
  330. main(argc,argv)
  331. int argc;
  332. char **argv;
  333. {
  334.     arg=(argc==2)?argv[1]:NULL;
  335.  
  336.     printf("Trying to open the listener socket ... ");
  337.     fflush(stdout);
  338.  
  339.     if((mfd=open_listener_socket(8888,MAXUSERS,LCTIMEOUT))<0)
  340.     {
  341.         printf("\nSocket not openable. Daemon not ready\n");
  342.         exit();
  343.     }
  344.  
  345.     printf("\nListener socket ready\n");
  346.     fflush(stdout);
  347.  
  348. #ifdef UNIX
  349.     if(fork())
  350.         exit();
  351. #endif
  352.  
  353.     osz=sizeof(struct sockaddr_in);
  354.     FIRST=1;
  355.     accept_user();
  356. }
  357.