aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlandley <landley@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-07-10 19:45:20 +0000
committerlandley <landley@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-07-10 19:45:20 +0000
commit3dcbe7a17d6339a39839017189d0f3bbbe985cd2 (patch)
tree71cb84ae857702f57bdced4a1e99b877499bfd4a
parent1edcf4d8e0eacc1998707b726689de836cc1edb1 (diff)
downloadbusybox-w32-3dcbe7a17d6339a39839017189d0f3bbbe985cd2.tar.gz
busybox-w32-3dcbe7a17d6339a39839017189d0f3bbbe985cd2.tar.bz2
busybox-w32-3dcbe7a17d6339a39839017189d0f3bbbe985cd2.zip
Upgrade netcat a lot. Make -e able to take the rest of the command line as
what to exec. Add -f mode and a brief explanation of how to use it to replace minicom. Add -l -l mode so you can turn any command into a server. And group all of netcat's command line options under two CONFIG entries, so if you disable both it doesn't use getopt at all. git-svn-id: svn://busybox.net/trunk/busybox@15675 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--include/libbb.h1
-rw-r--r--include/usage.h42
-rw-r--r--networking/Config.in16
-rw-r--r--networking/nc.c202
4 files changed, 145 insertions, 116 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 6d6213901..af45511d4 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -19,6 +19,7 @@
19#include <fcntl.h> 19#include <fcntl.h>
20#include <inttypes.h> 20#include <inttypes.h>
21#include <netdb.h> 21#include <netdb.h>
22#include <signal.h>
22#include <stdio.h> 23#include <stdio.h>
23#include <stdlib.h> 24#include <stdlib.h>
24#include <stdarg.h> 25#include <stdarg.h>
diff --git a/include/usage.h b/include/usage.h
index 3c1fb18e9..7c63e2f85 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -2105,23 +2105,41 @@ USE_FEATURE_MDEV_CONFIG( \
2105 " or\n" \ 2105 " or\n" \
2106 "$ nameif -c /etc/my_mactab_file\n" \ 2106 "$ nameif -c /etc/my_mactab_file\n" \
2107 2107
2108#ifdef CONFIG_NC_GAPING_SECURITY_HOLE 2108#if ENABLE_NC_SERVER || ENABLE_NC_EXTRA
2109# define USAGE_NC_EXEC(a) a 2109#define NC_BR1 "["
2110#define NC_BR2 "]"
2110#else 2111#else
2111# define USAGE_NC_EXEC(a) 2112#define NC_BR1
2113#define NC_BR2
2112#endif 2114#endif
2115
2113#define nc_trivial_usage \ 2116#define nc_trivial_usage \
2114 "[OPTIONS] [IP] [port]" 2117 "[" \
2118 NC_BR1 USE_NC_SERVER("-lp")USE_NC_EXTRA("iwf") NC_BR2 \
2119 " ["USE_NC_EXTRA("FILENAME|")"{IPADDR PORTNUM}]"USE_NC_EXTRA(" [-e COMMAND]")
2115#define nc_full_usage \ 2120#define nc_full_usage \
2116 "Netcat opens a pipe to IP:port\n\n" \ 2121 "Netcat opens a pipe, either to IP:port\n\n" \
2117 "Options:\n" \ 2122 "Options:" \
2118 "\t-l\t\tlisten mode, for inbound connects\n" \ 2123 USE_NC_EXTRA( \
2119 "\t-p PORT\t\tlocal port number\n" \ 2124 "\n\t-e\t\texec rest of command line after connect\n" \
2120 "\t-i SECS\t\tdelay interval for lines sent\n" \ 2125 "\t-i SECS\t\tdelay interval for lines sent\n" \
2121 USAGE_NC_EXEC( \ 2126 "\t-w SECS\t\ttimeout for connect\n" \
2122 "\t-e PROG\t\tprogram to exec after connect (dangerous!)\n" \ 2127 "\t-f filename\tuse file (ala /dev/ttyS0) instead of network" \
2123 ) \ 2128 ) \
2124 "\t-w SECS\t\ttimeout for connects and final net reads" 2129 USE_NC_SERVER( \
2130 "\n\t-l\t\tlisten mode, for inbound connects\n" \
2131 USE_NC_EXTRA("\t\t\t(use -l twice with -e for persistent server)\n") \
2132 "\t-p PORT\t\tlocal port number" \
2133 )
2134
2135
2136#define nc_notes_usage "" \
2137 USE_NC_EXTRA( \
2138 "To use netcat as a terminal emulator on a serial port:\n\n" \
2139 "$ stty 115200 -F /dev/ttyS0\n" \
2140 "$ stty raw -echo -ctlecho && nc -f /dev/ttyS0\n" \
2141 ) ""
2142
2125#define nc_example_usage \ 2143#define nc_example_usage \
2126 "$ nc foobar.somedomain.com 25\n" \ 2144 "$ nc foobar.somedomain.com 25\n" \
2127 "220 foobar ESMTP Exim 3.12 #1 Sat, 15 Apr 2000 00:03:02 -0600\n" \ 2145 "220 foobar ESMTP Exim 3.12 #1 Sat, 15 Apr 2000 00:03:02 -0600\n" \
diff --git a/networking/Config.in b/networking/Config.in
index e95ae0d74..e5eb11caa 100644
--- a/networking/Config.in
+++ b/networking/Config.in
@@ -446,13 +446,21 @@ config CONFIG_NC
446 A simple Unix utility which reads and writes data across network 446 A simple Unix utility which reads and writes data across network
447 connections. 447 connections.
448 448
449config CONFIG_NC_GAPING_SECURITY_HOLE 449config CONFIG_NC_SERVER
450 bool "gaping security hole" 450 bool "Netcat server options (-lp)"
451 default n 451 default n
452 depends on CONFIG_NC 452 depends on CONFIG_NC
453 help 453 help
454 Add support for executing a program after making or receiving a 454 Allow netcat to act as a server.
455 successful connection (-e option). 455
456config CONFIG_NC_EXTRA
457 bool "Netcat extensions (-eiw and filename)"
458 default n
459 depends on CONFIG_NC
460 help
461 Add -e (support for executing the rest of the command line after
462 making or receiving a successful connection), -i (delay interval for
463 lines sent), -w (timeout for initial connection).
456 464
457config CONFIG_NETSTAT 465config CONFIG_NETSTAT
458 bool "netstat" 466 bool "netstat"
diff --git a/networking/nc.c b/networking/nc.c
index 24f1aa5a5..bda0c407b 100644
--- a/networking/nc.c
+++ b/networking/nc.c
@@ -1,32 +1,16 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* nc: mini-netcat - built from the ground up for LRP 2/* nc: mini-netcat - built from the ground up for LRP
3 Copyright (C) 1998 Charles P. Wright 3 *
4 4 * Copyright (C) 1998, 1999 Charles P. Wright
5 0.0.1 6K It works. 5 * Copyright (C) 1998 Dave Cinege
6 0.0.2 5K Smaller and you can also check the exit condition if you wish. 6 *
7 0.0.3 Uses select() 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8 8 */
9 19980918 Busy Boxed! Dave Cinege 9
10 19990512 Uses Select. Charles P. Wright
11 19990513 Fixes stdin stupidity and uses buffers. Charles P. Wright
12
13 Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
14*/
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <unistd.h>
20#include <signal.h>
21
22#include <sys/types.h>
23#include <sys/socket.h>
24#include <netinet/in.h>
25#include <arpa/inet.h>
26#include <netdb.h>
27#include <sys/ioctl.h>
28#include "busybox.h" 10#include "busybox.h"
29 11
12#define xread bb_xread
13
30static void timeout(int signum) 14static void timeout(int signum)
31{ 15{
32 bb_error_msg_and_die("Timed out"); 16 bb_error_msg_and_die("Timed out");
@@ -34,79 +18,87 @@ static void timeout(int signum)
34 18
35int nc_main(int argc, char **argv) 19int nc_main(int argc, char **argv)
36{ 20{
37 int do_listen = 0, lport = 0, delay = 0, wsecs = 0, tmpfd, opt, sfd, x; 21 int do_listen = 0, lport = 0, delay = 0, wsecs = 0, execflag = 0, opt,
38 22 sfd = 0, cfd;
39#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
40 char *pr00gie = NULL;
41#endif
42
43 struct sockaddr_in address; 23 struct sockaddr_in address;
44 struct hostent *hostinfo; 24 struct hostent *hostinfo;
45
46 fd_set readfds, testfds; 25 fd_set readfds, testfds;
26 char *infile = NULL;
47 27
48 while ((opt = getopt(argc, argv, "lp:i:e:w:")) > 0) { 28 memset(&address, 0, sizeof(address));
49 switch (opt) { 29
50 case 'l': 30 if (ENABLE_NC_SERVER || ENABLE_NC_EXTRA) {
51 do_listen++; 31 while ((opt = getopt(argc, argv, "lp:" USE_NC_EXTRA("i:ew:f:"))) > 0) {
52 break; 32 if (ENABLE_NC_SERVER && opt=='l') do_listen++;
53 case 'p': 33 else if (ENABLE_NC_SERVER && opt=='p')
54 lport = bb_lookup_port(optarg, "tcp", 0); 34 lport = bb_lookup_port(optarg, "tcp", 0);
35 else if (ENABLE_NC_EXTRA && opt=='w') wsecs = atoi(optarg);
36 else if (ENABLE_NC_EXTRA && opt=='i') delay = atoi(optarg);
37 else if (ENABLE_NC_EXTRA && opt=='f') infile = optarg;
38 else if (ENABLE_NC_EXTRA && opt=='e' && optind!=argc) {
39 execflag++;
55 break; 40 break;
56 case 'i': 41 } else bb_show_usage();
57 delay = atoi(optarg);
58 break;
59#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
60 case 'e':
61 pr00gie = optarg;
62 break;
63#endif
64 case 'w':
65 wsecs = atoi(optarg);
66 break;
67 default:
68 bb_show_usage();
69 } 42 }
70 } 43 }
71 44
72 if ((do_listen && optind != argc) || (!do_listen && optind + 2 != argc)) 45
73 bb_show_usage(); 46 // For listen or file we need zero arguments, dialout is 2.
47 // For exec we need at least one more argument at the end, more ok
74 48
75 sfd = bb_xsocket(AF_INET, SOCK_STREAM, 0); 49 opt = (do_listen || infile) ? 0 : 2 + execflag;
76 x = 1; 50 if (execflag ? argc-optind < opt : argc-optind!=opt ||
77 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x)) == -1) 51 (infile && do_listen))
78 bb_perror_msg_and_die("reuseaddr"); 52 bb_show_usage();
79 address.sin_family = AF_INET;
80 53
81 if (wsecs) { 54 if (wsecs) {
82 signal(SIGALRM, timeout); 55 signal(SIGALRM, timeout);
83 alarm(wsecs); 56 alarm(wsecs);
84 } 57 }
58
59 if (infile) cfd = bb_xopen(infile, O_RDWR);
60 else {
61 opt = 1;
62 sfd = bb_xsocket(AF_INET, SOCK_STREAM, 0);
63 fcntl(sfd, F_SETFD, FD_CLOEXEC);
64 setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt));
65 address.sin_family = AF_INET;
85 66
86 if (lport != 0) { 67 // Set local port.
87 memset(&address.sin_addr, 0, sizeof(address.sin_addr));
88 address.sin_port = lport;
89 68
90 bb_xbind(sfd, (struct sockaddr *) &address, sizeof(address)); 69 if (lport != 0) {
91 } 70 address.sin_port = lport;
71
72 bb_xbind(sfd, (struct sockaddr *) &address, sizeof(address));
73 }
74
75 if (do_listen) {
76 socklen_t addrlen = sizeof(address);
77
78 bb_xlisten(sfd, do_listen);
92 79
93 if (do_listen) { 80 // If we didn't specify a port number, query and print it to stderr.
94 socklen_t addrlen = sizeof(address);
95 81
96 bb_xlisten(sfd, 1); 82 if (!lport) {
97 if ((tmpfd = accept(sfd, (struct sockaddr *) &address, &addrlen)) < 0) 83 socklen_t len = sizeof(address);
98 bb_perror_msg_and_die("accept"); 84 getsockname(sfd, &address, &len);
85 fdprintf(2, "%d\n", SWAP_BE16(address.sin_port));
86 }
87repeatyness:
88 if ((cfd = accept(sfd, (struct sockaddr *) &address, &addrlen)) < 0)
89 bb_perror_msg_and_die("accept");
99 90
100 close(sfd); 91 if (!execflag) close(sfd);
101 sfd = tmpfd; 92 } else {
102 } else { 93 hostinfo = xgethostbyname(argv[optind]);
103 hostinfo = xgethostbyname(argv[optind]);
104 94
105 address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list; 95 address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
106 address.sin_port = bb_lookup_port(argv[optind+1], "tcp", 0); 96 address.sin_port = bb_lookup_port(argv[optind+1], "tcp", 0);
107 97
108 if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0) 98 if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0)
109 bb_perror_msg_and_die("connect"); 99 bb_perror_msg_and_die("connect");
100 cfd = sfd;
101 }
110 } 102 }
111 103
112 if (wsecs) { 104 if (wsecs) {
@@ -114,24 +106,40 @@ int nc_main(int argc, char **argv)
114 signal(SIGALRM, SIG_DFL); 106 signal(SIGALRM, SIG_DFL);
115 } 107 }
116 108
117#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
118 /* -e given? */ 109 /* -e given? */
119 if (pr00gie) { 110 if (execflag) {
120 dup2(sfd, 0); 111 if(cfd) {
121 close(sfd); 112 signal(SIGCHLD, SIG_IGN);
113 dup2(cfd, 0);
114 close(cfd);
115 }
122 dup2(0, 1); 116 dup2(0, 1);
123 dup2(0, 2); 117 dup2(0, 2);
124 execl(pr00gie, pr00gie, NULL); 118
119 // With more than one -l, repeatedly act as server.
120
121 if (do_listen>1 && vfork()) {
122 // This is a bit weird as cleanup goes, since we wind up with no
123 // stdin/stdout/stderr. But it's small and shouldn't hurt anything.
124 // We check for cfd == 0 above.
125 close(0);
126 close(1);
127 close(2);
128
129 goto repeatyness;
130 }
131 execvp(argv[optind], argv+optind);
125 /* Don't print stuff or it will go over the wire.... */ 132 /* Don't print stuff or it will go over the wire.... */
126 _exit(-1); 133 _exit(127);
127 } 134 }
128#endif /* CONFIG_NC_GAPING_SECURITY_HOLE */
129 135
136 // Select loop copying stdin to cfd, and cfd to stdout.
137
130 FD_ZERO(&readfds); 138 FD_ZERO(&readfds);
131 FD_SET(sfd, &readfds); 139 FD_SET(cfd, &readfds);
132 FD_SET(STDIN_FILENO, &readfds); 140 FD_SET(STDIN_FILENO, &readfds);
133 141
134 while (1) { 142 for (;;) {
135 int fd; 143 int fd;
136 int ofd; 144 int ofd;
137 int nread; 145 int nread;
@@ -143,30 +151,24 @@ int nc_main(int argc, char **argv)
143 151
144 for (fd = 0; fd < FD_SETSIZE; fd++) { 152 for (fd = 0; fd < FD_SETSIZE; fd++) {
145 if (FD_ISSET(fd, &testfds)) { 153 if (FD_ISSET(fd, &testfds)) {
146 if ((nread = safe_read(fd, bb_common_bufsiz1, 154 nread = xread(fd, bb_common_bufsiz1, sizeof(bb_common_bufsiz1));
147 sizeof(bb_common_bufsiz1))) < 0)
148 {
149 bb_perror_msg_and_die(bb_msg_read_error);
150 }
151 155
152 if (fd == sfd) { 156 if (fd == cfd) {
153 if (nread == 0) 157 if (!nread) exit(0);
154 exit(0);
155 ofd = STDOUT_FILENO; 158 ofd = STDOUT_FILENO;
156 } else { 159 } else {
157 if (nread <= 0) { 160 if (!nread) {
158 shutdown(sfd, 1 /* send */ ); 161 // Close outgoing half-connection so they get EOF, but
159 close(STDIN_FILENO); 162 // leave incoming alone so we can see response.
163 shutdown(cfd, 1);
160 FD_CLR(STDIN_FILENO, &readfds); 164 FD_CLR(STDIN_FILENO, &readfds);
161 } 165 }
162 ofd = sfd; 166 ofd = cfd;
163 } 167 }
164 168
165 if (bb_full_write(ofd, bb_common_bufsiz1, nread) < 0) 169 if (bb_full_write(ofd, bb_common_bufsiz1, nread) < 0)
166 bb_perror_msg_and_die(bb_msg_write_error); 170 bb_perror_msg_and_die(bb_msg_write_error);
167 if (delay > 0) { 171 if (delay > 0) sleep(delay);
168 sleep(delay);
169 }
170 } 172 }
171 } 173 }
172 } 174 }