[prev in list] [next in list] [prev in thread] [next in thread]
List: busybox
Subject: netcat: Local socket support
From: Ingo van Lil <inguin () gmx ! de>
Date: 2009-03-19 12:31:43
Message-ID: 49C23B2F.6040609 () gmx ! de
[Download RAW message or body]
Hi there,
I have created a little patch to add support for local (Unix domain)
socket connections to Busybox's netcat implementation. An equivalent
feature is available in the OpenBSD version of netcat [1], which is
packaged by Fedora. Additionally, the patch fixes a minor memleak in
nc's server mode, where the sockaddr_and_len structure allocated by
xsocket_stream() isn't freed.
Regards,
Ingo
[1] http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/nc/
["busybox-nc-local.patch" (text/plain)]
Index: networking/nc.c
===================================================================
--- networking/nc.c (revision 190376)
+++ networking/nc.c (working copy)
@@ -34,6 +34,7 @@
SKIP_NC_EXTRA (const) unsigned delay = 0;
SKIP_NC_EXTRA (const int execparam = 0;)
USE_NC_EXTRA (char **execparam = NULL;)
+ SKIP_NC_EXTRA (const) unsigned do_local = 0;
len_and_sockaddr *lsa;
fd_set readfds, testfds;
int opt; /* must be signed (getopt returns -1) */
@@ -42,7 +43,7 @@
/* getopt32 is _almost_ usable:
** it cannot handle "... -e prog -prog-opt" */
while ((opt = getopt(argc, argv,
- "" USE_NC_SERVER("lp:") USE_NC_EXTRA("w:i:f:e:") )) > 0
+ "" USE_NC_SERVER("lp:") USE_NC_EXTRA("w:i:f:Ue:") )) > 0
) {
if (ENABLE_NC_SERVER && opt=='l')
USE_NC_SERVER(do_listen++);
@@ -54,6 +55,8 @@
USE_NC_EXTRA( delay = xatou(optarg));
else if (ENABLE_NC_EXTRA && opt=='f')
USE_NC_EXTRA( cfd = xopen(optarg, O_RDWR));
+ else if (ENABLE_NC_EXTRA && opt=='U')
+ USE_NC_EXTRA(do_local++);
else if (ENABLE_NC_EXTRA && opt=='e' && optind <= argc) {
/* We cannot just 'break'. We should let getopt finish.
** Or else we won't be able to find where
@@ -80,8 +83,11 @@
argc -= optind;
// -l and -f don't mix
if (do_listen && cfd) bb_show_usage();
- // Listen or file modes need zero arguments, client mode needs 2
- if (do_listen || cfd) {
+ // Local mode needs one argument, listen or file modes need zero,
+ // client mode needs 2
+ if (do_local) {
+ if (argc != 1) bb_show_usage();
+ } else if (do_listen || cfd) {
if (argc) bb_show_usage();
} else {
if (!argc || argc > 2) bb_show_usage();
@@ -99,23 +105,34 @@
if (!cfd) {
if (do_listen) {
- /* create_and_bind_stream_or_die(NULL, lport)
- * would've work wonderfully, but we need
- * to know lsa */
- sfd = xsocket_stream(&lsa);
- if (lport)
- set_nport(lsa, htons(lport));
- setsockopt_reuseaddr(sfd);
+ if (do_local) {
+ lsa = xzalloc(sizeof(*lsa));
+ lsa->len = sizeof(lsa->u.sun);
+ lsa->u.sa.sa_family = AF_UNIX;
+ safe_strncpy(lsa->u.sun.sun_path,
+ argv[0], sizeof(lsa->u.sun.sun_path));
+ unlink(lsa->u.sun.sun_path);
+ sfd = xsocket(AF_UNIX, SOCK_STREAM, 0);
+ } else {
+ /* create_and_bind_stream_or_die(NULL, lport)
+ * would've work wonderfully, but we need
+ * to know lsa */
+ sfd = xsocket_stream(&lsa);
+ if (lport)
+ set_nport(lsa, htons(lport));
+ setsockopt_reuseaddr(sfd);
+ }
xbind(sfd, &lsa->u.sa, lsa->len);
xlisten(sfd, do_listen); /* can be > 1 */
/* If we didn't specify a port number,
* query and print it after listen() */
- if (!lport) {
+ if (!do_local && !lport) {
socklen_t addrlen = lsa->len;
getsockname(sfd, &lsa->u.sa, &addrlen);
lport = get_nport(&lsa->u.sa);
fdprintf(2, "%d\n", ntohs(lport));
}
+ free(lsa);
close_on_exec_on(sfd);
accept_again:
cfd = accept(sfd, NULL, 0);
@@ -124,8 +141,19 @@
if (!execparam)
close(sfd);
} else {
- cfd = create_and_connect_stream_or_die(argv[0],
- argv[1] ? bb_lookup_port(argv[1], "tcp", 0) : 0);
+ if (do_local) {
+ lsa = xzalloc(sizeof(*lsa));
+ lsa->len = sizeof(lsa->u.sun);
+ lsa->u.sa.sa_family = AF_UNIX;
+ safe_strncpy(lsa->u.sun.sun_path,
+ argv[0], sizeof(lsa->u.sun.sun_path));
+ cfd = xsocket(AF_UNIX, SOCK_STREAM, 0);
+ xconnect(cfd, &lsa->u.sa, lsa->len);
+ free(lsa);
+ } else {
+ cfd = create_and_connect_stream_or_die(argv[0],
+ argv[1] ? bb_lookup_port(argv[1], "tcp", 0) : 0);
+ }
}
}
Index: Config.erla
===================================================================
--- Config.erla (revision 190376)
+++ Config.erla (working copy)
@@ -686,7 +686,7 @@
# CONFIG_FEATURE_NAMEIF_EXTENDED is not set
CONFIG_NC=y
# CONFIG_NC_SERVER is not set
-# CONFIG_NC_EXTRA is not set
+CONFIG_NC_EXTRA=y
CONFIG_NETSTAT=y
CONFIG_FEATURE_NETSTAT_WIDE=y
# CONFIG_FEATURE_NETSTAT_PRG is not set
Index: include/usage.h
===================================================================
--- include/usage.h (revision 190376)
+++ include/usage.h (working copy)
@@ -2784,7 +2784,7 @@
#endif
#define nc_trivial_usage \
- USE_NC_EXTRA("[-iN] [-wN] ")USE_NC_SERVER("[-l] [-p PORT] ") \
+ USE_NC_EXTRA("[-iN] [-wN] ")USE_NC_SERVER("[-l] [-p PORT] [-U] ") \
"["USE_NC_EXTRA("-f FILENAME|")"IPADDR PORTNUM]"USE_NC_EXTRA(" [-e COMMAND]")
#define nc_full_usage "\n\n" \
"Open a pipe to IP:port" USE_NC_EXTRA(" or file") \
@@ -2800,6 +2800,7 @@
USE_NC_EXTRA( \
"\n (use -l twice with -e for persistent server)") \
"\n -p PORT Local port number" \
+ "\n -U Use UNIX domain socket" \
)
#define nc_notes_usage "" \
Index: include/libbb.h
===================================================================
--- include/libbb.h (revision 190376)
+++ include/libbb.h (working copy)
@@ -33,6 +33,7 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <sys/un.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
@@ -444,6 +445,7 @@
socklen_t len;
union {
struct sockaddr sa;
+ struct sockaddr_un sun;
struct sockaddr_in sin;
#if ENABLE_FEATURE_IPV6
struct sockaddr_in6 sin6;
@@ -455,6 +457,7 @@
LSA_SIZEOF_SA = sizeof(
union {
struct sockaddr sa;
+ struct sockaddr_un sun;
struct sockaddr_in sin;
#if ENABLE_FEATURE_IPV6
struct sockaddr_in6 sin6;
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic