diff options
author | landley <landley@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-07-10 19:45:20 +0000 |
---|---|---|
committer | landley <landley@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-07-10 19:45:20 +0000 |
commit | 3dcbe7a17d6339a39839017189d0f3bbbe985cd2 (patch) | |
tree | 71cb84ae857702f57bdced4a1e99b877499bfd4a | |
parent | 1edcf4d8e0eacc1998707b726689de836cc1edb1 (diff) | |
download | busybox-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.h | 1 | ||||
-rw-r--r-- | include/usage.h | 42 | ||||
-rw-r--r-- | networking/Config.in | 16 | ||||
-rw-r--r-- | networking/nc.c | 202 |
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 | ||
449 | config CONFIG_NC_GAPING_SECURITY_HOLE | 449 | config 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 | |
456 | config 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 | ||
457 | config CONFIG_NETSTAT | 465 | config 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 | |||
30 | static void timeout(int signum) | 14 | static 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 | ||
35 | int nc_main(int argc, char **argv) | 19 | int 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 | } | ||
87 | repeatyness: | ||
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 | } |