[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