X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Fnc.c;h=63d8c5b19db9b70b8f16527ac4a3f6e8ed7b5104;hb=9bf9f1edbec05edbf566c3220835440e1b18fcc8;hp=fcacb0c45b45231f634fdc6317475dadf2a6e668;hpb=3570a34de46b1f7dedd16999bb1687e2d6b55d40;p=oweals%2Fbusybox.git diff --git a/networking/nc.c b/networking/nc.c index fcacb0c45..63d8c5b19 100644 --- a/networking/nc.c +++ b/networking/nc.c @@ -25,9 +25,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "busybox.h" + #include #include +#include #include #include @@ -37,51 +38,108 @@ #include #include #include +#include "busybox.h" -#define BUFSIZE 100 +#define GAPING_SECURITY_HOLE int nc_main(int argc, char **argv) { - int sfd; - int result; - int len; - char ch[BUFSIZE]; + int do_listen = 0, lport = 0, delay = 0, tmpfd, opt, sfd, x; + char buf[BUFSIZ]; +#ifdef GAPING_SECURITY_HOLE + char * pr00gie = NULL; +#endif struct sockaddr_in address; struct hostent *hostinfo; fd_set readfds, testfds; - argc--; - argv++; - if (argc < 2 || **(argv + 1) == '-') { - usage(nc_usage); + while ((opt = getopt(argc, argv, "lp:i:e:")) > 0) { + switch (opt) { + case 'l': + do_listen++; + break; + case 'p': + lport = atoi(optarg); + break; + case 'i': + delay = atoi(optarg); + break; +#ifdef GAPING_SECURITY_HOLE + case 'e': + pr00gie = optarg; + break; +#endif + default: + show_usage(); + } } - sfd = socket(AF_INET, SOCK_STREAM, 0); +#ifdef GAPING_SECURITY_HOLE + if (pr00gie) { + /* won't need stdin */ + close (fileno(stdin)); + } +#endif /* GAPING_SECURITY_HOLE */ - hostinfo = (struct hostent *) gethostbyname(*argv); - if (!hostinfo) { - fatalError("cannot resolve %s\n", *argv); - } + if ((do_listen && optind != argc) || (!do_listen && optind + 2 != argc)) + show_usage(); + if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + perror_msg_and_die("socket"); + x = 1; + if (setsockopt (sfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x)) == -1) + perror_msg_and_die ("reuseaddr failed"); address.sin_family = AF_INET; - address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list; - address.sin_port = htons(atoi(*(++argv))); - len = sizeof(address); + if (lport != 0) { + memset(&address.sin_addr, 0, sizeof(address.sin_addr)); + address.sin_port = htons(lport); + + if (bind(sfd, (struct sockaddr *) &address, sizeof(address)) < 0) + perror_msg_and_die("bind"); + } + + if (do_listen) { + socklen_t addrlen = sizeof(address); + + if (listen(sfd, 1) < 0) + perror_msg_and_die("listen"); + + if ((tmpfd = accept(sfd, (struct sockaddr *) &address, &addrlen)) < 0) + perror_msg_and_die("accept"); - result = connect(sfd, (struct sockaddr *) &address, len); + close(sfd); + sfd = tmpfd; + } else { + hostinfo = xgethostbyname(argv[optind]); - if (result < 0) { - perror("nc: connect"); - exit(2); + address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list; + address.sin_port = htons(atoi(argv[optind+1])); + + if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0) + perror_msg_and_die("connect"); + } + +#ifdef GAPING_SECURITY_HOLE + /* -e given? */ + if (pr00gie) { + dup2(sfd, 0); + close(sfd); + dup2 (0, 1); + dup2 (0, 2); + execl (pr00gie, pr00gie, NULL); + /* Don't print stuff or it will go over the wire.... */ + _exit(-1); } +#endif /* GAPING_SECURITY_HOLE */ + FD_ZERO(&readfds); FD_SET(sfd, &readfds); - FD_SET(fileno(stdin), &readfds); + FD_SET(STDIN_FILENO, &readfds); while (1) { int fd; @@ -90,39 +148,29 @@ int nc_main(int argc, char **argv) testfds = readfds; - result = - select(FD_SETSIZE, &testfds, (fd_set *) NULL, (fd_set *) NULL, - (struct timeval *) 0); - - if (result < 1) { - perror("nc: select"); - exit(3); - } + if (select(FD_SETSIZE, &testfds, NULL, NULL, NULL) < 0) + perror_msg_and_die("select"); for (fd = 0; fd < FD_SETSIZE; fd++) { if (FD_ISSET(fd, &testfds)) { - int trn = 0; - int rn; - - ioctl(fd, FIONREAD, &nread); + if ((nread = safe_read(fd, buf, sizeof(buf))) < 0) + perror_msg_and_die("read"); if (fd == sfd) { if (nread == 0) exit(0); - ofd = fileno(stdout); + ofd = STDOUT_FILENO; } else { + if (nread == 0) + shutdown(sfd, 1); ofd = sfd; } - - - do { - rn = (BUFSIZE < nread - trn) ? BUFSIZE : nread - trn; - trn += rn; - read(fd, ch, rn); - write(ofd, ch, rn); + if (full_write(ofd, buf, nread) < 0) + perror_msg_and_die("write"); + if (delay > 0) { + sleep(delay); } - while (trn < nread); } } }