summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjeremy <>2011-01-08 00:44:19 +0000
committerjeremy <>2011-01-08 00:44:19 +0000
commitdc99e0127d6fec60b05811ba3a2d2b087cd26184 (patch)
treec2e75d64486999445f14ca603bd38be678f9ff8d
parentab9ee91a071dfdb923a078342458cf270af8b71b (diff)
downloadopenbsd-dc99e0127d6fec60b05811ba3a2d2b087cd26184.tar.gz
openbsd-dc99e0127d6fec60b05811ba3a2d2b087cd26184.tar.bz2
openbsd-dc99e0127d6fec60b05811ba3a2d2b087cd26184.zip
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@
-rw-r--r--src/usr.bin/nc/nc.118
-rw-r--r--src/usr.bin/nc/netcat.c90
2 files changed, 83 insertions, 25 deletions
diff --git a/src/usr.bin/nc/nc.1 b/src/usr.bin/nc/nc.1
index c2599ce3f1..8745528040 100644
--- a/src/usr.bin/nc/nc.1
+++ b/src/usr.bin/nc/nc.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: nc.1,v 1.55 2010/07/25 07:51:39 guenther Exp $ 1.\" $OpenBSD: nc.1,v 1.56 2011/01/08 00:44:19 jeremy Exp $
2.\" 2.\"
3.\" Copyright (c) 1996 David Sacerdote 3.\" Copyright (c) 1996 David Sacerdote
4.\" All rights reserved. 4.\" All rights reserved.
@@ -25,7 +25,7 @@
25.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27.\" 27.\"
28.Dd $Mdocdate: July 25 2010 $ 28.Dd $Mdocdate: January 8 2011 $
29.Dt NC 1 29.Dt NC 1
30.Os 30.Os
31.Sh NAME 31.Sh NAME
@@ -155,6 +155,10 @@ assigns them.
155Enables the RFC 2385 TCP MD5 signature option. 155Enables the RFC 2385 TCP MD5 signature option.
156.It Fl s Ar source_ip_address 156.It Fl s Ar source_ip_address
157Specifies the IP of the interface which is used to send the packets. 157Specifies the IP of the interface which is used to send the packets.
158For
159.Ux Ns -domain
160datagram sockets, specifies the local temporary socket file
161to create and use so that datagrams can be received.
158It is an error to use this option in conjunction with the 162It is an error to use this option in conjunction with the
159.Fl l 163.Fl l
160option. 164option.
@@ -179,6 +183,16 @@ Specifies to use
179sockets. 183sockets.
180.It Fl u 184.It Fl u
181Use UDP instead of the default option of TCP. 185Use UDP instead of the default option of TCP.
186For
187.Ux Ns -domain
188sockets, use a datagram socket instead of a stream socket.
189If a
190.Ux Ns -domain
191socket is used, a temporary receiving socket is created in
192.Pa /tmp
193unless the
194.Fl s
195flag is given.
182.It Fl V Ar rtable 196.It Fl V Ar rtable
183Set the routing table to be used. 197Set the routing table to be used.
184The default is 0. 198The default is 0.
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
index e471182b2a..7b9fe41ba4 100644
--- a/src/usr.bin/nc/netcat.c
+++ b/src/usr.bin/nc/netcat.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: netcat.c,v 1.98 2010/07/03 04:44:51 guenther Exp $ */ 1/* $OpenBSD: netcat.c,v 1.99 2011/01/08 00:44:19 jeremy Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> 3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 * 4 *
@@ -62,6 +62,7 @@
62 62
63#define PORT_MAX 65535 63#define PORT_MAX 65535
64#define PORT_MAX_LEN 6 64#define PORT_MAX_LEN 6
65#define UNIX_DG_TMP_SOCKET_SIZE 19
65 66
66/* Command Line Options */ 67/* Command Line Options */
67int dflag; /* detached, no stdin */ 68int dflag; /* detached, no stdin */
@@ -89,6 +90,7 @@ u_int rtableid;
89int timeout = -1; 90int timeout = -1;
90int family = AF_UNSPEC; 91int family = AF_UNSPEC;
91char *portlist[PORT_MAX+1]; 92char *portlist[PORT_MAX+1];
93char *unix_dg_tmp_socket;
92 94
93void atelnet(int, unsigned char *, unsigned int); 95void atelnet(int, unsigned char *, unsigned int);
94void build_ports(char *); 96void build_ports(char *);
@@ -99,6 +101,7 @@ int remote_connect(const char *, const char *, struct addrinfo);
99int socks_connect(const char *, const char *, struct addrinfo, 101int socks_connect(const char *, const char *, struct addrinfo,
100 const char *, const char *, struct addrinfo, int, const char *); 102 const char *, const char *, struct addrinfo, int, const char *);
101int udptest(int); 103int udptest(int);
104int unix_bind(char *);
102int unix_connect(char *); 105int unix_connect(char *);
103int unix_listen(char *); 106int unix_listen(char *);
104void set_common_sockopts(int); 107void set_common_sockopts(int);
@@ -117,6 +120,7 @@ main(int argc, char *argv[])
117 char *proxy; 120 char *proxy;
118 const char *errstr, *proxyhost = "", *proxyport = NULL; 121 const char *errstr, *proxyhost = "", *proxyport = NULL;
119 struct addrinfo proxyhints; 122 struct addrinfo proxyhints;
123 char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
120 124
121 ret = 1; 125 ret = 1;
122 s = 0; 126 s = 0;
@@ -241,8 +245,6 @@ main(int argc, char *argv[])
241 245
242 /* Cruft to make sure options are clean, and used properly. */ 246 /* Cruft to make sure options are clean, and used properly. */
243 if (argv[0] && !argv[1] && family == AF_UNIX) { 247 if (argv[0] && !argv[1] && family == AF_UNIX) {
244 if (uflag)
245 errx(1, "cannot use -u and -U");
246 host = argv[0]; 248 host = argv[0];
247 uport = NULL; 249 uport = NULL;
248 } else if (argv[0] && !argv[1]) { 250 } else if (argv[0] && !argv[1]) {
@@ -265,6 +267,19 @@ main(int argc, char *argv[])
265 if (!lflag && kflag) 267 if (!lflag && kflag)
266 errx(1, "must use -l with -k"); 268 errx(1, "must use -l with -k");
267 269
270 /* Get name of temporary socket for unix datagram client */
271 if ((family == AF_UNIX) && uflag && !lflag) {
272 if (sflag) {
273 unix_dg_tmp_socket = sflag;
274 } else {
275 strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
276 UNIX_DG_TMP_SOCKET_SIZE);
277 if (mktemp(unix_dg_tmp_socket_buf) == NULL)
278 err(1, "mktemp");
279 unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
280 }
281 }
282
268 /* Initialize addrinfo structure. */ 283 /* Initialize addrinfo structure. */
269 if (family != AF_UNIX) { 284 if (family != AF_UNIX) {
270 memset(&hints, 0, sizeof(struct addrinfo)); 285 memset(&hints, 0, sizeof(struct addrinfo));
@@ -307,8 +322,12 @@ main(int argc, char *argv[])
307 int connfd; 322 int connfd;
308 ret = 0; 323 ret = 0;
309 324
310 if (family == AF_UNIX) 325 if (family == AF_UNIX) {
311 s = unix_listen(host); 326 if (uflag)
327 s = unix_bind(host);
328 else
329 s = unix_listen(host);
330 }
312 331
313 /* Allow only one connection at a time, but stay alive. */ 332 /* Allow only one connection at a time, but stay alive. */
314 for (;;) { 333 for (;;) {
@@ -337,17 +356,21 @@ main(int argc, char *argv[])
337 if (rv < 0) 356 if (rv < 0)
338 err(1, "connect"); 357 err(1, "connect");
339 358
340 connfd = s; 359 readwrite(s);
341 } else { 360 } else {
342 len = sizeof(cliaddr); 361 len = sizeof(cliaddr);
343 connfd = accept(s, (struct sockaddr *)&cliaddr, 362 connfd = accept(s, (struct sockaddr *)&cliaddr,
344 &len); 363 &len);
364 readwrite(connfd);
365 close(connfd);
345 } 366 }
346 367
347 readwrite(connfd);
348 close(connfd);
349 if (family != AF_UNIX) 368 if (family != AF_UNIX)
350 close(s); 369 close(s);
370 else if (uflag) {
371 if (connect(s, NULL, 0) < 0)
372 err(1, "connect");
373 }
351 374
352 if (!kflag) 375 if (!kflag)
353 break; 376 break;
@@ -361,6 +384,8 @@ main(int argc, char *argv[])
361 } else 384 } else
362 ret = 1; 385 ret = 1;
363 386
387 if (uflag)
388 unlink(unix_dg_tmp_socket);
364 exit(ret); 389 exit(ret);
365 390
366 } else { 391 } else {
@@ -421,18 +446,19 @@ main(int argc, char *argv[])
421} 446}
422 447
423/* 448/*
424 * unix_connect() 449 * unix_bind()
425 * Returns a socket connected to a local unix socket. Returns -1 on failure. 450 * Returns a unix socket bound to the given path
426 */ 451 */
427int 452int
428unix_connect(char *path) 453unix_bind(char *path)
429{ 454{
430 struct sockaddr_un sun; 455 struct sockaddr_un sun;
431 int s; 456 int s;
432 457
433 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 458 /* Create unix domain socket. */
459 if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM,
460 0)) < 0)
434 return (-1); 461 return (-1);
435 (void)fcntl(s, F_SETFD, 1);
436 462
437 memset(&sun, 0, sizeof(struct sockaddr_un)); 463 memset(&sun, 0, sizeof(struct sockaddr_un));
438 sun.sun_family = AF_UNIX; 464 sun.sun_family = AF_UNIX;
@@ -443,27 +469,32 @@ unix_connect(char *path)
443 errno = ENAMETOOLONG; 469 errno = ENAMETOOLONG;
444 return (-1); 470 return (-1);
445 } 471 }
446 if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { 472
473 if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
447 close(s); 474 close(s);
448 return (-1); 475 return (-1);
449 } 476 }
450 return (s); 477 return (s);
451
452} 478}
453 479
454/* 480/*
455 * unix_listen() 481 * unix_connect()
456 * Create a unix domain socket, and listen on it. 482 * Returns a socket connected to a local unix socket. Returns -1 on failure.
457 */ 483 */
458int 484int
459unix_listen(char *path) 485unix_connect(char *path)
460{ 486{
461 struct sockaddr_un sun; 487 struct sockaddr_un sun;
462 int s; 488 int s;
463 489
464 /* Create unix domain socket. */ 490 if (uflag) {
465 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 491 if ((s = unix_bind(unix_dg_tmp_socket)) < 0)
466 return (-1); 492 return (-1);
493 } else {
494 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
495 return (-1);
496 }
497 (void)fcntl(s, F_SETFD, 1);
467 498
468 memset(&sun, 0, sizeof(struct sockaddr_un)); 499 memset(&sun, 0, sizeof(struct sockaddr_un));
469 sun.sun_family = AF_UNIX; 500 sun.sun_family = AF_UNIX;
@@ -474,11 +505,24 @@ unix_listen(char *path)
474 errno = ENAMETOOLONG; 505 errno = ENAMETOOLONG;
475 return (-1); 506 return (-1);
476 } 507 }
477 508 if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
478 if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
479 close(s); 509 close(s);
480 return (-1); 510 return (-1);
481 } 511 }
512 return (s);
513
514}
515
516/*
517 * unix_listen()
518 * Create a unix domain socket, and listen on it.
519 */
520int
521unix_listen(char *path)
522{
523 int s;
524 if ((s = unix_bind(path)) < 0)
525 return (-1);
482 526
483 if (listen(s, 5) < 0) { 527 if (listen(s, 5) < 0) {
484 close(s); 528 close(s);