general purpose telnet bouncer.
Several people have expressed interest in a utility such as this. It's existed for several years but Ive recently decided to fix it up into a releasable condition. Share and enjoy. flames to /dev/null Mark mark@cairo.anu.edu.au ---------------------- cut here ---------------------------- /* Name: ts2.c */ /* Author: Hal-9000, Richard Stevens, Xanadude, Avalon, Mark */ /* Distribution: Public */ /* Copyright: Held by the respective contributors */ /* Posted to USENET 1st September '93 by Mark mark@cairo.anu.edu.au */ /* This file was telserv.c, part of the Telnet Server package v. 1.0, written by "Hal-9000". Much of that package was developed by Richard Stephens and his thanks go to "Xanadude" for providing him with that section. Performance fix by Darren Reed. */ /* Reworked to add concurrency, password checking and destination selection on the fly. - Mark 31st Aug 93 Compiled and tested on: HPUX 9.01 9000/700 series NeXTStep 3.1 NeXT 68040 OSx Pyramid 90x BSD universe SunOS 5.2 sun4c Ultrix 4.3 DEC RISC To compile, type "cc -O -s ts2.c -o ts2". MY_PASSWORD and SERV_TCP_PORT are all that is required to be altered. */ #define MY_PASSWORD "pass" #define SERV_TCP_PORT 12345 /* port I'll listen for connections on */ #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <sys/resource.h> #include <sys/wait.h> #include <fcntl.h> #include <errno.h> #include <netinet/in.h> #include <netdb.h> #include <arpa/inet.h> #include <sys/ioctl.h> #define QLEN 5 char sbuf[2048], cbuf[2048]; extern int errno; extern char *sys_errlist[]; void reaper(); int main(); void telcli(); int main(argc, argv) int argc; char *argv[]; { int srv_fd, rem_fd, rem_len, opt = 1; struct sockaddr_in rem_addr, srv_addr; bzero((char *) &rem_addr, sizeof(rem_addr)); bzero((char *) &srv_addr, sizeof(srv_addr)); srv_addr.sin_family = AF_INET; srv_addr.sin_addr.s_addr = htonl(INADDR_ANY); srv_addr.sin_port = htons(SERV_TCP_PORT); srv_fd = socket(PF_INET, SOCK_STREAM, 0); if (bind(srv_fd, (struct sockaddr *) &srv_addr, sizeof(srv_addr)) == -1) { perror("bind"); exit(-1); } listen(srv_fd, QLEN); close(0); close(1); close(2); #ifdef TIOCNOTTY if ((rem_fd = open("/dev/tty", O_RDWR)) >= 0) { ioctl(rem_fd, TIOCNOTTY, (char *)0); close(rem_fd); } #endif if (fork()) exit(0); while (1) { rem_len = sizeof(rem_addr); rem_fd=accept(srv_fd, (struct sockaddr *) &rem_addr, &rem_len); if (rem_fd < 0) { if (errno == EINTR) continue; exit(-1); } switch(fork()) { case 0: /* child process */ close(srv_fd); /* close original socket */ telcli(rem_fd); /* process the request */ close(rem_fd); exit(0); break; default: close(rem_fd); /* parent process */ if (fork()) exit(0); /* let init worry about children */ break; case -1: fprintf(stderr, "\n\rfork: %s\n\r", sys_errlist[errno]); break; } } } void telcli(source) int source; { int dest; int found; struct sockaddr_in sa; struct hostent *hp; struct servent *sp; char gethost[100]; char getport[100]; char string[100]; bzero(gethost, 100); sprintf(string, "Password: "); write(source, string, strlen(string)); read(source, gethost, 100); gethost[(strlen(gethost)-2)] = '\0'; /* kludge alert - kill the \r\n */ if (strcmp(gethost, MY_PASSWORD) != 0) { sprintf(string, "Wrong password, got %s.\n", gethost); write(source, string, strlen(string)); close(source); exit(0); } do { found = 0; bzero(gethost,100); sprintf(string, "Host: "); write(source, string, strlen(string)); read(source, gethost, 100); gethost[(strlen(gethost)-2)] = '\0'; hp = gethostbyname(gethost); if (hp) { found++; #if !defined(h_addr) /* In 4.3, this is a #define */ #if defined(hpux) || defined(NeXT) || defined(ultrix) || defined(POSIX) memcpy((caddr_t)&sa.sin_addr, hp->h_addr_list[0], hp->h_length); #else bcopy(hp->h_addr_list[0], &sa.sin_addr, hp->h_length); #endif #else /* defined(h_addr) */ #if defined(hpux) || defined(NeXT) || defined(ultrix) || defined(POSIX) memcpy((caddr_t)&sa.sin_addr, hp->h_addr, hp->h_length); #else bcopy(hp->h_addr, &sa.sin_addr, hp->h_length); #endif #endif /* defined(h_addr) */ sprintf(string, "Found address for %s\n", hp->h_name); write(source, string, strlen(string)); } else { if (inet_addr(gethost) == -1) { found = 0; sprintf(string, "Didnt find address for %s\n", gethost); write(source, string, strlen(string)); } else { found++; sa.sin_addr.s_addr = inet_addr(gethost); } } } while (!found); sa.sin_family = AF_INET; sprintf(string, "Port: "); write(source, string, strlen(string)); read(source, getport, 100); gethost[(strlen(getport)-2)] = '\0'; sa.sin_port = htons((unsigned) atoi(getport)); if (sa.sin_port == 0) { sp = getservbyname(getport, "tcp"); if (sp) sa.sin_port = sp->s_port; else { sprintf(string, "%s: bad port number\n", getport); write(source, string, strlen(string)); return; } } sprintf(string, "Trying %s...\n", (char *) inet_ntoa(sa.sin_addr)); write(source, string, strlen(string)); if ((dest = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("telcli: socket"); exit(1); } connect(dest, (struct sockaddr *) &sa, sizeof(sa)); sprintf(string, "Connected to %s port %d...\n", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port)); write(source, string, strlen(string)); #ifdef FNDELAY fcntl(source,F_SETFL,fcntl(source,F_GETFL,0)|FNDELAY); fcntl(dest,F_SETFL,fcntl(dest,F_GETFL,0)|FNDELAY); #else fcntl(source,F_SETFL,O_NDELAY); fcntl(dest,F_SETFL,O_NDELAY); #endif communicate(dest,source); close(dest); exit(0); } communicate(sfd,cfd) { char *chead, *ctail, *shead, *stail; int num, nfd, spos, cpos; extern int errno; fd_set rd, wr; chead = ctail = cbuf; cpos = 0; shead = stail = sbuf; spos = 0; while (1) { FD_ZERO(&rd); FD_ZERO(&wr); if (spos < sizeof(sbuf)-1) FD_SET(sfd, &rd); if (ctail > chead) FD_SET(sfd, &wr); if (cpos < sizeof(cbuf)-1) FD_SET(cfd, &rd); if (stail > shead) FD_SET(cfd, &wr); nfd = select(256, &rd, &wr, 0, 0); if (nfd <= 0) continue; if (FD_ISSET(sfd, &rd)) { num=read(sfd,stail,sizeof(sbuf)-spos); if ((num==-1) && (errno != EWOULDBLOCK)) return; if (num==0) return; if (num>0) { spos += num; stail += num; if (!--nfd) continue; } } if (FD_ISSET(cfd, &rd)) { num=read(cfd,ctail,sizeof(cbuf)-cpos); if ((num==-1) && (errno != EWOULDBLOCK)) return; if (num==0) return; if (num>0) { cpos += num; ctail += num; if (!--nfd) continue; } } if (FD_ISSET(sfd, &wr)) { num=write(sfd,chead,ctail-chead); if ((num==-1) && (errno != EWOULDBLOCK)) return; if (num>0) { chead += num; if (chead == ctail) { chead = ctail = cbuf; cpos = 0; } if (!--nfd) continue; } } if (FD_ISSET(cfd, &wr)) { num=write(cfd,shead,stail-shead); if ((num==-1) && (errno != EWOULDBLOCK)) return; if (num>0) { shead += num; if (shead == stail) { shead = stail = sbuf; spos = 0; } if (!--nfd) continue; } } } } ----------- end of file ------ cut here -------
participants (1)
-
Mark