diff options
author | delphij <delphij@FreeBSD.org> | 2011-05-11 21:52:26 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2011-05-11 21:52:26 +0000 |
commit | 8387350bb5178014090e94d6042a08dcb81c168f (patch) | |
tree | 2ada676374f8a269621594f3e6db578572546407 /contrib/netcat/netcat.c | |
parent | 34effb6be75df2ae78f96037e59acf89881522df (diff) | |
download | FreeBSD-src-8387350bb5178014090e94d6042a08dcb81c168f.zip FreeBSD-src-8387350bb5178014090e94d6042a08dcb81c168f.tar.gz |
MFV: nc(1) from OpenBSD 4.9.
MFC after: 1 month
Obtained from: OpenBSD
Diffstat (limited to 'contrib/netcat/netcat.c')
-rw-r--r-- | contrib/netcat/netcat.c | 94 |
1 files changed, 69 insertions, 25 deletions
diff --git a/contrib/netcat/netcat.c b/contrib/netcat/netcat.c index fe87e96..a874adb 100644 --- a/contrib/netcat/netcat.c +++ b/contrib/netcat/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.100 2011/01/09 22:16:46 jeremy Exp $ */ /* * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> * @@ -70,6 +70,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 */ @@ -98,6 +99,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 *); @@ -108,6 +110,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); @@ -134,6 +137,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]; struct option longopts[] = { { "no-tcpopt", no_argument, &FreeBSD_Oflag, 1 }, { NULL, 0, NULL, 0 } @@ -288,8 +292,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]) { @@ -312,6 +314,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)); @@ -354,8 +369,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 (;;) { @@ -384,17 +403,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; @@ -408,6 +431,8 @@ main(int argc, char *argv[]) } else ret = 1; + if (uflag) + unlink(unix_dg_tmp_socket); exit(ret); } else { @@ -468,18 +493,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; @@ -490,27 +516,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; @@ -521,11 +552,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); @@ -989,9 +1033,9 @@ usage(int ret) #else "usage: nc [-46DdhklnrStUuvz] [-I length] [-i interval] [-O length]\n" #endif - "\t [-P proxy_username] [-p source_port] [-s source_ip_address] [-T ToS]\n" + "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n" "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n" - "\t [-x proxy_address[:port]] [hostname] [port]\n"); + "\t [-x proxy_address[:port]] [destination] [port]\n"); if (ret) exit(1); } |