/* * Proxy server for Raccoon */ #include #include #include #include #include #include #include #include #include #include #define MAXMSG 512 #define BBSPORT 6145 #define BBSADDR "bbs.iscabbs.com" /* default timeout for bbs sockets list */ #define MAXTIME 600 /* 10 minutes */ int read_from_client(int); int make_socket(uint16_t); void scan_list(void); typedef struct _BSOCKET { char key[MAXMSG]; /* client file descriptor */ int socket_fd; /* bbs socket */ time_t last_access; struct _BSOCKET * next; } bsocket; bsocket * head; int read_from_client (int filedes) { char buffer[MAXMSG]; char out[MAXMSG]; char msg[MAXMSG]; int nbytes,nbbs; bsocket * p, *q, *r; struct sockaddr_in bbsname; struct hostent *hostinfo; char *s; time_t now; bbsname.sin_family = AF_INET; bbsname.sin_port = htons(BBSPORT); hostinfo = gethostbyname(BBSADDR); if ( hostinfo == NULL ) { fprintf(stderr,"Unknown host %s.\n", BBSADDR); exit(EXIT_FAILURE); } bbsname.sin_addr = *(struct in_addr *)hostinfo->h_addr; bzero(buffer,MAXMSG); bzero(out,MAXMSG); nbytes = read(filedes,buffer,MAXMSG); p = NULL; if (nbytes < 0) { perror("read"); exit(EXIT_FAILURE); } else if (nbytes == 0 ) { /* End of file */ return -1; } else { /* Data read */ s = strchr(buffer,'\n'); if ( s ) { sprintf(out,"s is %ld, buffer is %ld, diff is %ld\n", s, buffer, (s-buffer)); fprintf(stderr,out); buffer[(s-buffer-1)] = (char)0; } fprintf(stderr, "Server: got message: '%s'\n",buffer); if (strncmp("connect",buffer,7) == 0 ) { // connect to raccoon p = (bsocket*)malloc(sizeof(bsocket)); if ( p ) { p->socket_fd = socket(AF_INET, SOCK_STREAM, 0); if ( p->socket_fd < 0) { perror("bbs_socket"); exit(EXIT_FAILURE); } if (connect(p->socket_fd,&bbsname,sizeof(bbsname)) < 0) { perror("connect"); exit(EXIT_FAILURE); } bzero(buffer,MAXMSG); nbbs = read(p->socket_fd,buffer,MAXMSG); if ( nbbs > 0 ) { s = strstr(buffer,"seed:"); if ( s ) { s = s+5; strncpy(p->key,s,strlen(s)-1); send(filedes,p->key,strlen(p->key),0); time(&(p->last_access)); q = head; if (q) { while(q->next) { q=q->next; } q->next = p; } else { head = p; } return 1; } } } return -1; } if (strncmp("key",buffer,3) == 0 ) { strncpy(out,buffer+4,sizeof(buffer)-5); out[(strlen(buffer)-4)] = (char)0; /* find the associated socket */ p = head; while(p) { sprintf(msg,"Comparing '%s' => '%s'\n", out, p->key); fprintf(stderr,msg); if ( strcmp(out,p->key) == 0 ) { sprintf(msg,"Found it! %ld => %d\n", p, p->socket_fd); fprintf(stderr,msg); break; } p = p->next; } if ( p ) { time(&now); if (( (long)now - (long)(p->last_access)) > MAXTIME ) { sprintf(buffer,"quit"); sprintf(out,"The connection has timed out\n"); send(filedes,out,strlen(out),0); } else { sprintf(out,"cmd"); send(filedes,out,strlen(out),0); bzero(buffer,MAXMSG); nbytes = read(filedes,buffer,MAXMSG); } } } if ( strncmp("quit",buffer,4) == 0 ) { sprintf(out,"QUIT request accepted.\n"); send(filedes,out,strlen(out),0); fprintf(stderr,"Client socket %d QUIT request.\n",filedes); if ( p ) { close(p->socket_fd); /* remove that socket from our list */ if ( p == head ) { head = p->next; free(p); } else { q = head; while(q->next != p) { if (!q->next) { break; } q=q->next; } q->next = p->next; free(p); } } return 1; } if (!p) { sprintf(out,"503 Need a key"); send(filedes,out,strlen(out),0); return -1; } if (p) { fprintf(stderr,"Sending: [%s]\n",buffer); sprintf(out,"%s\n",buffer); send(p->socket_fd,out,strlen(out),0); bzero(buffer,MAXMSG); nbbs = recv(p->socket_fd,buffer,MAXMSG,0); sprintf(msg,"Read %d bytes.\n",nbbs); fprintf(stderr,msg); time(&(p->last_access)); if ( !((strncmp("list",out,4)==0) || (strncmp("online",out,6)==0) || (strncmp("read",out,4)==0))) { fprintf(stderr,"Not list or online...\n"); send(filedes,buffer,MAXMSG,0); return 1; } while(1) { send(filedes,buffer,MAXMSG,0); buffer[MAXMSG] = 0; if (( strcmp(buffer,".")==0) || ( strstr(buffer,"\n.\n"))) { break; } sprintf(msg,"%d|%d|%s\n", p->socket_fd, nbbs, buffer); fprintf(stderr,msg); bzero(buffer,MAXMSG); nbbs = recv(p->socket_fd,buffer,1,MSG_PEEK); sprintf(msg,"Number of bytes left: %d\n", nbbs); fprintf(stderr,msg); if ( nbbs < 1 ) { break; } bzero(buffer,MAXMSG); nbbs = recv(p->socket_fd,buffer,MAXMSG,0); } sprintf(msg,"%d|Done with session.\n"); fprintf(stderr,msg); return 1; } else { sprintf(out,"503 Send Key"); send(filedes,out,strlen(out),0); return 1; } return 0; } } int make_socket(uint16_t port) { int sock; struct sockaddr_in name; /* Create the socket */ sock = socket(PF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("socket"); exit(EXIT_FAILURE); } /* Give the socket a name */ name.sin_family = AF_INET; name.sin_port = htons(port); name.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sock,(struct sockaddr *) &name, sizeof(name)) < 0) { perror("bind"); exit(EXIT_FAILURE); } return sock; } void scan_list(void) { int count; bsocket * p, *q; char msg[MAXMSG]; time_t now; int secs; p = head; count = 0; time(&now); if ( p ) { do { count++; secs = (long)now - (long)(p->last_access); sprintf(msg,"%ld>%d|%s|%d|%ld|%d\n", now, count, p->key, p->socket_fd, p->last_access, secs); fprintf(stderr,msg); if ( secs > MAXTIME ) { fprintf(stderr,"\tRemoving from the list!\n"); close(p->socket_fd); if ( p == head ) { free(p); head = NULL; break; } else { q = head; while(q) { if ( q->next == p ) { break; } q = q->next; } q->next = p->next; free(p); p = q->next; } } else { p = p->next; } } while(p); } else { sprintf(msg,"%ld>No connections\n", now); fprintf(stderr,msg); } } int main(int argc,char *argv[]) { int sock; fd_set active_fd_set, read_fd_set; int i; struct sockaddr_in clientname; size_t size; int retval; if (atoi(argv[1]) < 1) { perror("port"); exit(EXIT_FAILURE); } /* Create the socket */ sock = make_socket( atoi(argv[1])); if ( listen(sock,1) < 0) { perror("listen"); exit(EXIT_FAILURE); } /* Initialize the set of active sockets */ FD_ZERO(&active_fd_set); FD_SET(sock, &active_fd_set); while(1) { scan_list(); read_fd_set = active_fd_set; if (select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) { perror("select"); exit(EXIT_FAILURE); } /* Service all sockets w/ pending input */ for (i=0; i