netcat: Local socket support

Denys Vlasenko vda.linux at googlemail.com
Wed Apr 22 00:17:16 UTC 2009


Hi Ingo,

Sorry for the delay :(

On Thursday 19 March 2009 13:31, Ingo van Lil wrote:
> 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.

Unfortunately, you patched nc.c instead of nc_bloaty.c,
and nc_bloaty.c is supposed to have "all bells and whistles"
and be compatible, not "small" nc.c


Adding 128-byte struct sockaddr_un to len_and_sockaddr like this:

typedef struct len_and_sockaddr {
        socklen_t len;
        union {
                struct sockaddr sa;
+               struct sockaddr_un sun;
                struct sockaddr_in sin;

will bloat stack and other data for many unrelated applets.
Since you malloc your lsa, you can work around this.


Connecting to UNIX domain socket like this:

-                       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);
+                       }

defeats the whole purpose of len_and_sockaddr data type
and create_and_connect_stream_or_die(name, port) function,
which is _supposed_ to_ derive the type of socket
(AF_INET? AF_INET6? AF_UNIX?...) by looking at its arguments.

Currently, it understands IP and IPv6.

In order to make _all_ network utilities AF_UNIX capable,
it's much better to teach create_and_connect_stream_or_die
to understand some sort of AF_UNIX name.

It can be "unix:" or "local:" prefix, and/or
special port value (although this feels more like a hack,
since port param should not have been there in the first place,
it can be specified in 1st argument, name: "1.2.3.4:56",
"[12:34::56:78]:90" (IPv6), and we do understand these forms)

Unfortunately there is no standard for this syntax. Pity.
We need to invent our own, and then shoehorn nc -U into using it
internally:

echo "hi syslog!" | nc -U /dev/log >/dev/null

and internally nc.c does:

        if (option -U is given)
                 peer_name = xasprintf("local:%s", peer_name);

Tht's *all* what nc.c needs to do to support -U.
The rest is handled in create_and_connect_stream_or_die!

And then you also can do this:

echo "hi syslog!" | nc local:/dev/log >/dev/null

Or this:

httpd -p local:/var/run/httpd.socket

Or this:

tcpsvd -vE local:/var/run/telnet.socket 0 telnetd -i


> 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.

Thanks, took this fix.

--
vda


More information about the busybox mailing list