[Midnightbsd-cvs] src: contrib/netcat: Sync netcat with OpenBSD 4.1 RELEASE.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Tue Oct 23 13:52:50 EDT 2007


Log Message:
-----------
Sync netcat with OpenBSD 4.1 RELEASE.

Modified Files:
--------------
    src/contrib/netcat:
        atomicio.c (r1.1.1.1 -> r1.2)
        nc.1 (r1.2 -> r1.3)
        netcat.c (r1.1.1.1 -> r1.2)
        socks.c (r1.1.1.1 -> r1.2)

Added Files:
-----------
    src/contrib/netcat:
        MIDNIGHTBSD-Xlist (r1.1)
        MIDNIGHTBSD-upgrade (r1.1)
        atomicio.h (r1.1)

Removed Files:
-------------
    src/contrib/netcat:
        FREEBSD-Xlist
        FREEBSD-upgrade

-------------- next part --------------
--- contrib/netcat/FREEBSD-upgrade
+++ /dev/null
@@ -1,17 +0,0 @@
-$FreeBSD: src/contrib/netcat/FREEBSD-upgrade,v 1.1 2005/02/06 15:26:44 delphij Exp $
-
-1. Export from OpenBSD's nc(1) into an empty directory (say "v-nc").
-2. while read pattern; do rm ${pattern} ; done < FREEBSD-Xlist
-3. Checkout our contrib/netcat to another directory (say "f-nc"),
-   with -rOPENBSD, and usr.bin/nc to its ../../
-4. copy the files from v-nc to f-nc
-5. do cvs up -A in f-nc
-6. If there is conflicits, try to resolve them.
-7. do build in f-nc/../../usr.bin/nc
-8. If everything seems ok, do the actual import in v-nc:
-	cvs -n import src/contrib/netcat OPENBSD OPENBSD_<date>
-   Everything appears be Ok? Do:
-	cvs import src/contrib/netcat OPENBSD OPENBSD_<date>
-9. Resolve the conflicits with the patchset obtained in step 6.
-
-delphij at FreeBSD.org - 06 Feb 2005
--- contrib/netcat/FREEBSD-Xlist
+++ /dev/null
@@ -1,3 +0,0 @@
-$FreeBSD: src/contrib/netcat/FREEBSD-Xlist,v 1.1 2005/02/06 15:26:44 delphij Exp $
-
-Makefile
Index: nc.1
===================================================================
RCS file: /home/cvs/src/contrib/netcat/nc.1,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lcontrib/netcat/nc.1 -Lcontrib/netcat/nc.1 -u -r1.2 -r1.3
--- contrib/netcat/nc.1
+++ contrib/netcat/nc.1
@@ -1,4 +1,4 @@
-.\"     $OpenBSD: nc.1,v 1.36 2005/01/07 10:11:31 jmc Exp $
+.\"     $OpenBSD: nc.1,v 1.44 2006/12/02 01:08:30 jmc Exp $
 .\"
 .\" Copyright (c) 1996 David Sacerdote
 .\" All rights reserved.
@@ -25,9 +25,9 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/contrib/netcat/nc.1,v 1.4.2.1 2006/03/23 07:38:26 hrs Exp $
+.\" $MidnightBSD$
 .\"
-.Dd January 30, 2005
+.Dd May 21, 2006
 .Dt NC 1
 .Os
 .Sh NAME
@@ -39,8 +39,10 @@
 .Op Fl 46DEdhklnorStUuvz
 .Op Fl e Ar IPsec_policy
 .Op Fl i Ar interval
+.Op Fl P Ar proxy_username
 .Op Fl p Ar source_port
 .Op Fl s Ar source_ip_address
+.Op Fl T Ar ToS
 .Op Fl w Ar timeout
 .Op Fl X Ar proxy_protocol
 .Oo Xo
@@ -153,6 +155,10 @@
 Specifying
 .Fl o
 will make it terminate on EOF as well.
+.It Fl P Ar proxy_username
+Specifies a username to present to a proxy server that requires authentication.
+If no username is specified then authentication will not be attempted.
+Proxy authentication is only supported for HTTP CONNECT proxies at present.
 .It Fl p Ar source_port
 Specifies the source port
 .Nm
@@ -171,6 +177,14 @@
 It is an error to use this option in conjunction with the
 .Fl l
 option.
+.It Fl T Ar ToS
+Specifies IP Type of Service (ToS) for the connection.
+Valid values are the tokens
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or an 8-bit hexadecimal value preceded by
+.Dq 0x .
 .It Fl t
 Causes
 .Nm
@@ -200,7 +214,7 @@
 .Fl w
 flag.
 The default is no timeout.
-.It Fl X Ar proxy_version
+.It Fl X Ar proxy_protocol
 Requests that
 .Nm
 should use the specified protocol when talking to the proxy server.
@@ -316,8 +330,9 @@
 when it might be necessary to verify what data a server is sending
 in response to commands issued by the client.
 For example, to retrieve the home page of a web site:
-.Pp
-.Dl $ echo \&"GET\&" | nc host.example.com 80
+.Bd -literal -offset indent
+$ echo -n "GET / HTTP/1.0\er\en\er\en" | nc host.example.com 80
+.Ed
 .Pp
 Note that this also displays the headers sent by the web server.
 They can be filtered, using a tool such as
@@ -330,8 +345,8 @@
 .Bd -literal -offset indent
 $ nc localhost 25 \*(Lt\*(Lt EOF
 HELO host.example.com
-MAIL FROM: \*(Ltuser at host.example.com\*(Gt
-RCPT TO: \*(Ltuser2 at host.example.com\*(Gt
+MAIL FROM:\*(Ltuser at host.example.com\*(Gt
+RCPT TO:\*(Ltuser2 at host.example.com\*(Gt
 DATA
 Body of email.
 \&.
@@ -345,15 +360,11 @@
 .Fl z
 flag can be used to tell
 .Nm
-not to initiate a connection,
-together with the
-.Fl v
-.Pq verbose
-flag,
-to report open ports.
+to report open ports,
+rather than initiate a connection.
 For example:
 .Bd -literal -offset indent
-$ nc -vz host.example.com 20-30
+$ nc -z host.example.com 20-30
 Connection to host.example.com 22 port [tcp/ssh] succeeded!
 Connection to host.example.com 25 port [tcp/smtp] succeeded!
 .Ed
@@ -377,47 +388,63 @@
 220 host.example.com IMS SMTP Receiver Version 0.84 Ready
 .Ed
 .Sh EXAMPLES
-Open a TCP connection to port 42 of hostname, using port 31337 as
+Open a TCP connection to port 42 of host.example.com, using port 31337 as
 the source port, with a timeout of 5 seconds:
 .Pp
-.Dl $ nc -p 31337 -w 5 hostname 42
+.Dl $ nc -p 31337 -w 5 host.example.com 42
 .Pp
-Open a UDP connection to port 53 of hostname:
+Open a UDP connection to port 53 of host.example.com:
 .Pp
-.Dl $ nc -u hostname 53
+.Dl $ nc -u host.example.com 53
 .Pp
-Open a TCP connection to port 42 of example.host using 10.1.2.3 as the
+Open a TCP connection to port 42 of host.example.com using 10.1.2.3 as the
 IP for the local end of the connection:
 .Pp
-.Dl $ nc -s 10.1.2.3 example.host 42
+.Dl $ nc -s 10.1.2.3 host.example.com 42
 .Pp
-Open a TCP connection to port 42 of example.host using IPsec ESP for
+Open a TCP connection to port 42 of host.example.com using IPsec ESP for
 incoming and outgoing traffic.
 .Pp
-.Dl $ nc -E example.host 42
+.Dl $ nc -E host.example.com 42
 .Pp
-Open a TCP connection to port 42 of example.host using IPsec ESP for
+Open a TCP connection to port 42 of host.example.com using IPsec ESP for
 outgoing traffic only.
 .Pp
-.Dl $ nc -e 'out ipsec esp/transport//require' example.host 42
-.Pp
-Send UDP packets to ports 20-30 of example.host, and report which ones
-responded with an ICMP packet after three seconds:
-.Pp
-.Dl $ nc -uvz -w 3 hostname 20-30
+.Dl $ nc -e 'out ipsec esp/transport//require' host.example.com 42
 .Pp
 Create and listen on a Unix Domain Socket:
 .Pp
 .Dl $ nc -lU /var/tmp/dsocket
 .Pp
-Connect to port 42 of hostname via an HTTP proxy at 10.2.3.4, port 8080:
+Connect to port 42 of host.example.com via an HTTP proxy at 10.2.3.4,
+port 8080.
+This example could also be used by
+.Xr ssh 1 ;
+see the
+.Cm ProxyCommand
+directive in
+.Xr ssh_config 5
+for more information.
+.Pp
+.Dl $ nc -x10.2.3.4:8080 -Xconnect host.example.com 42
+.Pp
+The same example again, this time enabling proxy authentication with username
+.Dq ruser
+if the proxy requires it:
 .Pp
-.Dl $ nc -x10.2.3.4:8080 -Xconnect hostname 42
+.Dl $ nc -x10.2.3.4:8080 -Xconnect -Pruser host.example.com 42
 .Sh SEE ALSO
-.Xr cat 1
+.Xr cat 1 ,
+.Xr ssh 1
 .Sh AUTHORS
 Original implementation by *Hobbit*
 .Aq hobbit at avian.org .
 .br
 Rewritten with IPv6 support by
 .An Eric Jackson Aq ericj at monkey.org .
+.Sh CAVEATS
+UDP port scans will always succeed
+(i.e. report the port as open),
+rendering the
+.Fl uz
+combination of flags relatively useless.
Index: atomicio.c
===================================================================
RCS file: /home/cvs/src/contrib/netcat/atomicio.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -Lcontrib/netcat/atomicio.c -Lcontrib/netcat/atomicio.c -u -r1.1.1.1 -r1.2
--- contrib/netcat/atomicio.c
+++ contrib/netcat/atomicio.c
@@ -1,4 +1,7 @@
-/*
+/* $OpenBSD: atomicio.c,v 1.8 2006/02/11 19:31:18 otto Exp $ */
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Anil Madhavapeddy.  All rights served.
  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
  * All rights reserved.
  *
@@ -25,20 +28,23 @@
 
 #include <sys/types.h>
 #include <sys/uio.h>
-
 #include <errno.h>
 #include <unistd.h>
-
-ssize_t atomicio(ssize_t (*f)(int, void *, size_t), int fd, void *_s, size_t n);
+#include "atomicio.h"
 
 /*
- * ensure all of data on socket comes through. f==read || f==write
+ * ensure all of data on socket comes through. f==read || f==vwrite
  */
-ssize_t
-atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
+size_t
+atomicio(f, fd, _s, n)
+	ssize_t (*f) (int, void *, size_t);
+	int fd;
+	void *_s;
+	size_t n;
 {
 	char *s = _s;
-	ssize_t res, pos = 0;
+	size_t pos = 0;
+	ssize_t res;
 
 	while (n > pos) {
 		res = (f) (fd, s + pos, n - pos);
@@ -46,11 +52,13 @@
 		case -1:
 			if (errno == EINTR || errno == EAGAIN)
 				continue;
+			return 0;
 		case 0:
-			return (res);
+			errno = EPIPE;
+			return pos;
 		default:
-			pos += res;
+			pos += (size_t)res;
 		}
 	}
-	return (pos);
+	return pos;
 }
--- /dev/null
+++ contrib/netcat/MIDNIGHTBSD-upgrade
@@ -0,0 +1,19 @@
+$MidnightBSD: src/contrib/netcat/MIDNIGHTBSD-upgrade,v 1.1 2007/10/23 17:52:49 laffer1 Exp $
+
+These are the original FreeBSD import instructions.  We currently
+don't have a vendor branch for this.
+
+1. Export from OpenBSD's nc(1) into an empty directory (say "v-nc").
+2. while read pattern; do rm ${pattern} ; done < MIDNIGHTBSD-Xlist
+3. Checkout our contrib/netcat to another directory (say "f-nc"),
+   with -rOPENBSD, and usr.bin/nc to its ../../
+4. copy the files from v-nc to f-nc
+5. do cvs up -A in f-nc
+6. If there is conflicits, try to resolve them.
+7. do build in f-nc/../../usr.bin/nc
+8. If everything seems ok, do the actual import in v-nc:
+	cvs -n import src/contrib/netcat OPENBSD OPENBSD_<date>
+   Everything appears be Ok? Do:
+	cvs import src/contrib/netcat OPENBSD OPENBSD_<date>
+9. Resolve the conflicits with the patchset obtained in step 6.
+
--- /dev/null
+++ contrib/netcat/atomicio.h
@@ -0,0 +1,33 @@
+/*	$OpenBSD: atomicio.h,v 1.1 2005/05/24 20:13:28 avsm Exp $	*/
+/* $MidnightBSD: src/contrib/netcat/atomicio.h,v 1.1 2007/10/23 17:52:49 laffer1 Exp $ */
+/*
+ * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Ensure all of data on socket comes through. f==read || f==vwrite
+ */
+size_t	atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
+
+#define vwrite (ssize_t (*)(int, void *, size_t))write
Index: netcat.c
===================================================================
RCS file: /home/cvs/src/contrib/netcat/netcat.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -Lcontrib/netcat/netcat.c -Lcontrib/netcat/netcat.c -u -r1.1.1.1 -r1.2
--- contrib/netcat/netcat.c
+++ contrib/netcat/netcat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: netcat.c,v 1.76 2004/12/10 16:51:31 hshoexer Exp $ */
+/* $OpenBSD: netcat.c,v 1.89 2007/02/20 14:11:17 jmc Exp $ */
 /*
  * Copyright (c) 2001 Eric Jackson <ericj at monkey.org>
  *
@@ -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.
  *
- * $FreeBSD: src/contrib/netcat/netcat.c,v 1.3 2005/02/07 05:34:35 delphij Exp $
+ * $MidnightBSD$
  */
 
 /*
@@ -40,10 +40,12 @@
 #include <sys/un.h>
 
 #include <netinet/in.h>
+#include <netinet/in_systm.h>
 #ifdef IPSEC
 #include <netinet6/ipsec.h>
 #endif
 #include <netinet/tcp.h>
+#include <netinet/ip.h>
 #include <arpa/telnet.h>
 
 #include <err.h>
@@ -56,6 +58,8 @@
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <limits.h>
+#include "atomicio.h"
 
 #ifndef SUN_LEN
 #define SUN_LEN(su) \
@@ -68,11 +72,13 @@
 /* Command Line Options */
 int	Eflag;					/* Use IPsec ESP */
 int	dflag;					/* detached, no stdin */
-int	iflag;					/* Interval Flag */
+unsigned int iflag;				/* Interval Flag */
+int	jflag;					/* use jumbo frames if we can */
 int	kflag;					/* More than one connect */
 int	lflag;					/* Bind to local port */
 int	nflag;					/* Don't do name look up */
 int	oflag;					/* Once only: stop on EOF */
+char   *Pflag;					/* Proxy username */
 char   *pflag;					/* Localport flag */
 int	rflag;					/* Random ports flag */
 char   *sflag;					/* Source Address */
@@ -83,23 +89,25 @@
 int	zflag;					/* Port Scan Flag */
 int	Dflag;					/* sodebug */
 int	Sflag;					/* TCP MD5 signature option */
+int	Tflag = -1;				/* IP Type of Service */
 
 int timeout = -1;
 int family = AF_UNSPEC;
 char *portlist[PORT_MAX+1];
 
-ssize_t	atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
 void	atelnet(int, unsigned char *, unsigned int);
 void	build_ports(char *);
 void	help(void);
 int	local_listen(char *, char *, struct addrinfo);
 void	readwrite(int);
-int	remote_connect(char *, char *, struct addrinfo);
-int	socks_connect(char *, char *, struct addrinfo, char *, char *,
-	struct addrinfo, int);
+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_connect(char *);
 int	unix_listen(char *);
+void	set_common_sockopts(int);
+int	parse_iptos(char *);
 void	usage(int);
 
 #ifdef IPSEC
@@ -112,13 +120,13 @@
 main(int argc, char *argv[])
 {
 	int ch, s, ret, socksv, ipsec_count;
-	char *host, *uport, *endp;
+	char *host, *uport;
 	struct addrinfo hints;
 	struct servent *sv;
 	socklen_t len;
 	struct sockaddr_storage cliaddr;
 	char *proxy;
-	char *proxyhost = "", *proxyport = NULL;
+	const char *errstr, *proxyhost = "", *proxyport = NULL;
 	struct addrinfo proxyhints;
 
 	ret = 1;
@@ -127,10 +135,10 @@
 	socksv = 5;
 	host = NULL;
 	uport = NULL;
-	endp = NULL;
 	sv = NULL;
 
-	while ((ch = getopt(argc, argv, "46e:DEdhi:klnop:rSs:tUuvw:X:x:z")) != -1) {
+	while ((ch = getopt(argc, argv,
+	    "46e:DEdhi:jklnoP:p:rSs:tT:Uuvw:X:x:z")) != -1) {
 		switch (ch) {
 		case '4':
 			family = AF_INET;
@@ -173,10 +181,15 @@
 			help();
 			break;
 		case 'i':
-			iflag = (int)strtoul(optarg, &endp, 10);
-			if (iflag < 0 || *endp != '\0')
-				errx(1, "interval cannot be negative");
+			iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
+			if (errstr)
+				errx(1, "interval %s: %s", errstr, optarg);
+			break;
+#ifdef SO_JUMBO
+		case 'j':
+			jflag = 1;
 			break;
+#endif
 		case 'k':
 			kflag = 1;
 			break;
@@ -189,6 +202,9 @@
 		case 'o':
 			oflag = 1;
 			break;
+		case 'P':
+			Pflag = optarg;
+			break;
 		case 'p':
 			pflag = optarg;
 			break;
@@ -208,11 +224,9 @@
 			vflag = 1;
 			break;
 		case 'w':
-			timeout = (int)strtoul(optarg, &endp, 10);
-			if (timeout < 0 || *endp != '\0')
-				errx(1, "timeout cannot be negative");
-			if (timeout >= (INT_MAX / 1000))
-				errx(1, "timeout too large");
+			timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
+			if (errstr)
+				errx(1, "timeout %s: %s", errstr, optarg);
 			timeout *= 1000;
 			break;
 		case 'x':
@@ -229,6 +243,9 @@
 		case 'S':
 			Sflag = 1;
 			break;
+		case 'T':
+			Tflag = parse_iptos(optarg);
+			break;
 		default:
 			usage(1);
 		}
@@ -319,12 +336,13 @@
 			 * functions to talk to the caller.
 			 */
 			if (uflag) {
-				int rv;
-				char buf[1024];
+				int rv, plen;
+				char buf[8192];
 				struct sockaddr_storage z;
 
 				len = sizeof(z);
-				rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK,
+				plen = jflag ? 8192 : 1024;
+				rv = recvfrom(s, buf, plen, MSG_PEEK,
 				    (struct sockaddr *)&z, &len);
 				if (rv < 0)
 					err(1, "recvfrom");
@@ -335,6 +353,7 @@
 
 				connfd = s;
 			} else {
+				len = sizeof(cliaddr);
 				connfd = accept(s, (struct sockaddr *)&cliaddr,
 				    &len);
 			}
@@ -371,7 +390,8 @@
 
 			if (xflag)
 				s = socks_connect(host, portlist[i], hints,
-				    proxyhost, proxyport, proxyhints, socksv);
+				    proxyhost, proxyport, proxyhints, socksv,
+				    Pflag);
 			else
 				s = remote_connect(host, portlist[i], hints);
 
@@ -485,10 +505,10 @@
  * port or source address if needed. Returns -1 on failure.
  */
 int
-remote_connect(char *host, char *port, struct addrinfo hints)
+remote_connect(const char *host, const char *port, struct addrinfo hints)
 {
 	struct addrinfo *res, *res0;
-	int s, error, x = 1;
+	int s, error;
 
 	if ((error = getaddrinfo(host, port, &hints, &res)))
 		errx(1, "getaddrinfo: %s", gai_strerror(error));
@@ -509,13 +529,6 @@
 		if (sflag || pflag) {
 			struct addrinfo ahints, *ares;
 
-			if (!(sflag && pflag)) {
-				if (!sflag)
-					sflag = NULL;
-				else
-					pflag = NULL;
-			}
-
 			memset(&ahints, 0, sizeof(struct addrinfo));
 			ahints.ai_family = res0->ai_family;
 			ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
@@ -529,16 +542,8 @@
 				errx(1, "bind failed: %s", strerror(errno));
 			freeaddrinfo(ares);
 		}
-		if (Sflag) {
-			if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
-			    &x, sizeof(x)) == -1)
-				err(1, NULL);
-		}
-		if (Dflag) {
-			if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
-			    &x, sizeof(x)) == -1)
-				err(1, NULL);
-		}
+
+		set_common_sockopts(s);
 
 		if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
 			break;
@@ -583,7 +588,7 @@
 	res0 = res;
 	do {
 		if ((s = socket(res0->ai_family, res0->ai_socktype,
-		    res0->ai_protocol)) == 0)
+		    res0->ai_protocol)) < 0)
 			continue;
 
 		ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
@@ -595,17 +600,6 @@
 		if (ipsec_policy[1] != NULL)
 			add_ipsec_policy(s, ipsec_policy[1]);
 #endif
-		if (Sflag) {
-			ret = setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
-			    &x, sizeof(x));
-			if (ret == -1)
-				err(1, NULL);
-		}
-		if (Dflag) {
-			if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
-			    &x, sizeof(x)) == -1)
-				err(1, NULL);
-		}
 
 		if (bind(s, (struct sockaddr *)res0->ai_addr,
 		    res0->ai_addrlen) == 0)
@@ -633,9 +627,12 @@
 readwrite(int nfd)
 {
 	struct pollfd pfd[2];
-	unsigned char buf[BUFSIZ];
-	int wfd = fileno(stdin), n;
+	unsigned char buf[8192];
+	int n, wfd = fileno(stdin);
 	int lfd = fileno(stdout);
+	int plen;
+
+	plen = jflag ? 8192 : 1024;
 
 	/* Setup Network FD */
 	pfd[0].fd = nfd;
@@ -658,7 +655,7 @@
 			return;
 
 		if (pfd[0].revents & POLLIN) {
-			if ((n = read(nfd, buf, sizeof(buf))) < 0)
+			if ((n = read(nfd, buf, plen)) < 0)
 				return;
 			else if (n == 0) {
 				shutdown(nfd, SHUT_RD);
@@ -667,14 +664,13 @@
 			} else {
 				if (tflag)
 					atelnet(nfd, buf, n);
-				if (atomicio((ssize_t (*)(int, void *, size_t))write,
-				    lfd, buf, n) != n)
+				if (atomicio(vwrite, lfd, buf, n) != n)
 					return;
 			}
 		}
 
 		if (!dflag && pfd[1].revents & POLLIN) {
-			if ((n = read(wfd, buf, sizeof(buf))) < 0 ||
+			if ((n = read(wfd, buf, plen)) < 0 ||
 			    (oflag && n == 0)) {
 				return;
 			} else if (n == 0) {
@@ -682,8 +678,7 @@
 				pfd[1].fd = -1;
 				pfd[1].events = 0;
 			} else {
-				if (atomicio((ssize_t (*)(int, void *, size_t))write,
-				    nfd, buf, n) != n)
+				if (atomicio(vwrite, nfd, buf, n) != n)
 					return;
 			}
 		}
@@ -714,9 +709,8 @@
 			p++;
 			obuf[2] = *p;
 			obuf[3] = '\0';
-			if (atomicio((ssize_t (*)(int, void *, size_t))write,
-			    nfd, obuf, 3) != 3)
-				warnx("Write Error!");
+			if (atomicio(vwrite, nfd, obuf, 3) != 3)
+				warn("Write Error!");
 			obuf[0] = '\0';
 		}
 	}
@@ -730,7 +724,8 @@
 void
 build_ports(char *p)
 {
-	char *n, *endp;
+	const char *errstr;
+	char *n;
 	int hi, lo, cp;
 	int x = 0;
 
@@ -742,12 +737,12 @@
 		n++;
 
 		/* Make sure the ports are in order: lowest->highest. */
-		hi = (int)strtoul(n, &endp, 10);
-		if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
-			errx(1, "port range not valid");
-		lo = (int)strtoul(p, &endp, 10);
-		if (lo <= 0 || lo > PORT_MAX || *endp != '\0')
-			errx(1, "port range not valid");
+		hi = strtonum(n, 1, PORT_MAX, &errstr);
+		if (errstr)
+			errx(1, "port number %s: %s", errstr, n);
+		lo = strtonum(p, 1, PORT_MAX, &errstr);
+		if (errstr)
+			errx(1, "port number %s: %s", errstr, p);
 
 		if (lo > hi) {
 			cp = hi;
@@ -777,9 +772,9 @@
 			}
 		}
 	} else {
-		hi = (int)strtoul(p, &endp, 10);
-		if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
-			errx(1, "port range not valid");
+		hi = strtonum(p, 1, PORT_MAX, &errstr);
+		if (errstr)
+			errx(1, "port number %s: %s", errstr, p);
 		portlist[0] = calloc(1, PORT_MAX_LEN);
 		if (portlist[0] == NULL)
 			err(1, NULL);
@@ -808,6 +803,52 @@
 }
 
 void
+set_common_sockopts(int s)
+{
+	int x = 1;
+
+	if (Sflag) {
+		if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
+			&x, sizeof(x)) == -1)
+			err(1, NULL);
+	}
+	if (Dflag) {
+		if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
+			&x, sizeof(x)) == -1)
+			err(1, NULL);
+	}
+#ifdef SO_JUMBO
+	if (jflag) {
+		if (setsockopt(s, SOL_SOCKET, SO_JUMBO,
+			&x, sizeof(x)) == -1)
+			err(1, NULL);
+	}
+#endif
+	if (Tflag != -1) {
+		if (setsockopt(s, IPPROTO_IP, IP_TOS,
+		    &Tflag, sizeof(Tflag)) == -1)
+			err(1, "set IP ToS");
+	}
+}
+
+int
+parse_iptos(char *s)
+{
+	int tos = -1;
+
+	if (strcmp(s, "lowdelay") == 0)
+		return (IPTOS_LOWDELAY);
+	if (strcmp(s, "throughput") == 0)
+		return (IPTOS_THROUGHPUT);
+	if (strcmp(s, "reliability") == 0)
+		return (IPTOS_RELIABILITY);
+
+	if (sscanf(s, "0x%x", &tos) != 1 || tos < 0 || tos > 0xff)
+		errx(1, "invalid IP Type of Service");
+	return (tos);
+}
+
+void
 help(void)
 {
 	usage(0);
@@ -827,10 +868,12 @@
 	\t-k		Keep inbound sockets open for multiple connects\n\
 	\t-l		Listen mode, for inbound connects\n\
 	\t-n		Suppress name/port resolutions\n\
+	\t-P proxyuser\tUsername for proxy authentication\n\
 	\t-p port\t	Specify local port for remote connects\n\
 	\t-r		Randomize remote ports\n\
 	\t-S		Enable the TCP MD5 signature option\n\
 	\t-s addr\t	Local source address\n\
+	\t-T ToS\t	Set IP Type of Service\n\
 	\t-t		Answer TELNET negotiation\n\
 	\t-U		Use UNIX domain socket\n\
 	\t-u		UDP mode\n\
@@ -871,13 +914,12 @@
 void
 usage(int ret)
 {
-
 #ifdef IPSEC
-	fprintf(stderr, "usage: nc [-46DEdhklnrStUuvz] [-e policy] [-i interval] [-p source_port]\n");
+	fprintf(stderr, "usage: nc [-46DEdhklnrStUuvz] [-e policy] [-i interval] [-P proxy_username] [-p source_port]\n");
 #else
-	fprintf(stderr, "usage: nc [-46DdhklnrStUuvz] [-i interval] [-p source_port]\n");
+	fprintf(stderr, "usage: nc [-46DdhklnrStUuvz] [-i interval] [-P proxy_username] [-p source_port]\n");
 #endif
-	fprintf(stderr, "\t  [-s source_ip_address] [-w timeout] [-X proxy_version]\n");
+	fprintf(stderr, "\t  [-s source_ip_address] [-T ToS] [-w timeout] [-X proxy_protocol]\n");
 	fprintf(stderr, "\t  [-x proxy_address[:port]] [hostname] [port[s]]\n");
 	if (ret)
 		exit(1);
--- /dev/null
+++ contrib/netcat/MIDNIGHTBSD-Xlist
@@ -0,0 +1,3 @@
+$FreeBSD: src/contrib/netcat/FREEBSD-Xlist,v 1.1 2005/02/06 15:26:44 delphij Exp $
+
+Makefile
Index: socks.c
===================================================================
RCS file: /home/cvs/src/contrib/netcat/socks.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -Lcontrib/netcat/socks.c -Lcontrib/netcat/socks.c -u -r1.1.1.1 -r1.2
--- contrib/netcat/socks.c
+++ contrib/netcat/socks.c
@@ -1,7 +1,8 @@
-/*	$OpenBSD: socks.c,v 1.9 2004/10/17 03:13:55 djm Exp $	*/
-
+/*	$OpenBSD: socks.c,v 1.17 2006/09/25 04:51:20 ray Exp $	*/
+/* $MidnightBSD$ */
 /*
  * Copyright (c) 1999 Niklas Hallqvist.  All rights reserved.
+ * Copyright (c) 2004, 2005 Damien Miller.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,6 +37,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <resolv.h>
+#include <readpassphrase.h>
+#include "atomicio.h"
 
 #define SOCKS_PORT	"1080"
 #define HTTP_PROXY_PORT	"3128"
@@ -46,57 +50,53 @@
 #define SOCKS_NOMETHOD	0xff
 #define SOCKS_CONNECT	1
 #define SOCKS_IPV4	1
+#define SOCKS_DOMAIN	3
+#define SOCKS_IPV6	4
 
+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	remote_connect(char *, char *, struct addrinfo);
-int	socks_connect(char *host, char *port, struct addrinfo hints,
-	    char *proxyhost, char *proxyport, struct addrinfo proxyhints,
-	    int socksv);
-
-static in_addr_t
-decode_addr(const char *s)
+static int
+decode_addrport(const char *h, const char *p, struct sockaddr *addr,
+    socklen_t addrlen, int v4only, int numeric)
 {
-	struct hostent *hp = gethostbyname (s);
-	struct in_addr retval;
-
-	if (hp)
-		return *(in_addr_t *)hp->h_addr_list[0];
-	if (inet_aton (s, &retval))
-		return retval.s_addr;
-	errx (1, "cannot decode address \"%s\"", s);
-}
+	int r;
+	struct addrinfo hints, *res;
 
-static in_port_t
-decode_port(const char *s)
-{
-	struct servent *sp;
-	in_port_t port;
-	char *p;
-
-	port = strtol (s, &p, 10);
-	if (s == p) {
-		sp = getservbyname (s, "tcp");
-		if (sp)
-			return sp->s_port;
+	bzero(&hints, sizeof(hints));
+	hints.ai_family = v4only ? PF_INET : PF_UNSPEC;
+	hints.ai_flags = numeric ? AI_NUMERICHOST : 0;
+	hints.ai_socktype = SOCK_STREAM;
+	r = getaddrinfo(h, p, &hints, &res);
+	/* Don't fatal when attempting to convert a numeric address */
+	if (r != 0) {
+		if (!numeric) {
+			errx(1, "getaddrinfo(\"%.64s\", \"%.64s\"): %s", h, p,
+			    gai_strerror(r));
+		}
+		return (-1);
+	}
+	if (addrlen < res->ai_addrlen) {
+		freeaddrinfo(res);
+		errx(1, "internal error: addrlen < res->ai_addrlen");
 	}
-	if (*s != '\0' && *p == '\0')
-		return htons (port);
-	errx (1, "cannot decode port \"%s\"", s);
+	memcpy(addr, res->ai_addr, res->ai_addrlen);
+	freeaddrinfo(res);
+	return (0);
 }
 
 static int
-proxy_read_line(int fd, char *buf, int bufsz)
+proxy_read_line(int fd, char *buf, size_t bufsz)
 {
-	int r, off;
+	size_t off;
 
 	for(off = 0;;) {
 		if (off >= bufsz)
 			errx(1, "proxy read too long");
-		if ((r = read(fd, buf + off, 1)) <= 0) {
-			if (r == -1 && errno == EINTR)
-				continue;
+		if (atomicio(read, fd, buf + off, 1) != 1)
 			err(1, "proxy read");
-		}
 		/* Skip CR */
 		if (buf[off] == '\r')
 			continue;
@@ -109,127 +109,218 @@
 	return (off);
 }
 
+static const char *
+getproxypass(const char *proxyuser, const char *proxyhost)
+{
+	char prompt[512];
+	static char pw[256];
+
+	snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ",
+	   proxyuser, proxyhost);
+	if (readpassphrase(prompt, pw, sizeof(pw), RPP_REQUIRE_TTY) == NULL)
+		errx(1, "Unable to read proxy passphrase");
+	return (pw);
+}
+
 int
-socks_connect(char *host, char *port, struct addrinfo hints,
-    char *proxyhost, char *proxyport, struct addrinfo proxyhints,
-    int socksv)
+socks_connect(const char *host, const char *port,
+    struct addrinfo hints __attribute__ ((__unused__)),
+    const char *proxyhost, const char *proxyport, struct addrinfo proxyhints,
+    int socksv, const char *proxyuser)
 {
-	int proxyfd, r;
+	int proxyfd, r, authretry = 0;
+	size_t hlen, wlen;
 	unsigned char buf[1024];
-	ssize_t cnt;
-	in_addr_t serveraddr;
+	size_t cnt;
+	struct sockaddr_storage addr;
+	struct sockaddr_in *in4 = (struct sockaddr_in *)&addr;
+	struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr;
 	in_port_t serverport;
+	const char *proxypass = NULL;
 
 	if (proxyport == NULL)
 		proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT;
 
+	/* Abuse API to lookup port */
+	if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr,
+	    sizeof(addr), 1, 1) == -1)
+		errx(1, "unknown port \"%.64s\"", port);
+	serverport = in4->sin_port;
+
+ again:
+	if (authretry++ > 3)
+		errx(1, "Too many authentication failures");
+
 	proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
 
 	if (proxyfd < 0)
-		return -1;
-
-	serveraddr = decode_addr (host);
-	serverport = decode_port (port);
+		return (-1);
 
 	if (socksv == 5) {
+		if (decode_addrport(host, port, (struct sockaddr *)&addr,
+		    sizeof(addr), 0, 1) == -1)
+			addr.ss_family = 0; /* used in switch below */
+
 		/* Version 5, one method: no authentication */
 		buf[0] = SOCKS_V5;
 		buf[1] = 1;
 		buf[2] = SOCKS_NOAUTH;
-		cnt = write (proxyfd, buf, 3);
-		if (cnt == -1)
-			err (1, "write failed");
+		cnt = atomicio(vwrite, proxyfd, buf, 3);
 		if (cnt != 3)
-			errx (1, "short write, %d (expected 3)", cnt);
+			err(1, "write failed (%d/3)", cnt);
+
+		cnt = atomicio(read, proxyfd, buf, 2);
+		if (cnt != 2)
+			err(1, "read failed (%d/3)", cnt);
 
-		read (proxyfd, buf, 2);
 		if (buf[1] == SOCKS_NOMETHOD)
-			errx (1, "authentication method negotiation failed");
+			errx(1, "authentication method negotiation failed");
 
-		/* Version 5, connect: IPv4 address */
-		buf[0] = SOCKS_V5;
-		buf[1] = SOCKS_CONNECT;
-		buf[2] = 0;
-		buf[3] = SOCKS_IPV4;
-		memcpy (buf + 4, &serveraddr, sizeof serveraddr);
-		memcpy (buf + 8, &serverport, sizeof serverport);
-
-		/* XXX Handle short writes better */
-		cnt = write (proxyfd, buf, 10);
-		if (cnt == -1)
-			err (1, "write failed");
-		if (cnt != 10)
-			errx (1, "short write, %d (expected 10)", cnt);
+		switch (addr.ss_family) {
+		case 0:
+			/* Version 5, connect: domain name */
+
+			/* Max domain name length is 255 bytes */
+			hlen = strlen(host);
+			if (hlen > 255)
+				errx(1, "host name too long for SOCKS5");
+			buf[0] = SOCKS_V5;
+			buf[1] = SOCKS_CONNECT;
+			buf[2] = 0;
+			buf[3] = SOCKS_DOMAIN;
+			buf[4] = hlen;
+			memcpy(buf + 5, host, hlen);			
+			memcpy(buf + 5 + hlen, &serverport, sizeof serverport);
+			wlen = 7 + hlen;
+			break;
+		case AF_INET:
+			/* Version 5, connect: IPv4 address */
+			buf[0] = SOCKS_V5;
+			buf[1] = SOCKS_CONNECT;
+			buf[2] = 0;
+			buf[3] = SOCKS_IPV4;
+			memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
+			memcpy(buf + 8, &in4->sin_port, sizeof in4->sin_port);
+			wlen = 10;
+			break;
+		case AF_INET6:
+			/* Version 5, connect: IPv6 address */
+			buf[0] = SOCKS_V5;
+			buf[1] = SOCKS_CONNECT;
+			buf[2] = 0;
+			buf[3] = SOCKS_IPV6;
+			memcpy(buf + 4, &in6->sin6_addr, sizeof in6->sin6_addr);
+			memcpy(buf + 20, &in6->sin6_port,
+			    sizeof in6->sin6_port);
+			wlen = 22;
+			break;
+		default:
+			errx(1, "internal error: silly AF");
+		}
 
-		/* XXX Handle short reads better */
-		cnt = read (proxyfd, buf, sizeof buf);
-		if (cnt == -1)
-			err (1, "read failed");
+		cnt = atomicio(vwrite, proxyfd, buf, wlen);
+		if (cnt != wlen)
+			err(1, "write failed (%d/%d)", cnt, wlen);
+
+		cnt = atomicio(read, proxyfd, buf, 10);
 		if (cnt != 10)
-			errx (1, "unexpected reply size %d (expected 10)", cnt);
+			err(1, "read failed (%d/10)", cnt);
 		if (buf[1] != 0)
-			errx (1, "connection failed, SOCKS error %d", buf[1]);
+			errx(1, "connection failed, SOCKS error %d", buf[1]);
 	} else if (socksv == 4) {
+		/* This will exit on lookup failure */
+		decode_addrport(host, port, (struct sockaddr *)&addr,
+		    sizeof(addr), 1, 0);
+
 		/* Version 4 */
 		buf[0] = SOCKS_V4;
 		buf[1] = SOCKS_CONNECT;	/* connect */
-		memcpy (buf + 2, &serverport, sizeof serverport);
-		memcpy (buf + 4, &serveraddr, sizeof serveraddr);
+		memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port);
+		memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
 		buf[8] = 0;	/* empty username */
+		wlen = 9;
 
-		cnt = write (proxyfd, buf, 9);
-		if (cnt == -1)
-			err (1, "write failed");
-		if (cnt != 9)
-			errx (1, "short write, %d (expected 9)", cnt);
-
-		/* XXX Handle short reads better */
-		cnt = read (proxyfd, buf, 8);
-		if (cnt == -1)
-			err (1, "read failed");
+		cnt = atomicio(vwrite, proxyfd, buf, wlen);
+		if (cnt != wlen)
+			err(1, "write failed (%d/%d)", cnt, wlen);
+
+		cnt = atomicio(read, proxyfd, buf, 8);
 		if (cnt != 8)
-			errx (1, "unexpected reply size %d (expected 8)", cnt);
+			err(1, "read failed (%d/8)", cnt);
 		if (buf[1] != 90)
-			errx (1, "connection failed, SOCKS error %d", buf[1]);
+			errx(1, "connection failed, SOCKS error %d", buf[1]);
 	} else if (socksv == -1) {
 		/* HTTP proxy CONNECT */
 
 		/* Disallow bad chars in hostname */
 		if (strcspn(host, "\r\n\t []:") != strlen(host))
-			errx (1, "Invalid hostname");
+			errx(1, "Invalid hostname");
 
 		/* Try to be sane about numeric IPv6 addresses */
 		if (strchr(host, ':') != NULL) {
 			r = snprintf(buf, sizeof(buf),
-			    "CONNECT [%s]:%d HTTP/1.0\r\n\r\n",
+			    "CONNECT [%s]:%d HTTP/1.0\r\n",
 			    host, ntohs(serverport));
 		} else {
 			r = snprintf(buf, sizeof(buf),
-			    "CONNECT %s:%d HTTP/1.0\r\n\r\n",
+			    "CONNECT %s:%d HTTP/1.0\r\n",
 			    host, ntohs(serverport));
 		}
-		if (r == -1 || r >= sizeof(buf))
-			errx (1, "hostname too long");
+		if (r == -1 || (size_t)r >= sizeof(buf))
+			errx(1, "hostname too long");
 		r = strlen(buf);
 
-		/* XXX atomicio */
-		cnt = write (proxyfd, buf, r);
-		if (cnt == -1)
-			err (1, "write failed");
+		cnt = atomicio(vwrite, proxyfd, buf, r);
 		if (cnt != r)
-			errx (1, "short write, %d (expected %d)", cnt, r);
+			err(1, "write failed (%d/%d)", cnt, r);
+
+		if (authretry > 1) {
+			char resp[1024];
+
+			proxypass = getproxypass(proxyuser, proxyhost);
+			r = snprintf(buf, sizeof(buf), "%s:%s",
+			    proxyuser, proxypass);
+			if (r == -1 || (size_t)r >= sizeof(buf) ||
+			    b64_ntop(buf, strlen(buf), resp,
+			    sizeof(resp)) == -1)
+				errx(1, "Proxy username/password too long");
+			r = snprintf(buf, sizeof(buf), "Proxy-Authorization: "
+			    "Basic %s\r\n", resp);
+			if (r == -1 || (size_t)r >= sizeof(buf))
+				errx(1, "Proxy auth response too long");
+			r = strlen(buf);
+			if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != r)
+				err(1, "write failed (%d/%d)", cnt, r);
+		}
+
+		/* Terminate headers */
+		if ((r = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2)
+			err(1, "write failed (2/%d)", r);
+
+		/* Read status reply */
+		proxy_read_line(proxyfd, buf, sizeof(buf));
+		if (proxyuser != NULL &&
+		    strncmp(buf, "HTTP/1.0 407 ", 12) == 0) {
+			if (authretry > 1) {
+				fprintf(stderr, "Proxy authentication "
+				    "failed\n");
+			}
+			close(proxyfd);
+			goto again;
+		} else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0 &&
+		    strncmp(buf, "HTTP/1.1 200 ", 12) != 0)
+			errx(1, "Proxy error: \"%s\"", buf);
 
-		/* Read reply */
+		/* Headers continue until we hit an empty line */
 		for (r = 0; r < HTTP_MAXHDRS; r++) {
 			proxy_read_line(proxyfd, buf, sizeof(buf));
-			if (r == 0 && strncmp(buf, "HTTP/1.0 200 ", 12) != 0)
-				errx (1, "Proxy error: \"%s\"", buf);
-			/* Discard headers until we hit an empty line */
 			if (*buf == '\0')
 				break;
 		}
+		if (*buf != '\0')
+			errx(1, "Too many proxy headers received");
 	} else
-		errx (1, "Unknown proxy protocol %d", socksv);
+		errx(1, "Unknown proxy protocol %d", socksv);
 
-	return proxyfd;
+	return (proxyfd);
 }


More information about the Midnightbsd-cvs mailing list