diff options
author | jeremy <> | 2011-01-08 00:44:19 +0000 |
---|---|---|
committer | jeremy <> | 2011-01-08 00:44:19 +0000 |
commit | dc99e0127d6fec60b05811ba3a2d2b087cd26184 (patch) | |
tree | c2e75d64486999445f14ca603bd38be678f9ff8d | |
parent | ab9ee91a071dfdb923a078342458cf270af8b71b (diff) | |
download | openbsd-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.1 | 18 | ||||
-rw-r--r-- | src/usr.bin/nc/netcat.c | 90 |
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. | |||
155 | Enables the RFC 2385 TCP MD5 signature option. | 155 | Enables the RFC 2385 TCP MD5 signature option. |
156 | .It Fl s Ar source_ip_address | 156 | .It Fl s Ar source_ip_address |
157 | Specifies the IP of the interface which is used to send the packets. | 157 | Specifies the IP of the interface which is used to send the packets. |
158 | For | ||
159 | .Ux Ns -domain | ||
160 | datagram sockets, specifies the local temporary socket file | ||
161 | to create and use so that datagrams can be received. | ||
158 | It is an error to use this option in conjunction with the | 162 | It is an error to use this option in conjunction with the |
159 | .Fl l | 163 | .Fl l |
160 | option. | 164 | option. |
@@ -179,6 +183,16 @@ Specifies to use | |||
179 | sockets. | 183 | sockets. |
180 | .It Fl u | 184 | .It Fl u |
181 | Use UDP instead of the default option of TCP. | 185 | Use UDP instead of the default option of TCP. |
186 | For | ||
187 | .Ux Ns -domain | ||
188 | sockets, use a datagram socket instead of a stream socket. | ||
189 | If a | ||
190 | .Ux Ns -domain | ||
191 | socket is used, a temporary receiving socket is created in | ||
192 | .Pa /tmp | ||
193 | unless the | ||
194 | .Fl s | ||
195 | flag is given. | ||
182 | .It Fl V Ar rtable | 196 | .It Fl V Ar rtable |
183 | Set the routing table to be used. | 197 | Set the routing table to be used. |
184 | The default is 0. | 198 | The 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 */ |
67 | int dflag; /* detached, no stdin */ | 68 | int dflag; /* detached, no stdin */ |
@@ -89,6 +90,7 @@ u_int rtableid; | |||
89 | int timeout = -1; | 90 | int timeout = -1; |
90 | int family = AF_UNSPEC; | 91 | int family = AF_UNSPEC; |
91 | char *portlist[PORT_MAX+1]; | 92 | char *portlist[PORT_MAX+1]; |
93 | char *unix_dg_tmp_socket; | ||
92 | 94 | ||
93 | void atelnet(int, unsigned char *, unsigned int); | 95 | void atelnet(int, unsigned char *, unsigned int); |
94 | void build_ports(char *); | 96 | void build_ports(char *); |
@@ -99,6 +101,7 @@ int remote_connect(const char *, const char *, struct addrinfo); | |||
99 | int socks_connect(const char *, const char *, struct addrinfo, | 101 | int 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 *); |
101 | int udptest(int); | 103 | int udptest(int); |
104 | int unix_bind(char *); | ||
102 | int unix_connect(char *); | 105 | int unix_connect(char *); |
103 | int unix_listen(char *); | 106 | int unix_listen(char *); |
104 | void set_common_sockopts(int); | 107 | void 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 | */ |
427 | int | 452 | int |
428 | unix_connect(char *path) | 453 | unix_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 | */ |
458 | int | 484 | int |
459 | unix_listen(char *path) | 485 | unix_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 | */ | ||
520 | int | ||
521 | unix_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); |