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.
This commit is contained in:
parent
5d8843e451
commit
1cca9484db
@ -19,6 +19,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -2105,23 +2105,41 @@ USE_FEATURE_MDEV_CONFIG( \
|
|||||||
" or\n" \
|
" or\n" \
|
||||||
"$ nameif -c /etc/my_mactab_file\n" \
|
"$ nameif -c /etc/my_mactab_file\n" \
|
||||||
|
|
||||||
#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
|
#if ENABLE_NC_SERVER || ENABLE_NC_EXTRA
|
||||||
# define USAGE_NC_EXEC(a) a
|
#define NC_BR1 "["
|
||||||
|
#define NC_BR2 "]"
|
||||||
#else
|
#else
|
||||||
# define USAGE_NC_EXEC(a)
|
#define NC_BR1
|
||||||
|
#define NC_BR2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define nc_trivial_usage \
|
#define nc_trivial_usage \
|
||||||
"[OPTIONS] [IP] [port]"
|
"[" \
|
||||||
|
NC_BR1 USE_NC_SERVER("-lp")USE_NC_EXTRA("iwf") NC_BR2 \
|
||||||
|
" ["USE_NC_EXTRA("FILENAME|")"{IPADDR PORTNUM}]"USE_NC_EXTRA(" [-e COMMAND]")
|
||||||
#define nc_full_usage \
|
#define nc_full_usage \
|
||||||
"Netcat opens a pipe to IP:port\n\n" \
|
"Netcat opens a pipe, either to IP:port\n\n" \
|
||||||
"Options:\n" \
|
"Options:" \
|
||||||
"\t-l\t\tlisten mode, for inbound connects\n" \
|
USE_NC_EXTRA( \
|
||||||
"\t-p PORT\t\tlocal port number\n" \
|
"\n\t-e\t\texec rest of command line after connect\n" \
|
||||||
"\t-i SECS\t\tdelay interval for lines sent\n" \
|
"\t-i SECS\t\tdelay interval for lines sent\n" \
|
||||||
USAGE_NC_EXEC( \
|
"\t-w SECS\t\ttimeout for connect\n" \
|
||||||
"\t-e PROG\t\tprogram to exec after connect (dangerous!)\n" \
|
"\t-f filename\tuse file (ala /dev/ttyS0) instead of network" \
|
||||||
) \
|
) \
|
||||||
"\t-w SECS\t\ttimeout for connects and final net reads"
|
USE_NC_SERVER( \
|
||||||
|
"\n\t-l\t\tlisten mode, for inbound connects\n" \
|
||||||
|
USE_NC_EXTRA("\t\t\t(use -l twice with -e for persistent server)\n") \
|
||||||
|
"\t-p PORT\t\tlocal port number" \
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#define nc_notes_usage "" \
|
||||||
|
USE_NC_EXTRA( \
|
||||||
|
"To use netcat as a terminal emulator on a serial port:\n\n" \
|
||||||
|
"$ stty 115200 -F /dev/ttyS0\n" \
|
||||||
|
"$ stty raw -echo -ctlecho && nc -f /dev/ttyS0\n" \
|
||||||
|
) ""
|
||||||
|
|
||||||
#define nc_example_usage \
|
#define nc_example_usage \
|
||||||
"$ nc foobar.somedomain.com 25\n" \
|
"$ nc foobar.somedomain.com 25\n" \
|
||||||
"220 foobar ESMTP Exim 3.12 #1 Sat, 15 Apr 2000 00:03:02 -0600\n" \
|
"220 foobar ESMTP Exim 3.12 #1 Sat, 15 Apr 2000 00:03:02 -0600\n" \
|
||||||
|
@ -446,13 +446,21 @@ config CONFIG_NC
|
|||||||
A simple Unix utility which reads and writes data across network
|
A simple Unix utility which reads and writes data across network
|
||||||
connections.
|
connections.
|
||||||
|
|
||||||
config CONFIG_NC_GAPING_SECURITY_HOLE
|
config CONFIG_NC_SERVER
|
||||||
bool "gaping security hole"
|
bool "Netcat server options (-lp)"
|
||||||
default n
|
default n
|
||||||
depends on CONFIG_NC
|
depends on CONFIG_NC
|
||||||
help
|
help
|
||||||
Add support for executing a program after making or receiving a
|
Allow netcat to act as a server.
|
||||||
successful connection (-e option).
|
|
||||||
|
config CONFIG_NC_EXTRA
|
||||||
|
bool "Netcat extensions (-eiw and filename)"
|
||||||
|
default n
|
||||||
|
depends on CONFIG_NC
|
||||||
|
help
|
||||||
|
Add -e (support for executing the rest of the command line after
|
||||||
|
making or receiving a successful connection), -i (delay interval for
|
||||||
|
lines sent), -w (timeout for initial connection).
|
||||||
|
|
||||||
config CONFIG_NETSTAT
|
config CONFIG_NETSTAT
|
||||||
bool "netstat"
|
bool "netstat"
|
||||||
|
204
networking/nc.c
204
networking/nc.c
@ -1,32 +1,16 @@
|
|||||||
/* vi: set sw=4 ts=4: */
|
/* vi: set sw=4 ts=4: */
|
||||||
/* nc: mini-netcat - built from the ground up for LRP
|
/* nc: mini-netcat - built from the ground up for LRP
|
||||||
Copyright (C) 1998 Charles P. Wright
|
*
|
||||||
|
* Copyright (C) 1998, 1999 Charles P. Wright
|
||||||
|
* Copyright (C) 1998 Dave Cinege
|
||||||
|
*
|
||||||
|
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||||
|
*/
|
||||||
|
|
||||||
0.0.1 6K It works.
|
|
||||||
0.0.2 5K Smaller and you can also check the exit condition if you wish.
|
|
||||||
0.0.3 Uses select()
|
|
||||||
|
|
||||||
19980918 Busy Boxed! Dave Cinege
|
|
||||||
19990512 Uses Select. Charles P. Wright
|
|
||||||
19990513 Fixes stdin stupidity and uses buffers. Charles P. Wright
|
|
||||||
|
|
||||||
Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include "busybox.h"
|
#include "busybox.h"
|
||||||
|
|
||||||
|
#define xread bb_xread
|
||||||
|
|
||||||
static void timeout(int signum)
|
static void timeout(int signum)
|
||||||
{
|
{
|
||||||
bb_error_msg_and_die("Timed out");
|
bb_error_msg_and_die("Timed out");
|
||||||
@ -34,79 +18,87 @@ static void timeout(int signum)
|
|||||||
|
|
||||||
int nc_main(int argc, char **argv)
|
int nc_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int do_listen = 0, lport = 0, delay = 0, wsecs = 0, tmpfd, opt, sfd, x;
|
int do_listen = 0, lport = 0, delay = 0, wsecs = 0, execflag = 0, opt,
|
||||||
|
sfd = 0, cfd;
|
||||||
#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
|
|
||||||
char *pr00gie = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct sockaddr_in address;
|
struct sockaddr_in address;
|
||||||
struct hostent *hostinfo;
|
struct hostent *hostinfo;
|
||||||
|
|
||||||
fd_set readfds, testfds;
|
fd_set readfds, testfds;
|
||||||
|
char *infile = NULL;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "lp:i:e:w:")) > 0) {
|
memset(&address, 0, sizeof(address));
|
||||||
switch (opt) {
|
|
||||||
case 'l':
|
if (ENABLE_NC_SERVER || ENABLE_NC_EXTRA) {
|
||||||
do_listen++;
|
while ((opt = getopt(argc, argv, "lp:" USE_NC_EXTRA("i:ew:f:"))) > 0) {
|
||||||
break;
|
if (ENABLE_NC_SERVER && opt=='l') do_listen++;
|
||||||
case 'p':
|
else if (ENABLE_NC_SERVER && opt=='p')
|
||||||
lport = bb_lookup_port(optarg, "tcp", 0);
|
lport = bb_lookup_port(optarg, "tcp", 0);
|
||||||
|
else if (ENABLE_NC_EXTRA && opt=='w') wsecs = atoi(optarg);
|
||||||
|
else if (ENABLE_NC_EXTRA && opt=='i') delay = atoi(optarg);
|
||||||
|
else if (ENABLE_NC_EXTRA && opt=='f') infile = optarg;
|
||||||
|
else if (ENABLE_NC_EXTRA && opt=='e' && optind!=argc) {
|
||||||
|
execflag++;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
} else bb_show_usage();
|
||||||
delay = atoi(optarg);
|
|
||||||
break;
|
|
||||||
#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
|
|
||||||
case 'e':
|
|
||||||
pr00gie = optarg;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case 'w':
|
|
||||||
wsecs = atoi(optarg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
bb_show_usage();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((do_listen && optind != argc) || (!do_listen && optind + 2 != argc))
|
|
||||||
bb_show_usage();
|
// For listen or file we need zero arguments, dialout is 2.
|
||||||
|
// For exec we need at least one more argument at the end, more ok
|
||||||
|
|
||||||
sfd = bb_xsocket(AF_INET, SOCK_STREAM, 0);
|
opt = (do_listen || infile) ? 0 : 2 + execflag;
|
||||||
x = 1;
|
if (execflag ? argc-optind < opt : argc-optind!=opt ||
|
||||||
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x)) == -1)
|
(infile && do_listen))
|
||||||
bb_perror_msg_and_die("reuseaddr");
|
bb_show_usage();
|
||||||
address.sin_family = AF_INET;
|
|
||||||
|
|
||||||
if (wsecs) {
|
if (wsecs) {
|
||||||
signal(SIGALRM, timeout);
|
signal(SIGALRM, timeout);
|
||||||
alarm(wsecs);
|
alarm(wsecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (infile) cfd = bb_xopen(infile, O_RDWR);
|
||||||
|
else {
|
||||||
|
opt = 1;
|
||||||
|
sfd = bb_xsocket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
fcntl(sfd, F_SETFD, FD_CLOEXEC);
|
||||||
|
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt));
|
||||||
|
address.sin_family = AF_INET;
|
||||||
|
|
||||||
if (lport != 0) {
|
// Set local port.
|
||||||
memset(&address.sin_addr, 0, sizeof(address.sin_addr));
|
|
||||||
address.sin_port = lport;
|
|
||||||
|
|
||||||
bb_xbind(sfd, (struct sockaddr *) &address, sizeof(address));
|
if (lport != 0) {
|
||||||
}
|
address.sin_port = lport;
|
||||||
|
|
||||||
if (do_listen) {
|
bb_xbind(sfd, (struct sockaddr *) &address, sizeof(address));
|
||||||
socklen_t addrlen = sizeof(address);
|
}
|
||||||
|
|
||||||
bb_xlisten(sfd, 1);
|
if (do_listen) {
|
||||||
if ((tmpfd = accept(sfd, (struct sockaddr *) &address, &addrlen)) < 0)
|
socklen_t addrlen = sizeof(address);
|
||||||
bb_perror_msg_and_die("accept");
|
|
||||||
|
|
||||||
close(sfd);
|
bb_xlisten(sfd, do_listen);
|
||||||
sfd = tmpfd;
|
|
||||||
} else {
|
|
||||||
hostinfo = xgethostbyname(argv[optind]);
|
|
||||||
|
|
||||||
address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
|
// If we didn't specify a port number, query and print it to stderr.
|
||||||
address.sin_port = bb_lookup_port(argv[optind+1], "tcp", 0);
|
|
||||||
|
|
||||||
if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0)
|
if (!lport) {
|
||||||
bb_perror_msg_and_die("connect");
|
socklen_t len = sizeof(address);
|
||||||
|
getsockname(sfd, &address, &len);
|
||||||
|
fdprintf(2, "%d\n", SWAP_BE16(address.sin_port));
|
||||||
|
}
|
||||||
|
repeatyness:
|
||||||
|
if ((cfd = accept(sfd, (struct sockaddr *) &address, &addrlen)) < 0)
|
||||||
|
bb_perror_msg_and_die("accept");
|
||||||
|
|
||||||
|
if (!execflag) close(sfd);
|
||||||
|
} else {
|
||||||
|
hostinfo = xgethostbyname(argv[optind]);
|
||||||
|
|
||||||
|
address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
|
||||||
|
address.sin_port = bb_lookup_port(argv[optind+1], "tcp", 0);
|
||||||
|
|
||||||
|
if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0)
|
||||||
|
bb_perror_msg_and_die("connect");
|
||||||
|
cfd = sfd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wsecs) {
|
if (wsecs) {
|
||||||
@ -114,24 +106,40 @@ int nc_main(int argc, char **argv)
|
|||||||
signal(SIGALRM, SIG_DFL);
|
signal(SIGALRM, SIG_DFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
|
|
||||||
/* -e given? */
|
/* -e given? */
|
||||||
if (pr00gie) {
|
if (execflag) {
|
||||||
dup2(sfd, 0);
|
if(cfd) {
|
||||||
close(sfd);
|
signal(SIGCHLD, SIG_IGN);
|
||||||
|
dup2(cfd, 0);
|
||||||
|
close(cfd);
|
||||||
|
}
|
||||||
dup2(0, 1);
|
dup2(0, 1);
|
||||||
dup2(0, 2);
|
dup2(0, 2);
|
||||||
execl(pr00gie, pr00gie, NULL);
|
|
||||||
/* Don't print stuff or it will go over the wire.... */
|
|
||||||
_exit(-1);
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_NC_GAPING_SECURITY_HOLE */
|
|
||||||
|
|
||||||
|
// With more than one -l, repeatedly act as server.
|
||||||
|
|
||||||
|
if (do_listen>1 && vfork()) {
|
||||||
|
// This is a bit weird as cleanup goes, since we wind up with no
|
||||||
|
// stdin/stdout/stderr. But it's small and shouldn't hurt anything.
|
||||||
|
// We check for cfd == 0 above.
|
||||||
|
close(0);
|
||||||
|
close(1);
|
||||||
|
close(2);
|
||||||
|
|
||||||
|
goto repeatyness;
|
||||||
|
}
|
||||||
|
execvp(argv[optind], argv+optind);
|
||||||
|
/* Don't print stuff or it will go over the wire.... */
|
||||||
|
_exit(127);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select loop copying stdin to cfd, and cfd to stdout.
|
||||||
|
|
||||||
FD_ZERO(&readfds);
|
FD_ZERO(&readfds);
|
||||||
FD_SET(sfd, &readfds);
|
FD_SET(cfd, &readfds);
|
||||||
FD_SET(STDIN_FILENO, &readfds);
|
FD_SET(STDIN_FILENO, &readfds);
|
||||||
|
|
||||||
while (1) {
|
for (;;) {
|
||||||
int fd;
|
int fd;
|
||||||
int ofd;
|
int ofd;
|
||||||
int nread;
|
int nread;
|
||||||
@ -143,30 +151,24 @@ int nc_main(int argc, char **argv)
|
|||||||
|
|
||||||
for (fd = 0; fd < FD_SETSIZE; fd++) {
|
for (fd = 0; fd < FD_SETSIZE; fd++) {
|
||||||
if (FD_ISSET(fd, &testfds)) {
|
if (FD_ISSET(fd, &testfds)) {
|
||||||
if ((nread = safe_read(fd, bb_common_bufsiz1,
|
nread = xread(fd, bb_common_bufsiz1, sizeof(bb_common_bufsiz1));
|
||||||
sizeof(bb_common_bufsiz1))) < 0)
|
|
||||||
{
|
|
||||||
bb_perror_msg_and_die(bb_msg_read_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd == sfd) {
|
if (fd == cfd) {
|
||||||
if (nread == 0)
|
if (!nread) exit(0);
|
||||||
exit(0);
|
|
||||||
ofd = STDOUT_FILENO;
|
ofd = STDOUT_FILENO;
|
||||||
} else {
|
} else {
|
||||||
if (nread <= 0) {
|
if (!nread) {
|
||||||
shutdown(sfd, 1 /* send */ );
|
// Close outgoing half-connection so they get EOF, but
|
||||||
close(STDIN_FILENO);
|
// leave incoming alone so we can see response.
|
||||||
|
shutdown(cfd, 1);
|
||||||
FD_CLR(STDIN_FILENO, &readfds);
|
FD_CLR(STDIN_FILENO, &readfds);
|
||||||
}
|
}
|
||||||
ofd = sfd;
|
ofd = cfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bb_full_write(ofd, bb_common_bufsiz1, nread) < 0)
|
if (bb_full_write(ofd, bb_common_bufsiz1, nread) < 0)
|
||||||
bb_perror_msg_and_die(bb_msg_write_error);
|
bb_perror_msg_and_die(bb_msg_write_error);
|
||||||
if (delay > 0) {
|
if (delay > 0) sleep(delay);
|
||||||
sleep(delay);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user