diff options
author | Jeremy Evans <jeremy@cvs.openbsd.org> | 2011-01-08 00:44:20 +0000 |
---|---|---|
committer | Jeremy Evans <jeremy@cvs.openbsd.org> | 2011-01-08 00:44:20 +0000 |
commit | 8f3623d08d2ea87f7d62d1b114b849f426dcee6d (patch) | |
tree | b83fe91ad6fa36c7fdae0ac525a683bb2e3348a9 /usr.bin | |
parent | e39ad44ca931953c1004f94eb5b89ad7e2f59df0 (diff) |
Support unix domain sockets in nc(1) with -Uu.
Previously, using -U with -u was an error that was not documented
in the man page. Now it will use a unix socket in datagram mode.
Bidirectional unix datagram communication requires a socket at
both ends, so in client mode (without -l), a temporary socket is
created so that responses from the server can be received.
If -s is specified with -U and -u, it specifies the location of
the temporary socket to create.
This was mostly written way back in 2007. Since then, various
improvements implemented based on suggestions from guenther@,
tedu@, and nicm@. Man page help from nicm@ and jmc@.
Unix datagram support requires a small change to atomicio.c
in order to function correctly, this will be committed separately
shortly.
OK nicm@
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/nc/nc.1 | 18 | ||||
-rw-r--r-- | usr.bin/nc/netcat.c | 90 |
2 files changed, 83 insertions, 25 deletions
diff --git a/usr.bin/nc/nc.1 b/usr.bin/nc/nc.1 index c2599ce3f13..8745528040b 100644 --- a/usr.bin/nc/nc.1 +++ b/usr.bin/nc/nc.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: nc.1,v 1.55 2010/07/25 07:51:39 guenther Exp $ +.\" $OpenBSD: nc.1,v 1.56 2011/01/08 00:44:19 jeremy Exp $ .\" .\" Copyright (c) 1996 David Sacerdote .\" All rights reserved. @@ -25,7 +25,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: July 25 2010 $ +.Dd $Mdocdate: January 8 2011 $ .Dt NC 1 .Os .Sh NAME @@ -155,6 +155,10 @@ assigns them. Enables the RFC 2385 TCP MD5 signature option. .It Fl s Ar source_ip_address Specifies the IP of the interface which is used to send the packets. +For +.Ux Ns -domain +datagram sockets, specifies the local temporary socket file +to create and use so that datagrams can be received. It is an error to use this option in conjunction with the .Fl l option. @@ -179,6 +183,16 @@ Specifies to use sockets. .It Fl u Use UDP instead of the default option of TCP. +For +.Ux Ns -domain +sockets, use a datagram socket instead of a stream socket. +If a +.Ux Ns -domain +socket is used, a temporary receiving socket is created in +.Pa /tmp +unless the +.Fl s +flag is given. .It Fl V Ar rtable Set the routing table to be used. The default is 0. diff --git a/usr.bin/nc/netcat.c b/usr.bin/nc/netcat.c index e471182b2ad..7b9fe41ba46 100644 --- a/usr.bin/nc/netcat.c +++ b/usr.bin/nc/netcat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: netcat.c,v 1.98 2010/07/03 04:44:51 guenther Exp $ */ +/* $OpenBSD: netcat.c,v 1.99 2011/01/08 00:44:19 jeremy Exp $ */ /* * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> * @@ -62,6 +62,7 @@ #define PORT_MAX 65535 #define PORT_MAX_LEN 6 +#define UNIX_DG_TMP_SOCKET_SIZE 19 /* Command Line Options */ int dflag; /* detached, no stdin */ @@ -89,6 +90,7 @@ u_int rtableid; int timeout = -1; int family = AF_UNSPEC; char *portlist[PORT_MAX+1]; +char *unix_dg_tmp_socket; void atelnet(int, unsigned char *, unsigned int); void build_ports(char *); @@ -99,6 +101,7 @@ int remote_connect(const char *, const char *, struct addrinfo); int socks_connect(const char *, const char *, struct addrinfo, const char *, const char *, struct addrinfo, int, const char *); int udptest(int); +int unix_bind(char *); int unix_connect(char *); int unix_listen(char *); void set_common_sockopts(int); @@ -117,6 +120,7 @@ main(int argc, char *argv[]) char *proxy; const char *errstr, *proxyhost = "", *proxyport = NULL; struct addrinfo proxyhints; + char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE]; ret = 1; s = 0; @@ -241,8 +245,6 @@ main(int argc, char *argv[]) /* Cruft to make sure options are clean, and used properly. */ if (argv[0] && !argv[1] && family == AF_UNIX) { - if (uflag) - errx(1, "cannot use -u and -U"); host = argv[0]; uport = NULL; } else if (argv[0] && !argv[1]) { @@ -265,6 +267,19 @@ main(int argc, char *argv[]) if (!lflag && kflag) errx(1, "must use -l with -k"); + /* Get name of temporary socket for unix datagram client */ + if ((family == AF_UNIX) && uflag && !lflag) { + if (sflag) { + unix_dg_tmp_socket = sflag; + } else { + strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX", + UNIX_DG_TMP_SOCKET_SIZE); + if (mktemp(unix_dg_tmp_socket_buf) == NULL) + err(1, "mktemp"); + unix_dg_tmp_socket = unix_dg_tmp_socket_buf; + } + } + /* Initialize addrinfo structure. */ if (family != AF_UNIX) { memset(&hints, 0, sizeof(struct addrinfo)); @@ -307,8 +322,12 @@ main(int argc, char *argv[]) int connfd; ret = 0; - if (family == AF_UNIX) - s = unix_listen(host); + if (family == AF_UNIX) { + if (uflag) + s = unix_bind(host); + else + s = unix_listen(host); + } /* Allow only one connection at a time, but stay alive. */ for (;;) { @@ -337,17 +356,21 @@ main(int argc, char *argv[]) if (rv < 0) err(1, "connect"); - connfd = s; + readwrite(s); } else { len = sizeof(cliaddr); connfd = accept(s, (struct sockaddr *)&cliaddr, &len); + readwrite(connfd); + close(connfd); } - readwrite(connfd); - close(connfd); if (family != AF_UNIX) close(s); + else if (uflag) { + if (connect(s, NULL, 0) < 0) + err(1, "connect"); + } if (!kflag) break; @@ -361,6 +384,8 @@ main(int argc, char *argv[]) } else ret = 1; + if (uflag) + unlink(unix_dg_tmp_socket); exit(ret); } else { @@ -421,18 +446,19 @@ main(int argc, char *argv[]) } /* - * unix_connect() - * Returns a socket connected to a local unix socket. Returns -1 on failure. + * unix_bind() + * Returns a unix socket bound to the given path */ int -unix_connect(char *path) +unix_bind(char *path) { struct sockaddr_un sun; int s; - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + /* Create unix domain socket. */ + if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM, + 0)) < 0) return (-1); - (void)fcntl(s, F_SETFD, 1); memset(&sun, 0, sizeof(struct sockaddr_un)); sun.sun_family = AF_UNIX; @@ -443,27 +469,32 @@ unix_connect(char *path) errno = ENAMETOOLONG; return (-1); } - if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { + + if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { close(s); return (-1); } return (s); - } /* - * unix_listen() - * Create a unix domain socket, and listen on it. + * unix_connect() + * Returns a socket connected to a local unix socket. Returns -1 on failure. */ int -unix_listen(char *path) +unix_connect(char *path) { struct sockaddr_un sun; int s; - /* Create unix domain socket. */ - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - return (-1); + if (uflag) { + if ((s = unix_bind(unix_dg_tmp_socket)) < 0) + return (-1); + } else { + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + return (-1); + } + (void)fcntl(s, F_SETFD, 1); memset(&sun, 0, sizeof(struct sockaddr_un)); sun.sun_family = AF_UNIX; @@ -474,11 +505,24 @@ unix_listen(char *path) errno = ENAMETOOLONG; return (-1); } - - if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { + if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { close(s); return (-1); } + return (s); + +} + +/* + * unix_listen() + * Create a unix domain socket, and listen on it. + */ +int +unix_listen(char *path) +{ + int s; + if ((s = unix_bind(path)) < 0) + return (-1); if (listen(s, 5) < 0) { close(s); |