diff options
author | Tom Cherry <tomcherry@google.com> | 2019-06-28 16:48:34 -0700 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2019-07-01 15:21:00 -0500 |
commit | a55b7d7094072cfdc2f818f63633a89cff8f7cd5 (patch) | |
tree | 2b26a052c008b7c1d3d6203fe8aa9d91269e213e | |
parent | 5beb9842ed71aeb0a6644666a857f4e1e5e94619 (diff) | |
download | toybox-a55b7d7094072cfdc2f818f63633a89cff8f7cd5.tar.gz |
netcat: Add UNIX domain socket support (-U)
Other implementations of netcat support UNIX domain sockets via -U, so
this change adds it to toybox too.
Example usage:
Create ./uds as a UNIX domain socket and listen on it, forwarding
messages to bash:
> nc -U -s ./uds -L /bin/bash
Connect to ./uds as a UNIX domain socket
> nc -U ./uds
-rw-r--r-- | toys/net/netcat.c | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/toys/net/netcat.c b/toys/net/netcat.c index 833d32ae..65c41ace 100644 --- a/toys/net/netcat.c +++ b/toys/net/netcat.c @@ -7,13 +7,13 @@ * netcat -L zombies USE_NETCAT(OLDTOY(nc, netcat, TOYFLAG_USR|TOYFLAG_BIN)) -USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("^tlL")"w#<1W#<1p#<1>65535q#<1s:f:46u"USE_NETCAT_LISTEN("[!tlL][!Lw]")"[!46]", TOYFLAG_BIN)) +USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("^tlL")"w#<1W#<1p#<1>65535q#<1s:f:46uU"USE_NETCAT_LISTEN("[!tlL][!Lw]")"[!46U]", TOYFLAG_BIN)) config NETCAT bool "netcat" default y help - usage: netcat [-46] [-u] [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME} + usage: netcat [-46U] [-u] [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME} Forward stdin/stdout to a file or network connection. @@ -24,6 +24,7 @@ config NETCAT -q Quit SECONDS after EOF on stdin, even if stdout hasn't closed yet -s Local source address -u Use UDP + -U Use a UNIX domain socket -w SECONDS timeout to establish connection -W SECONDS timeout for more data on an idle connection @@ -85,11 +86,13 @@ void netcat_main(void) // The argument parsing logic can't make "<2" conditional on other // arguments like -f and -l, so do it by hand here. if ((toys.optflags&FLAG_f) ? toys.optc : - (!(toys.optflags&(FLAG_l|FLAG_L)) && toys.optc!=2)) + (!(toys.optflags&(FLAG_l|FLAG_L)) && + toys.optc!=(toys.optflags&FLAG_U?1:2))) help_exit("bad argument count"); if (toys.optflags&FLAG_4) family = AF_INET; else if (toys.optflags&FLAG_6) family = AF_INET6; + else if (toys.optflags&FLAG_U) family = AF_UNIX; if (toys.optflags&FLAG_u) type = SOCK_DGRAM; @@ -97,9 +100,28 @@ void netcat_main(void) else { // Setup socket if (!(toys.optflags&(FLAG_L|FLAG_l))) { - struct addrinfo *addr = xgetaddrinfo(toys.optargs[0], toys.optargs[1], - family, type, 0, 0); - sockfd = xconnect(addr); + if (toys.optflags&FLAG_U) { + struct sockaddr_un sockaddr; + + memset(&sockaddr, 0, sizeof(struct sockaddr_un)); + + if (strlen(toys.optargs[0]) + 1 > sizeof(sockaddr.sun_path)) + error_exit("socket path too long %s", toys.optargs[0]); + strcpy(sockaddr.sun_path, toys.optargs[0]); + sockaddr.sun_family = AF_UNIX; + + sockfd = xsocket(AF_UNIX, type | SOCK_CLOEXEC, 0); + if (connect(sockfd, (struct sockaddr*)&sockaddr, + sizeof(sockaddr)) != 0) { + perror_exit("could not bind to unix domain socket"); + } + + } else { + struct addrinfo *addr = xgetaddrinfo(toys.optargs[0], toys.optargs[1], + family, type, 0, 0); + + sockfd = xconnect(addr); + } // We have a connection. Disarm timeout. set_alarm(0); @@ -109,14 +131,33 @@ void netcat_main(void) pollinate(in1, in2, out1, out2, TT.W, TT.q); } else { // Listen for incoming connections - struct sockaddr* address = (void*)toybuf; - socklen_t len = sizeof(struct sockaddr_storage); + if (toys.optflags&FLAG_U) { + struct sockaddr_un sockaddr; + + memset(&sockaddr, 0, sizeof(struct sockaddr_un)); + + if (!(toys.optflags&FLAG_s)) + error_exit("-s must be provided if using -U with -L/-l"); - sprintf(toybuf, "%ld", TT.p); - sockfd = xbind(xgetaddrinfo(TT.s, toybuf, family, type, 0, 0)); + if (strlen(TT.s) + 1 > sizeof(sockaddr.sun_path)) + error_exit("socket path too long %s", TT.s); + strcpy(sockaddr.sun_path, TT.s); + sockaddr.sun_family = AF_UNIX; + + sockfd = xsocket(AF_UNIX, type | SOCK_CLOEXEC, 0); + if (bind(sockfd, (struct sockaddr*)&sockaddr, + sizeof(struct sockaddr_un)) != 0) { + perror_exit("unable to bind to UNIX domain socket"); + } + } else { + sprintf(toybuf, "%ld", TT.p); + sockfd = xbind(xgetaddrinfo(TT.s, toybuf, family, type, 0, 0)); + } if (listen(sockfd, 5)) error_exit("listen"); - if (!TT.p) { + if (!TT.p && !(toys.optflags&FLAG_U)) { + struct sockaddr* address = (void*)toybuf; + socklen_t len = sizeof(struct sockaddr_storage); short port_be; getsockname(sockfd, address, &len); @@ -136,7 +177,7 @@ void netcat_main(void) do { child = 0; - in1 = out2 = accept(sockfd, (struct sockaddr *)address, &len); + in1 = out2 = accept(sockfd, NULL, NULL); if (in1<0) perror_exit("accept"); // We have a connection. Disarm timeout. |