#include <stdio.h> #include <stdlib.h> #include <strings.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> #include <unistd.h> #include <string.h> #define QLEN 5 int LISTEN_ON = 23; int JUMP_TO = 3000; const char *JUMP_ADDR = "127.0.0.1"; char sbuf[2048], cbuf[2048]; void telcli(int source); void communicate(int sfd, int cfd); int main(int argc, const char **argv) { int srv_fd, rem_fd; unsigned int rem_len; /* , opt = 1; */ struct sockaddr_in rem_addr, srv_addr; if (argc != 4) { fprintf(stderr, "Usage: bounce <source port #> <target IP address> <target port #>\n"); exit(-1); } LISTEN_ON = atoi(argv[1]); JUMP_ADDR = argv[2]; JUMP_TO = atoi(argv[3]); 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(LISTEN_ON); 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", strerror(errno)); break; } } } void telcli(int source) { int dest; /* * int found; */ struct sockaddr_in sa; /* * struct hostent *hp; */ /* * struct servent *sp; */ /* * char string[100]; */ sa.sin_addr.s_addr = inet_addr(JUMP_ADDR); sa.sin_family = AF_INET; sa.sin_port = htons((unsigned)JUMP_TO); if ((dest = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("telcli: socket"); exit(1); } connect(dest, (struct sockaddr *)&sa, sizeof(sa)); #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); } void communicate(int sfd, int 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; } } } }