summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/netcat/atomicio.c56
-rw-r--r--contrib/netcat/nc.1387
-rw-r--r--contrib/netcat/netcat.c802
-rw-r--r--contrib/netcat/socks.c235
4 files changed, 1480 insertions, 0 deletions
diff --git a/contrib/netcat/atomicio.c b/contrib/netcat/atomicio.c
new file mode 100644
index 0000000..9e73290
--- /dev/null
+++ b/contrib/netcat/atomicio.c
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#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);
+
+/*
+ * ensure all of data on socket comes through. f==read || f==write
+ */
+ssize_t
+atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
+{
+ char *s = _s;
+ ssize_t res, pos = 0;
+
+ while (n > pos) {
+ res = (f) (fd, s + pos, n - pos);
+ switch (res) {
+ case -1:
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ case 0:
+ return (res);
+ default:
+ pos += res;
+ }
+ }
+ return (pos);
+}
diff --git a/contrib/netcat/nc.1 b/contrib/netcat/nc.1
new file mode 100644
index 0000000..472fa76
--- /dev/null
+++ b/contrib/netcat/nc.1
@@ -0,0 +1,387 @@
+.\" $OpenBSD: nc.1,v 1.36 2005/01/07 10:11:31 jmc Exp $
+.\"
+.\" Copyright (c) 1996 David Sacerdote
+.\" 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.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission
+.\"
+.\" 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.
+.\"
+.Dd June 25, 2001
+.Dt NC 1
+.Os
+.Sh NAME
+.Nm nc
+.Nd arbitrary TCP and UDP connections and listens
+.Sh SYNOPSIS
+.Nm nc
+.Bk -words
+.Op Fl 46DdhklnrStUuvz
+.Op Fl i Ar interval
+.Op Fl p Ar source_port
+.Op Fl s Ar source_ip_address
+.Op Fl w Ar timeout
+.Op Fl X Ar proxy_protocol
+.Oo Xo
+.Fl x Ar proxy_address Ns Oo : Ns
+.Ar port Oc Oc
+.Xc
+.Op Ar hostname
+.Op Ar port Ns Bq Ar s
+.Ek
+.Sh DESCRIPTION
+The
+.Nm
+(or
+.Nm netcat )
+utility is used for just about anything under the sun involving TCP
+or UDP.
+It can open TCP connections, send UDP packets, listen on arbitrary
+TCP and UDP ports, do port scanning, and deal with both IPv4 and
+IPv6.
+Unlike
+.Xr telnet 1 ,
+.Nm
+scripts nicely, and separates error messages onto standard error instead
+of sending them to standard output, as
+.Xr telnet 1
+does with some.
+.Pp
+Common uses include:
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+simple TCP proxies
+.It
+shell-script based HTTP clients and servers
+.It
+network daemon testing
+.It
+a SOCKS or HTTP ProxyCommand for
+.Xr ssh 1
+.It
+and much, much more
+.El
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl 4
+Forces
+.Nm
+to use IPv4 addresses only.
+.It Fl 6
+Forces
+.Nm
+to use IPv6 addresses only.
+.It Fl D
+Enable debugging on the socket.
+.It Fl d
+Do not attempt to read from stdin.
+.It Fl h
+Prints out
+.Nm
+help.
+.It Fl i Ar interval
+Specifies a delay time interval between lines of text sent and received.
+Also causes a delay time between connections to multiple ports.
+.It Fl k
+Forces
+.Nm
+to stay listening for another connection after its current connection
+is completed.
+It is an error to use this option without the
+.Fl l
+option.
+.It Fl l
+Used to specify that
+.Nm
+should listen for an incoming connection rather than initiate a
+connection to a remote host.
+It is an error to use this option in conjunction with the
+.Fl p ,
+.Fl s ,
+or
+.Fl z
+options.
+Additionally, any timeouts specified with the
+.Fl w
+option are ignored.
+.It Fl n
+Do not do any DNS or service lookups on any specified addresses,
+hostnames or ports.
+.It Fl p Ar source_port
+Specifies the source port
+.Nm
+should use, subject to privilege restrictions and availability.
+It is an error to use this option in conjunction with the
+.Fl l
+option.
+.It Fl r
+Specifies that source and/or destination ports should be chosen randomly
+instead of sequentially within a range or in the order that the system
+assigns them.
+.It Fl S
+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.
+It is an error to use this option in conjunction with the
+.Fl l
+option.
+.It Fl t
+Causes
+.Nm
+to send RFC 854 DON'T and WON'T responses to RFC 854 DO and WILL requests.
+This makes it possible to use
+.Nm
+to script telnet sessions.
+.It Fl U
+Specifies to use Unix Domain Sockets.
+.It Fl u
+Use UDP instead of the default option of TCP.
+.It Fl v
+Have
+.Nm
+give more verbose output.
+.It Fl w Ar timeout
+If a connection and stdin are idle for more than
+.Ar timeout
+seconds, then the connection is silently closed.
+The
+.Fl w
+flag has no effect on the
+.Fl l
+option, i.e.\&
+.Nm
+will listen forever for a connection, with or without the
+.Fl w
+flag.
+The default is no timeout.
+.It Fl X Ar proxy_version
+Requests that
+.Nm
+should use the specified protocol when talking to the proxy server.
+Supported protocols are
+.Dq 4
+(SOCKS v.4),
+.Dq 5
+(SOCKS v.5)
+and
+.Dq connect
+(HTTPS proxy).
+If the protocol is not specified, SOCKS version 5 is used.
+.It Xo
+.Fl x Ar proxy_address Ns Oo : Ns
+.Ar port Oc
+.Xc
+Requests that
+.Nm
+should connect to
+.Ar hostname
+using a proxy at
+.Ar proxy_address
+and
+.Ar port .
+If
+.Ar port
+is not specified, the well-known port for the proxy protocol is used (1080
+for SOCKS, 3128 for HTTPS).
+.It Fl z
+Specifies that
+.Nm
+should just scan for listening daemons, without sending any data to them.
+It is an error to use this option in conjunction with the
+.Fl l
+option.
+.El
+.Pp
+.Ar hostname
+can be a numerical IP address or a symbolic hostname
+(unless the
+.Fl n
+option is given).
+In general, a hostname must be specified,
+unless the
+.Fl l
+option is given
+(in which case the local host is used).
+.Pp
+.Ar port Ns Op Ar s
+can be single integers or ranges.
+Ranges are in the form nn-mm.
+In general,
+a destination port must be specified,
+unless the
+.Fl U
+option is given
+(in which case a socket must be specified).
+.Sh CLIENT/SERVER MODEL
+It is quite simple to build a very basic client/server model using
+.Nm .
+On one console, start
+.Nm
+listening on a specific port for a connection.
+For example:
+.Pp
+.Dl $ nc -l 1234
+.Pp
+.Nm
+is now listening on port 1234 for a connection.
+On a second console
+.Pq or a second machine ,
+connect to the machine and port being listened on:
+.Pp
+.Dl $ nc 127.0.0.1 1234
+.Pp
+There should now be a connection between the ports.
+Anything typed at the second console will be concatenated to the first,
+and vice-versa.
+After the connection has been set up,
+.Nm
+does not really care which side is being used as a
+.Sq server
+and which side is being used as a
+.Sq client .
+The connection may be terminated using an
+.Dv EOF
+.Pq Sq ^D .
+.Sh DATA TRANSFER
+The example in the previous section can be expanded to build a
+basic data transfer model.
+Any information input into one end of the connection will be output
+to the other end, and input and output can be easily captured in order to
+emulate file transfer.
+.Pp
+Start by using
+.Nm
+to listen on a specific port, with output captured into a file:
+.Pp
+.Dl $ nc -l 1234 \*(Gt filename.out
+.Pp
+Using a second machine, connect to the listening
+.Nm
+process, feeding it the file which is to be transferred:
+.Pp
+.Dl $ nc host.example.com 1234 \*(Lt filename.in
+.Pp
+After the file has been transferred, the connection will close automatically.
+.Sh TALKING TO SERVERS
+It is sometimes useful to talk to servers
+.Dq by hand
+rather than through a user interface.
+It can aid in troubleshooting,
+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
+.Pp
+Note that this also displays the headers sent by the web server.
+They can be filtered, using a tool such as
+.Xr sed 1 ,
+if necessary.
+.Pp
+More complicated examples can be built up when the user knows the format
+of requests required by the server.
+As another example, an email may be submitted to an SMTP server using:
+.Bd -literal -offset indent
+$ nc localhost 25 \*(Lt\*(Lt EOF
+HELO host.example.com
+MAIL FROM: \*(Ltuser@host.example.com\*(Gt
+RCPT TO: \*(Ltuser2@host.example.com\*(Gt
+DATA
+Body of email.
+\&.
+QUIT
+EOF
+.Ed
+.Sh PORT SCANNING
+It may be useful to know which ports are open and running services on
+a target machine.
+The
+.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.
+For example:
+.Bd -literal -offset indent
+$ nc -vz 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
+.Pp
+The port range was specified to limit the search to ports 20 \- 30.
+.Pp
+Alternatively, it might be useful to know which server software
+is running, and which versions.
+This information is often contained within the greeting banners.
+In order to retrieve these, it is necessary to first make a connection,
+and then break the connection when the banner has been retrieved.
+This can be accomplished by specifying a small timeout with the
+.Fl w
+flag, or perhaps by issuing a
+.Qq Dv QUIT
+command to the server:
+.Bd -literal -offset indent
+$ echo "QUIT" | nc host.example.com 20-30
+SSH-1.99-OpenSSH_3.6.1p2
+Protocol mismatch.
+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
+the source port, with a timeout of 5 seconds:
+.Pp
+.Dl $ nc -p 31337 -w 5 hostname 42
+.Pp
+Open a UDP connection to port 53 of hostname:
+.Pp
+.Dl $ nc -u hostname 53
+.Pp
+Open a TCP connection to port 42 of example.host 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
+.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
+.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:
+.Pp
+.Dl $ nc -x10.2.3.4:8080 -Xconnect hostname 42
+.Sh SEE ALSO
+.Xr cat 1
+.Sh AUTHORS
+Original implementation by *Hobbit*
+.Aq hobbit@avian.org .
+.br
+Rewritten with IPv6 support by
+.An Eric Jackson Aq ericj@monkey.org .
diff --git a/contrib/netcat/netcat.c b/contrib/netcat/netcat.c
new file mode 100644
index 0000000..3c610b9
--- /dev/null
+++ b/contrib/netcat/netcat.c
@@ -0,0 +1,802 @@
+/* $OpenBSD: netcat.c,v 1.76 2004/12/10 16:51:31 hshoexer Exp $ */
+/*
+ * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * Re-written nc(1) for OpenBSD. Original implementation by
+ * *Hobbit* <hobbit@avian.org>.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/telnet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <poll.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifndef SUN_LEN
+#define SUN_LEN(su) \
+ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
+#endif
+
+#define PORT_MAX 65535
+#define PORT_MAX_LEN 6
+
+/* Command Line Options */
+int dflag; /* detached, no stdin */
+int iflag; /* Interval Flag */
+int kflag; /* More than one connect */
+int lflag; /* Bind to local port */
+int nflag; /* Don't do name look up */
+char *pflag; /* Localport flag */
+int rflag; /* Random ports flag */
+char *sflag; /* Source Address */
+int tflag; /* Telnet Emulation */
+int uflag; /* UDP - Default to TCP */
+int vflag; /* Verbosity */
+int xflag; /* Socks proxy */
+int zflag; /* Port Scan Flag */
+int Dflag; /* sodebug */
+int Sflag; /* TCP MD5 signature option */
+
+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 udptest(int);
+int unix_connect(char *);
+int unix_listen(char *);
+void usage(int);
+
+int
+main(int argc, char *argv[])
+{
+ int ch, s, ret, socksv;
+ char *host, *uport, *endp;
+ struct addrinfo hints;
+ struct servent *sv;
+ socklen_t len;
+ struct sockaddr_storage cliaddr;
+ char *proxy;
+ char *proxyhost = "", *proxyport = NULL;
+ struct addrinfo proxyhints;
+
+ ret = 1;
+ s = 0;
+ socksv = 5;
+ host = NULL;
+ uport = NULL;
+ endp = NULL;
+ sv = NULL;
+
+ while ((ch = getopt(argc, argv, "46Ddhi:klnp:rSs:tUuvw:X:x:z")) != -1) {
+ switch (ch) {
+ case '4':
+ family = AF_INET;
+ break;
+ case '6':
+ family = AF_INET6;
+ break;
+ case 'U':
+ family = AF_UNIX;
+ break;
+ case 'X':
+ if (strcasecmp(optarg, "connect") == 0)
+ socksv = -1; /* HTTP proxy CONNECT */
+ else if (strcmp(optarg, "4") == 0)
+ socksv = 4; /* SOCKS v.4 */
+ else if (strcmp(optarg, "5") == 0)
+ socksv = 5; /* SOCKS v.5 */
+ else
+ errx(1, "unsupported proxy protocol");
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'h':
+ help();
+ break;
+ case 'i':
+ iflag = (int)strtoul(optarg, &endp, 10);
+ if (iflag < 0 || *endp != '\0')
+ errx(1, "interval cannot be negative");
+ break;
+ case 'k':
+ kflag = 1;
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 'p':
+ pflag = optarg;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 's':
+ sflag = optarg;
+ break;
+ case 't':
+ tflag = 1;
+ break;
+ case 'u':
+ uflag = 1;
+ break;
+ case 'v':
+ 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 *= 1000;
+ break;
+ case 'x':
+ xflag = 1;
+ if ((proxy = strdup(optarg)) == NULL)
+ err(1, NULL);
+ break;
+ case 'z':
+ zflag = 1;
+ break;
+ case 'D':
+ Dflag = 1;
+ break;
+ case 'S':
+ Sflag = 1;
+ break;
+ default:
+ usage(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* 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]) {
+ if (!lflag)
+ usage(1);
+ uport = argv[0];
+ host = NULL;
+ } else if (argv[0] && argv[1]) {
+ host = argv[0];
+ uport = argv[1];
+ } else
+ usage(1);
+
+ if (lflag && sflag)
+ errx(1, "cannot use -s and -l");
+ if (lflag && pflag)
+ errx(1, "cannot use -p and -l");
+ if (lflag && zflag)
+ errx(1, "cannot use -z and -l");
+ if (!lflag && kflag)
+ errx(1, "must use -l with -k");
+
+ /* Initialize addrinfo structure. */
+ if (family != AF_UNIX) {
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = family;
+ hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
+ if (nflag)
+ hints.ai_flags |= AI_NUMERICHOST;
+ }
+
+ if (xflag) {
+ if (uflag)
+ errx(1, "no proxy support for UDP mode");
+
+ if (lflag)
+ errx(1, "no proxy support for listen");
+
+ if (family == AF_UNIX)
+ errx(1, "no proxy support for unix sockets");
+
+ /* XXX IPv6 transport to proxy would probably work */
+ if (family == AF_INET6)
+ errx(1, "no proxy support for IPv6");
+
+ if (sflag)
+ errx(1, "no proxy support for local source address");
+
+ proxyhost = strsep(&proxy, ":");
+ proxyport = proxy;
+
+ memset(&proxyhints, 0, sizeof(struct addrinfo));
+ proxyhints.ai_family = family;
+ proxyhints.ai_socktype = SOCK_STREAM;
+ proxyhints.ai_protocol = IPPROTO_TCP;
+ if (nflag)
+ proxyhints.ai_flags |= AI_NUMERICHOST;
+ }
+
+ if (lflag) {
+ int connfd;
+ ret = 0;
+
+ if (family == AF_UNIX)
+ s = unix_listen(host);
+
+ /* Allow only one connection at a time, but stay alive. */
+ for (;;) {
+ if (family != AF_UNIX)
+ s = local_listen(host, uport, hints);
+ if (s < 0)
+ err(1, NULL);
+ /*
+ * For UDP, we will use recvfrom() initially
+ * to wait for a caller, then use the regular
+ * functions to talk to the caller.
+ */
+ if (uflag) {
+ int rv;
+ char buf[1024];
+ struct sockaddr_storage z;
+
+ len = sizeof(z);
+ rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK,
+ (struct sockaddr *)&z, &len);
+ if (rv < 0)
+ err(1, "recvfrom");
+
+ rv = connect(s, (struct sockaddr *)&z, len);
+ if (rv < 0)
+ err(1, "connect");
+
+ connfd = s;
+ } else {
+ connfd = accept(s, (struct sockaddr *)&cliaddr,
+ &len);
+ }
+
+ readwrite(connfd);
+ close(connfd);
+ if (family != AF_UNIX)
+ close(s);
+
+ if (!kflag)
+ break;
+ }
+ } else if (family == AF_UNIX) {
+ ret = 0;
+
+ if ((s = unix_connect(host)) > 0 && !zflag) {
+ readwrite(s);
+ close(s);
+ } else
+ ret = 1;
+
+ exit(ret);
+
+ } else {
+ int i = 0;
+
+ /* Construct the portlist[] array. */
+ build_ports(uport);
+
+ /* Cycle through portlist, connecting to each port. */
+ for (i = 0; portlist[i] != NULL; i++) {
+ if (s)
+ close(s);
+
+ if (xflag)
+ s = socks_connect(host, portlist[i], hints,
+ proxyhost, proxyport, proxyhints, socksv);
+ else
+ s = remote_connect(host, portlist[i], hints);
+
+ if (s < 0)
+ continue;
+
+ ret = 0;
+ if (vflag || zflag) {
+ /* For UDP, make sure we are connected. */
+ if (uflag) {
+ if (udptest(s) == -1) {
+ ret = 1;
+ continue;
+ }
+ }
+
+ /* Don't look up port if -n. */
+ if (nflag)
+ sv = NULL;
+ else {
+ sv = getservbyport(
+ ntohs(atoi(portlist[i])),
+ uflag ? "udp" : "tcp");
+ }
+
+ printf("Connection to %s %s port [%s/%s] succeeded!\n",
+ host, portlist[i], uflag ? "udp" : "tcp",
+ sv ? sv->s_name : "*");
+ }
+ if (!zflag)
+ readwrite(s);
+ }
+ }
+
+ if (s)
+ close(s);
+
+ exit(ret);
+}
+
+/*
+ * unix_connect()
+ * Returns a socket connected to a local unix socket. Returns -1 on failure.
+ */
+int
+unix_connect(char *path)
+{
+ struct sockaddr_un sun;
+ int s;
+
+ 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;
+
+ if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
+ sizeof(sun.sun_path)) {
+ close(s);
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ 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)
+{
+ struct sockaddr_un sun;
+ int s;
+
+ /* Create unix domain socket. */
+ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ return (-1);
+
+ memset(&sun, 0, sizeof(struct sockaddr_un));
+ sun.sun_family = AF_UNIX;
+
+ if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
+ sizeof(sun.sun_path)) {
+ close(s);
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+
+ if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
+ close(s);
+ return (-1);
+ }
+
+ if (listen(s, 5) < 0) {
+ close(s);
+ return (-1);
+ }
+ return (s);
+}
+
+/*
+ * remote_connect()
+ * Returns a socket connected to a remote host. Properly binds to a local
+ * port or source address if needed. Returns -1 on failure.
+ */
+int
+remote_connect(char *host, char *port, struct addrinfo hints)
+{
+ struct addrinfo *res, *res0;
+ int s, error, x = 1;
+
+ if ((error = getaddrinfo(host, port, &hints, &res)))
+ errx(1, "getaddrinfo: %s", gai_strerror(error));
+
+ res0 = res;
+ do {
+ if ((s = socket(res0->ai_family, res0->ai_socktype,
+ res0->ai_protocol)) < 0)
+ continue;
+
+ /* Bind to a local port or source address if specified. */
+ 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;
+ ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
+ ahints.ai_flags = AI_PASSIVE;
+ if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
+ errx(1, "getaddrinfo: %s", gai_strerror(error));
+
+ if (bind(s, (struct sockaddr *)ares->ai_addr,
+ ares->ai_addrlen) < 0)
+ 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);
+ }
+
+ if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
+ break;
+ else if (vflag)
+ warn("connect to %s port %s (%s) failed", host, port,
+ uflag ? "udp" : "tcp");
+
+ close(s);
+ s = -1;
+ } while ((res0 = res0->ai_next) != NULL);
+
+ freeaddrinfo(res);
+
+ return (s);
+}
+
+/*
+ * local_listen()
+ * Returns a socket listening on a local port, binds to specified source
+ * address. Returns -1 on failure.
+ */
+int
+local_listen(char *host, char *port, struct addrinfo hints)
+{
+ struct addrinfo *res, *res0;
+ int s, ret, x = 1;
+ int error;
+
+ /* Allow nodename to be null. */
+ hints.ai_flags |= AI_PASSIVE;
+
+ /*
+ * In the case of binding to a wildcard address
+ * default to binding to an ipv4 address.
+ */
+ if (host == NULL && hints.ai_family == AF_UNSPEC)
+ hints.ai_family = AF_INET;
+
+ if ((error = getaddrinfo(host, port, &hints, &res)))
+ errx(1, "getaddrinfo: %s", gai_strerror(error));
+
+ res0 = res;
+ do {
+ if ((s = socket(res0->ai_family, res0->ai_socktype,
+ res0->ai_protocol)) == 0)
+ continue;
+
+ ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
+ if (ret == -1)
+ err(1, NULL);
+ 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)
+ break;
+
+ close(s);
+ s = -1;
+ } while ((res0 = res0->ai_next) != NULL);
+
+ if (!uflag && s != -1) {
+ if (listen(s, 1) < 0)
+ err(1, "listen");
+ }
+
+ freeaddrinfo(res);
+
+ return (s);
+}
+
+/*
+ * readwrite()
+ * Loop that polls on the network file descriptor and stdin.
+ */
+void
+readwrite(int nfd)
+{
+ struct pollfd pfd[2];
+ unsigned char buf[BUFSIZ];
+ int wfd = fileno(stdin), n;
+ int lfd = fileno(stdout);
+
+ /* Setup Network FD */
+ pfd[0].fd = nfd;
+ pfd[0].events = POLLIN;
+
+ /* Set up STDIN FD. */
+ pfd[1].fd = wfd;
+ pfd[1].events = POLLIN;
+
+ while (pfd[0].fd != -1) {
+ if (iflag)
+ sleep(iflag);
+
+ if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
+ close(nfd);
+ err(1, "Polling Error");
+ }
+
+ if (n == 0)
+ return;
+
+ if (pfd[0].revents & POLLIN) {
+ if ((n = read(nfd, buf, sizeof(buf))) < 0)
+ return;
+ else if (n == 0) {
+ shutdown(nfd, SHUT_RD);
+ pfd[0].fd = -1;
+ pfd[0].events = 0;
+ } else {
+ if (tflag)
+ atelnet(nfd, buf, n);
+ if (atomicio((ssize_t (*)(int, void *, size_t))write,
+ lfd, buf, n) != n)
+ return;
+ }
+ }
+
+ if (!dflag && pfd[1].revents & POLLIN) {
+ if ((n = read(wfd, buf, sizeof(buf))) < 0)
+ return;
+ else if (n == 0) {
+ shutdown(nfd, SHUT_WR);
+ pfd[1].fd = -1;
+ pfd[1].events = 0;
+ } else {
+ if (atomicio((ssize_t (*)(int, void *, size_t))write,
+ nfd, buf, n) != n)
+ return;
+ }
+ }
+ }
+}
+
+/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
+void
+atelnet(int nfd, unsigned char *buf, unsigned int size)
+{
+ unsigned char *p, *end;
+ unsigned char obuf[4];
+
+ end = buf + size;
+ obuf[0] = '\0';
+
+ for (p = buf; p < end; p++) {
+ if (*p != IAC)
+ break;
+
+ obuf[0] = IAC;
+ p++;
+ if ((*p == WILL) || (*p == WONT))
+ obuf[1] = DONT;
+ if ((*p == DO) || (*p == DONT))
+ obuf[1] = WONT;
+ if (obuf) {
+ p++;
+ obuf[2] = *p;
+ obuf[3] = '\0';
+ if (atomicio((ssize_t (*)(int, void *, size_t))write,
+ nfd, obuf, 3) != 3)
+ warnx("Write Error!");
+ obuf[0] = '\0';
+ }
+ }
+}
+
+/*
+ * build_ports()
+ * Build an array or ports in portlist[], listing each port
+ * that we should try to connect to.
+ */
+void
+build_ports(char *p)
+{
+ char *n, *endp;
+ int hi, lo, cp;
+ int x = 0;
+
+ if ((n = strchr(p, '-')) != NULL) {
+ if (lflag)
+ errx(1, "Cannot use -l with multiple ports!");
+
+ *n = '\0';
+ 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");
+
+ if (lo > hi) {
+ cp = hi;
+ hi = lo;
+ lo = cp;
+ }
+
+ /* Load ports sequentially. */
+ for (cp = lo; cp <= hi; cp++) {
+ portlist[x] = calloc(1, PORT_MAX_LEN);
+ if (portlist[x] == NULL)
+ err(1, NULL);
+ snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
+ x++;
+ }
+
+ /* Randomly swap ports. */
+ if (rflag) {
+ int y;
+ char *c;
+
+ for (x = 0; x <= (hi - lo); x++) {
+ y = (arc4random() & 0xFFFF) % (hi - lo);
+ c = portlist[x];
+ portlist[x] = portlist[y];
+ portlist[y] = c;
+ }
+ }
+ } else {
+ hi = (int)strtoul(p, &endp, 10);
+ if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
+ errx(1, "port range not valid");
+ portlist[0] = calloc(1, PORT_MAX_LEN);
+ if (portlist[0] == NULL)
+ err(1, NULL);
+ portlist[0] = p;
+ }
+}
+
+/*
+ * udptest()
+ * Do a few writes to see if the UDP port is there.
+ * XXX - Better way of doing this? Doesn't work for IPv6.
+ * Also fails after around 100 ports checked.
+ */
+int
+udptest(int s)
+{
+ int i, ret;
+
+ for (i = 0; i <= 3; i++) {
+ if (write(s, "X", 1) == 1)
+ ret = 1;
+ else
+ ret = -1;
+ }
+ return (ret);
+}
+
+void
+help(void)
+{
+ usage(0);
+ fprintf(stderr, "\tCommand Summary:\n\
+ \t-4 Use IPv4\n\
+ \t-6 Use IPv6\n\
+ \t-D Enable the debug socket option\n\
+ \t-d Detach from stdin\n\
+ \t-h This help text\n\
+ \t-i secs\t Delay interval for lines sent, ports scanned\n\
+ \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 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 Answer TELNET negotiation\n\
+ \t-U Use UNIX domain socket\n\
+ \t-u UDP mode\n\
+ \t-v Verbose\n\
+ \t-w secs\t Timeout for connects and final net reads\n\
+ \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
+ \t-x addr[:port]\tSpecify proxy address and port\n\
+ \t-z Zero-I/O mode [used for scanning]\n\
+ Port numbers can be individual or ranges: lo-hi [inclusive]\n");
+ exit(1);
+}
+
+void
+usage(int ret)
+{
+ fprintf(stderr, "usage: nc [-46DdhklnrStUuvz] [-i interval] [-p source_port]\n");
+ fprintf(stderr, "\t [-s source_ip_address] [-w timeout] [-X proxy_version]\n");
+ fprintf(stderr, "\t [-x proxy_address[:port]] [hostname] [port[s]]\n");
+ if (ret)
+ exit(1);
+}
diff --git a/contrib/netcat/socks.c b/contrib/netcat/socks.c
new file mode 100644
index 0000000..e7d35b6
--- /dev/null
+++ b/contrib/netcat/socks.c
@@ -0,0 +1,235 @@
+/* $OpenBSD: socks.c,v 1.9 2004/10/17 03:13:55 djm Exp $ */
+
+/*
+ * Copyright (c) 1999 Niklas Hallqvist. 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define SOCKS_PORT "1080"
+#define HTTP_PROXY_PORT "3128"
+#define HTTP_MAXHDRS 64
+#define SOCKS_V5 5
+#define SOCKS_V4 4
+#define SOCKS_NOAUTH 0
+#define SOCKS_NOMETHOD 0xff
+#define SOCKS_CONNECT 1
+#define SOCKS_IPV4 1
+
+
+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)
+{
+ 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);
+}
+
+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;
+ }
+ if (*s != '\0' && *p == '\0')
+ return htons (port);
+ errx (1, "cannot decode port \"%s\"", s);
+}
+
+static int
+proxy_read_line(int fd, char *buf, int bufsz)
+{
+ int r, 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;
+ err(1, "proxy read");
+ }
+ /* Skip CR */
+ if (buf[off] == '\r')
+ continue;
+ if (buf[off] == '\n') {
+ buf[off] = '\0';
+ break;
+ }
+ off++;
+ }
+ return (off);
+}
+
+int
+socks_connect(char *host, char *port, struct addrinfo hints,
+ char *proxyhost, char *proxyport, struct addrinfo proxyhints,
+ int socksv)
+{
+ int proxyfd, r;
+ unsigned char buf[1024];
+ ssize_t cnt;
+ in_addr_t serveraddr;
+ in_port_t serverport;
+
+ if (proxyport == NULL)
+ proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT;
+
+ proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
+
+ if (proxyfd < 0)
+ return -1;
+
+ serveraddr = decode_addr (host);
+ serverport = decode_port (port);
+
+ if (socksv == 5) {
+ /* 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");
+ if (cnt != 3)
+ errx (1, "short write, %d (expected 3)", cnt);
+
+ read (proxyfd, buf, 2);
+ if (buf[1] == SOCKS_NOMETHOD)
+ 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);
+
+ /* XXX Handle short reads better */
+ cnt = read (proxyfd, buf, sizeof buf);
+ if (cnt == -1)
+ err (1, "read failed");
+ if (cnt != 10)
+ errx (1, "unexpected reply size %d (expected 10)", cnt);
+ if (buf[1] != 0)
+ errx (1, "connection failed, SOCKS error %d", buf[1]);
+ } else if (socksv == 4) {
+ /* Version 4 */
+ buf[0] = SOCKS_V4;
+ buf[1] = SOCKS_CONNECT; /* connect */
+ memcpy (buf + 2, &serverport, sizeof serverport);
+ memcpy (buf + 4, &serveraddr, sizeof serveraddr);
+ buf[8] = 0; /* empty username */
+
+ 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");
+ if (cnt != 8)
+ errx (1, "unexpected reply size %d (expected 8)", cnt);
+ if (buf[1] != 90)
+ 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");
+
+ /* 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",
+ host, ntohs(serverport));
+ } else {
+ r = snprintf(buf, sizeof(buf),
+ "CONNECT %s:%d HTTP/1.0\r\n\r\n",
+ host, ntohs(serverport));
+ }
+ if (r == -1 || 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");
+ if (cnt != r)
+ errx (1, "short write, %d (expected %d)", cnt, r);
+
+ /* Read reply */
+ 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;
+ }
+ } else
+ errx (1, "Unknown proxy protocol %d", socksv);
+
+ return proxyfd;
+}
OpenPOWER on IntegriCloud