home *** CD-ROM | disk | FTP | other *** search
- #ident "@(#) aprelay.c 0.1 06/15/1998 "
-
- /********************************************************/
- /* Copyright (C) 1998 ID NET - Nancy - FRANCE */
- /* P.Toilon (zorthrax@id-net.fr) */
- /* This relay is released into the Public Domain */
- /* The original file 'apircrly.c' has 6901 bytes */
- /********************************************************/
-
- #include <stdio.h>
- #include <netdb.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #define hd(h) ((h<'A')?(h-'0'):(((h&0xdf)-'A')+10))
-
- /* Change it to #undef UNIX if under Windows */
- #undef UNIX
- /* Max simultaneous users on the relay */
- #define MAXUSERS 128
- /* Local listener socket timeout in seconds */
- #define LCTIMEOUT 120
- /* Max length of negociation frame before connecting to remote */
- #define MAXFRAME 128
-
- struct usr
- {
- int fd;
- int fdo;
- } usr[MAXUSERS];
-
- char oc;
- fd_set rfds,fds;
- struct sockaddr_in uin;
- int FIRST,mfd,maxfd,osz;
- short eoframe[MAXUSERS];
- char *cpass,*cserv,*cport,*arg,*strchr();
- char *fptr[MAXUSERS],frame[MAXUSERS][MAXFRAME];
-
- void htod4(saddr,i1,i2,i3,i4)
- long saddr;
- int *i1,*i2,*i3,*i4;
- {
- char xsaddr[32];
-
- sprintf(xsaddr,"%.8x",saddr);
-
- *i4=hd(xsaddr[0])*16+hd(xsaddr[1]);
- *i3=hd(xsaddr[2])*16+hd(xsaddr[3]);
- *i2=hd(xsaddr[4])*16+hd(xsaddr[5]);
- *i1=hd(xsaddr[6])*16+hd(xsaddr[7]);
- }
-
- /*
- ** addrcmp("194.206.115.0",0x0673cec2) -> 0
- ** addrcmp("194.206.115.0",0x0673cec2) -> 0
- ** (0x0673cec2 corresponding to 194.206.115.6)
- **
- ** Allow to select incoming users on an accept(fd,&in,&sz).
- ** E.g.: addrcmp("194.206.115.0",in.sin_addr.s_addr)
- */
- int addrcmp(faddr,saddr)
- char *faddr;
- long saddr;
- {
- int fi[4],si[4],cpt;
- char caddr[32],*cn2,*cn3,*cn4;
-
- strcpy(caddr,faddr);
-
- if(!isdigit(*caddr) || !(cn2=strchr(caddr,'.')) || !isdigit(*++cn2) ||
- !(cn3=strchr(cn2,'.')) || !isdigit(*++cn3) ||
- !(cn4=strchr(cn3,'.')) || !isdigit(*++cn4))
- return(-1);
-
- *(cn2-1)=*(cn3-1)=*(cn4-1)='\0';
-
- if((fi[0]=atoi(caddr))>255 || (fi[1]=atoi(cn2))>255 ||
- (fi[2]=atoi(cn3))>255 || (fi[3]=atoi(cn4))>255)
- return(-1);
-
- htod4(saddr,&si[0],&si[1],&si[2],&si[3]);
-
- for(cpt=0;cpt<4;cpt++)
- if(fi[cpt] && si[cpt]!=fi[cpt])
- return(-1);
-
- return(0);
- }
-
- int open_remote_server_socket(server,port)
- char *server;
- int port;
- {
- int fd;
- struct hostent *rmt;
- struct sockaddr_in out;
-
- if((fd=socket(AF_INET,SOCK_STREAM,0))<0)
- return(-1);
-
- if(!(rmt=gethostbyname(server)))
- {
- close(fd);
- return(-1);
- }
-
- memcpy(&out.sin_addr,rmt->h_addr,rmt->h_length);
-
- out.sin_family=AF_INET;
- out.sin_port=htons(port);
-
- if(connect(fd,(struct sockaddr *)&out,sizeof out)<0)
- {
- close(fd);
- return(-1);
- }
-
- return(fd);
- }
-
- int open_listener_socket(port,maxusers,timeout)
- int port,maxusers,timeout;
- {
- time_t tvey;
- struct sockaddr_in in;
- int fd,rt,sz=sizeof(struct sockaddr_in);
-
- if((fd=socket(AF_INET,SOCK_STREAM,0))<0)
- return(-1);
-
- memset(&in,0,sz);
- in.sin_family=AF_INET;
- in.sin_addr.s_addr=INADDR_ANY;
- in.sin_port=htons(port);
-
- time(&tvey);
-
- while((rt=bind(fd,(struct sockaddr *)&in,sz))<0 && (time(0)-tvey)<timeout)
- sleep(1);
-
- if(rt<0 || listen(fd,maxusers)<0)
- {
- close(fd);
- return(-1);
- }
-
- return(fd);
- }
-
- int sd(fd,str)
- int fd;
- char *str;
- {
- return(send(fd,str,strlen(str),0));
- }
-
- int getnewusernum()
- {
- int i;
-
- for(i=0;i<MAXUSERS;i++)
- if(usr[i].fd==-1)
- return(i);
- return(-1);
- }
-
- int getmaxfdvalue(fd)
- int fd;
- {
- int i,j;
-
- for(i=0,j=-1;i<MAXUSERS;i++)
- {
- if(usr[i].fd>j)
- j=usr[i].fd;
- if(usr[i].fdo>j)
- j=usr[i].fdo;
- }
-
- if(fd>j)
- j=fd;
-
- return(j);
- }
-
- /*
- ** accept sent a broken pipe (signal 13)
- ** We go back into accept_user()
- */
- void b_accept()
- {
- FIRST=0;
- accept_user();
- }
-
- accept_user()
- {
- int i,newfd;
-
- /*
- ** To avoid the accept() brokenpipe
- */
- signal(13,b_accept);
-
- if(FIRST)
- {
- for(i=0;i<MAXUSERS;i++)
- {
- usr[i].fd=-1;
- usr[i].fdo=-1;
- }
-
- FD_ZERO(&fds);
- FD_ZERO(&rfds);
- FD_SET((maxfd=mfd),&fds);
- }
-
- while(1)
- {
- rfds=fds;
- select(maxfd+1,&rfds,NULL,NULL,0);
-
- if(FD_ISSET(mfd,&rfds))
- {
- if((newfd=accept(mfd,(struct sockaddr *)&uin,&osz))>=0)
- {
- if(arg && addrcmp(arg,uin.sin_addr.s_addr)==-1)
- {
- sd(newfd,"Sorry, your host is not allowed !\n\r");
- close(newfd);
- }
- else if((i=getnewusernum())==-1)
- {
- sd(newfd,"Sorry, all relay sockets are busy !\n\r");
- close(newfd);
- }
- else
- {
- usr[i].fd=newfd;
- usr[i].fdo=-1;
- fptr[i]=frame[i];
- eoframe[i]=0;
- sd(usr[i].fd,"Apirc relay v1.0\r\n\n");
- FD_SET(usr[i].fd,&fds);
- maxfd=getmaxfdvalue(mfd);
- }
- }
- }
- else for(i=0;i<MAXUSERS;i++)
- {
- if(usr[i].fd!=-1 && FD_ISSET(usr[i].fd,&rfds))
- {
- if(!recv(usr[i].fd,&oc,1,0)) /* If disconnected */
- {
- FD_CLR(usr[i].fd,&fds);
- close(usr[i].fd);
- usr[i].fd=-1;
- if(usr[i].fdo!=-1)
- {
- FD_CLR(usr[i].fdo,&fds);
- close(usr[i].fdo);
- usr[i].fdo=-1;
- }
- maxfd=getmaxfdvalue(mfd);
- }
- else if(usr[i].fdo!=-1) /* connected to remote serv */
- send(usr[i].fdo,&oc,1,0);
- else if(!eoframe[i]) /* remove this cond for direct relay */
- {
- /* too big negociation frame */
- if((fptr[i]-frame[i])>=MAXFRAME)
- {
- FD_CLR(usr[i].fd,&fds);
- close(usr[i].fd);
- usr[i].fd=-1;
- maxfd=getmaxfdvalue(mfd);
- }
- else if(oc=='º')
- {
- *(fptr[i]-1)='\0'; /* On the last ':' */
- cpass=frame[i];
- *(cserv=strchr(frame[i],':'))='\0';
- *(cport=strchr(++cserv,':'))='\0';
- cport++;
- eoframe[i]=1;
- }
- /* Still not º in "xUi.HjGF/g:irc.id-net.fr:6667:º" */
- else if(oc>0)
- *(fptr[i])++ = oc;
- }
- else /* We just received the complete frame, let's connect */
- {
- if((usr[i].fdo=open_remote_server_socket(cserv,atoi(cport)))<0)
- {
- sd(usr[i].fd,"Server unavailable\r\n");
- FD_CLR(usr[i].fd,&fds); /* On libere */
- close(usr[i].fd);
- usr[i].fd=-1;
- maxfd=getmaxfdvalue(mfd);
- }
- else
- {
- FD_SET(usr[i].fdo,&fds);
- maxfd=getmaxfdvalue(mfd);
- send(usr[i].fdo,&oc,1,0); /* 1st byte sent to th server */
- }
- }
- }
-
- if(usr[i].fdo!=-1 && FD_ISSET(usr[i].fdo,&rfds))
- {
- if(!recv(usr[i].fdo,&oc,1,0)) /* If disconnected */
- {
- FD_CLR(usr[i].fd,&fds);
- FD_CLR(usr[i].fdo,&fds);
- close(usr[i].fd);
- close(usr[i].fdo);
- usr[i].fd=-1;
- usr[i].fdo=-1;
- maxfd=getmaxfdvalue(mfd);
- }
- else
- send(usr[i].fd,&oc,1,0);
- }
- }
- }
- }
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- arg=(argc==2)?argv[1]:NULL;
-
- printf("Trying to open the listener socket ... ");
- fflush(stdout);
-
- if((mfd=open_listener_socket(8888,MAXUSERS,LCTIMEOUT))<0)
- {
- printf("\nSocket not openable. Daemon not ready\n");
- exit();
- }
-
- printf("\nListener socket ready\n");
- fflush(stdout);
-
- #ifdef UNIX
- if(fork())
- exit();
- #endif
-
- osz=sizeof(struct sockaddr_in);
- FIRST=1;
- accept_user();
- }
-