summaryrefslogtreecommitdiff
path: root/src/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr.bin')
-rw-r--r--src/usr.bin/nc/Makefile6
-rw-r--r--src/usr.bin/nc/atomicio.c58
-rw-r--r--src/usr.bin/nc/nc.1198
-rw-r--r--src/usr.bin/nc/netcat.c738
-rw-r--r--src/usr.bin/nc/socks.c171
5 files changed, 1171 insertions, 0 deletions
diff --git a/src/usr.bin/nc/Makefile b/src/usr.bin/nc/Makefile
new file mode 100644
index 0000000000..150f8295bd
--- /dev/null
+++ b/src/usr.bin/nc/Makefile
@@ -0,0 +1,6 @@
1# $OpenBSD: Makefile,v 1.6 2001/09/02 18:45:41 jakob Exp $
2
3PROG= nc
4SRCS= netcat.c atomicio.c socks.c
5
6.include <bsd.prog.mk>
diff --git a/src/usr.bin/nc/atomicio.c b/src/usr.bin/nc/atomicio.c
new file mode 100644
index 0000000000..f404eeedd8
--- /dev/null
+++ b/src/usr.bin/nc/atomicio.c
@@ -0,0 +1,58 @@
1/*
2 * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <sys/types.h>
27#include <sys/uio.h>
28
29#include <errno.h>
30#include <unistd.h>
31
32/*
33 * ensure all of data on socket comes through. f==read || f==write
34 */
35ssize_t
36atomicio(f, fd, _s, n)
37 ssize_t (*f) ();
38 int fd;
39 void *_s;
40 size_t n;
41{
42 char *s = _s;
43 ssize_t res, pos = 0;
44
45 while (n > pos) {
46 res = (f) (fd, s + pos, n - pos);
47 switch (res) {
48 case -1:
49 if (errno == EINTR || errno == EAGAIN)
50 continue;
51 case 0:
52 return (res);
53 default:
54 pos += res;
55 }
56 }
57 return (pos);
58}
diff --git a/src/usr.bin/nc/nc.1 b/src/usr.bin/nc/nc.1
new file mode 100644
index 0000000000..759be26a31
--- /dev/null
+++ b/src/usr.bin/nc/nc.1
@@ -0,0 +1,198 @@
1.\" $OpenBSD: nc.1,v 1.22 2002/02/28 18:05:36 markus Exp $
2.\"
3.\" Copyright (c) 1996 David Sacerdote
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. The name of the author may not be used to endorse or promote products
15.\" derived from this software without specific prior written permission
16.\"
17.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
27.\"
28.Dd June 25, 2001
29.Dt NC 1
30.Os
31.Sh NAME
32.Nm nc
33.Nd "arbitrary TCP and UDP connections and listens"
34.Sh SYNOPSIS
35.Nm nc
36.Op Fl 46hklnrtuvzU
37.Op Fl i Ar interval
38.Op Fl p Ar source port
39.Op Fl s Ar source ip address
40.Op Fl x Ar proxy address Op :port
41.Op Fl w Ar timeout
42.Op Fl X Ar socks version
43.Op Ar hostname
44.Op Ar port[s]
45.Sh DESCRIPTION
46The
47.Nm
48(or
49.Nm netcat )
50utility is used for just about anything under the sun involving TCP
51or UDP.
52It can open TCP connections, send UDP packets, listen on arbitrary
53TCP and UDP ports, do port scanning, and deal with both IPv4 and
54IPv6.
55Unlike
56.Xr telnet 1 ,
57.Nm
58scripts nicely, and separates error messages onto standard error instead
59of sending them to standard output, as
60.Xr telnet 1 ,
61does with some.
62.Pp
63Destination ports can be single integers or ranges.
64Ranges are in the form nn-mm.
65.Pp
66Common uses include:
67.Pp
68.Bl -bullet -offset indent -compact
69.It
70simple TCP proxies
71.It
72shell\-script based HTTP clients and servers
73.It
74network daemon testing
75.It
76and much, much more
77.El
78.Pp
79The options are as follows:
80.Bl -tag -width Ds
81.It Fl 4
82Forces
83.Nm
84to use IPv4 addresses only.
85.It Fl 6
86Forces
87.Nm
88to use IPv6 addresses only.
89.It Fl h
90Prints out
91.Nm
92help.
93.It Fl i Ar interval
94Specifies a delay time interval between lines of text sent and received.
95Also causes a delay time between connections to multiple ports.
96.It Fl k
97Forces
98.Nm
99to stay listening for another connection after its current connection
100is completed.
101.It Fl l
102Used to specify that
103.Nm
104should listen for an incoming connection rather than initiate a
105connection to a remote host.
106.It Fl n
107Do not do any DNS or service lookups on any specified addresses,
108hostnames or ports.
109.It Fl p Ar port
110Specifies the source port
111.Nm
112should use, subject to privilege restrictions and availability.
113.It Fl r
114Specifies that source and/or destination ports should be chosen randomly
115instead of sequentially within a range or in the order that the system
116assigns them.
117.It Fl s Ar hostname/ip address
118Specifies the IP of the interface which is used to send the packets.
119.It Fl t
120Causes
121.Nm
122to send RFC854 DON'T and WON'T responses to RFC854 DO and WILL requests.
123This makes it possible to use
124.Nm
125to script telnet sessions.
126.It Fl u
127Use UDP instead of the default option of TCP.
128.It Fl v
129Have
130.Nm
131give more verbose output.
132.It Fl x Ar proxy address Op :port
133Requests that
134.Nm
135should connect to
136.Ar hostname
137using a SOCKS proxy at address and port.
138If port is not specified, port 1080 is used.
139.It Fl z
140Specifies that
141.Nm
142should just scan for listening daemons, without sending any data to them.
143.It Fl U
144Specifies to use Unix Domain Sockets.
145.It Fl X Ar version
146Requests that
147.Nm
148should use the specified version of the SOCKS protocol when talking to
149a SOCKS proxy.
150If version is not specified, SOCKS version 5 is used.
151.El
152.Sh EXAMPLES
153.Bl -tag -width x
154.It Li "nc hostname 42"
155Open a TCP connection to port 42 of hostname.
156.It Li "nc -p 31337 hostname 42"
157Open a TCP connection to port 42 of hostname, and use port 31337 as
158the source port.
159.It Li "nc -w 5 hostname 42"
160Open a TCP connection to port 42 of hostname, and timeout after
161five seconds while attempting to connect.
162.It Li "nc -u hostname 53"
163Open a UDP connection to port 53 of hostname.
164.It Li "nc -s 10.1.2.3 example.host 42"
165Open a TCP connection to port 42 of example.host using 10.1.2.3 as the
166IP for the local end of the connection.
167.It Li "nc -v hostname 42"
168Open a TCP connection to port 42 of hostname, displaying some
169diagnostic messages on stderr.
170.It Li "nc -v -z hostname 20-30"
171Attempt to open TCP connections to ports 20 through 30 of
172hostname, and report which ones
173.Nm
174was able to connect to.
175.It Li "nc -v -u -z -w 3 hostname 20-30"
176Send UDP packets to ports 20-30 of example.host, and report which ones
177did not respond with an ICMP packet after three seconds.
178.It Li "nc -l 3000"
179Listen on TCP port 3000, and once there is a connection, send stdin to
180the remote host, and send data from the remote host to stdout.
181.It Li "echo foobar | nc hostname 1000"
182Connect to port 1000 of hostname, send the string "foobar"
183followed by a newline, and move data from port 1000 of hostname to
184stdout until hostname closes the connection.
185.It Li "nc -U /var/tmp/dsocket"
186Connect to a Unix Domain Socket.
187.It Li "nc -lU /var/tmp/dsocket"
188Create and listen on a Unix Domain Socket.
189.El
190.Sh SEE ALSO
191.Xr cat 1 ,
192.Xr telnet 1
193.Sh AUTHORS
194Original implementation by *Hobbit*
195.Aq hobbit@avian.org .
196.Pp
197Rewritten with IPv6 support by Eric Jackson
198.Aq ericj@monkey.org .
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
new file mode 100644
index 0000000000..9e6acc9f6d
--- /dev/null
+++ b/src/usr.bin/nc/netcat.c
@@ -0,0 +1,738 @@
1/* $OpenBSD: netcat.c,v 1.52 2002/07/04 04:42:25 vincent Exp $ */
2/*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
27 */
28
29/*
30 * Re-written nc(1) for OpenBSD. Original implementation by
31 * *Hobbit* <hobbit@avian.org>.
32 */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <sys/time.h>
37#include <sys/un.h>
38
39#include <netinet/in.h>
40#include <arpa/telnet.h>
41
42#include <err.h>
43#include <errno.h>
44#include <netdb.h>
45#include <poll.h>
46#include <stdarg.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <unistd.h>
51#include <fcntl.h>
52
53#ifndef SUN_LEN
54#define SUN_LEN(su) \
55 (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
56#endif
57
58#define PORT_MAX 65535
59
60/* Command Line Options */
61int iflag; /* Interval Flag */
62int kflag; /* More than one connect */
63int lflag; /* Bind to local port */
64int nflag; /* Dont do name lookup */
65char *pflag; /* Localport flag */
66int rflag; /* Random ports flag */
67char *sflag; /* Source Address */
68int tflag; /* Telnet Emulation */
69int uflag; /* UDP - Default to TCP */
70int vflag; /* Verbosity */
71int xflag; /* Socks proxy */
72int zflag; /* Port Scan Flag */
73
74int timeout = -1;
75int family = AF_UNSPEC;
76char *portlist[PORT_MAX];
77
78ssize_t atomicio(ssize_t (*)(), int, void *, size_t);
79void atelnet(int, unsigned char *, unsigned int);
80void build_ports(char *);
81void help(void);
82int local_listen(char *, char *, struct addrinfo);
83void readwrite(int);
84int remote_connect(char *, char *, struct addrinfo);
85int socks_connect(char *, char *, struct addrinfo, char *, char *,
86 struct addrinfo, int);
87int udptest(int);
88int unix_connect(char *);
89int unix_listen(char *);
90void usage(int);
91
92int
93main(int argc, char *argv[])
94{
95 int ch, s, ret, socksv;
96 char *host, *uport, *endp;
97 struct addrinfo hints;
98 struct servent *sv;
99 socklen_t len;
100 struct sockaddr *cliaddr;
101 char *proxy;
102 char *proxyhost = "", *proxyport = NULL;
103 struct addrinfo proxyhints;
104
105 ret = 1;
106 s = 0;
107 socksv = 5;
108 host = NULL;
109 uport = NULL;
110 endp = NULL;
111 sv = NULL;
112
113 while ((ch = getopt(argc, argv, "46UX:hi:klnp:rs:tuvw:x:z")) != -1) {
114 switch (ch) {
115 case '4':
116 family = AF_INET;
117 break;
118 case '6':
119 family = AF_INET6;
120 break;
121 case 'U':
122 family = AF_UNIX;
123 break;
124 case 'X':
125 socksv = (int)strtoul(optarg, &endp, 10);
126 if ((socksv != 4 && socksv != 5) || *endp != '\0')
127 errx(1, "only SOCKS version 4 and 5 supported");
128 break;
129 case 'h':
130 help();
131 break;
132 case 'i':
133 iflag = (int)strtoul(optarg, &endp, 10);
134 if (iflag < 0 || *endp != '\0')
135 errx(1, "interval cannot be negative");
136 break;
137 case 'k':
138 kflag = 1;
139 break;
140 case 'l':
141 lflag = 1;
142 break;
143 case 'n':
144 nflag = 1;
145 break;
146 case 'p':
147 pflag = optarg;
148 break;
149 case 'r':
150 rflag = 1;
151 break;
152 case 's':
153 sflag = optarg;
154 break;
155 case 't':
156 tflag = 1;
157 break;
158 case 'u':
159 uflag = 1;
160 break;
161 case 'v':
162 vflag = 1;
163 break;
164 case 'w':
165 timeout = (int)strtoul(optarg, &endp, 10);
166 if (timeout < 0 || *endp != '\0')
167 errx(1, "timeout cannot be negative");
168 if (timeout >= (INT_MAX / 1000))
169 errx(1, "timeout too large");
170 timeout *= 1000;
171 break;
172 case 'x':
173 xflag = 1;
174 proxy = strdup(optarg);
175 break;
176 case 'z':
177 zflag = 1;
178 break;
179 default:
180 usage(1);
181 }
182 }
183 argc -= optind;
184 argv += optind;
185
186 /* Cruft to make sure options are clean, and used properly. */
187 if (argv[0] && !argv[1] && family == AF_UNIX) {
188 if (uflag)
189 errx(1, "cannot use -u and -U");
190 host = argv[0];
191 uport = NULL;
192 } else if (argv[0] && !argv[1]) {
193 if (!lflag)
194 usage(1);
195 uport = argv[0];
196 host = NULL;
197 } else if (argv[0] && argv[1]) {
198 host = argv[0];
199 uport = argv[1];
200 } else
201 usage(1);
202
203 if (lflag && sflag)
204 errx(1, "cannot use -s and -l");
205 if (lflag && pflag)
206 errx(1, "cannot use -p and -l");
207 if (lflag && zflag)
208 errx(1, "cannot use -z and -l");
209 if (!lflag && kflag)
210 errx(1, "must use -l with -k");
211
212 /* Initialize addrinfo structure */
213 if (family != AF_UNIX) {
214 memset(&hints, 0, sizeof(struct addrinfo));
215 hints.ai_family = family;
216 hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
217 hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
218 if (nflag)
219 hints.ai_flags |= AI_NUMERICHOST;
220 }
221
222
223 if (xflag) {
224 if (uflag)
225 errx(1, "no proxy support for UDP mode");
226
227 if (lflag)
228 errx(1, "no proxy support for listen");
229
230 if (family == AF_UNIX)
231 errx(1, "no proxy support for unix sockets");
232
233 /* XXX IPv6 transport to proxy would probably work */
234 if (family == AF_INET6)
235 errx(1, "no proxy support for IPv6");
236
237 if (sflag)
238 errx(1, "no proxy support for local source address");
239
240 proxyhost = strsep(&proxy, ":");
241 proxyport = proxy;
242
243 memset(&proxyhints, 0, sizeof(struct addrinfo));
244 proxyhints.ai_family = family;
245 proxyhints.ai_socktype = SOCK_STREAM;
246 proxyhints.ai_protocol = IPPROTO_TCP;
247 if (nflag)
248 proxyhints.ai_flags |= AI_NUMERICHOST;
249 }
250
251 if (lflag) {
252 int connfd;
253 ret = 0;
254
255 if (family == AF_UNIX)
256 s = unix_listen(host);
257
258 /* Allow only one connection at a time, but stay alive */
259 for (;;) {
260 if (family != AF_UNIX)
261 s = local_listen(host, uport, hints);
262 if (s < 0)
263 err(1, NULL);
264 /*
265 * For UDP, we will use recvfrom() initially
266 * to wait for a caller, then use the regular
267 * functions to talk to the caller.
268 */
269 if (uflag) {
270 int rv;
271 char buf[1024];
272 struct sockaddr_storage z;
273
274 len = sizeof(z);
275 rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK,
276 (struct sockaddr *)&z, &len);
277 if (rv < 0)
278 errx(1, "%s", strerror(errno));
279
280 rv = connect(s, (struct sockaddr *)&z, len);
281 if (rv < 0)
282 errx(1, "%s", strerror(errno));
283
284 connfd = s;
285 } else {
286 connfd = accept(s, (struct sockaddr *)&cliaddr,
287 &len);
288 }
289
290 readwrite(connfd);
291 close(connfd);
292 if (family != AF_UNIX)
293 close(s);
294
295 if (!kflag)
296 break;
297 }
298 } else if (family == AF_UNIX) {
299 ret = 0;
300
301 if ((s = unix_connect(host)) > 0 && !zflag) {
302 readwrite(s);
303 close(s);
304 } else
305 ret = 1;
306
307 exit(ret);
308
309 } else {
310 int i = 0;
311
312 /* construct the portlist[] array */
313 build_ports(uport);
314
315 /* Cycle through portlist, connecting to each port */
316 for (i = 0; portlist[i] != NULL; i++) {
317 if (s)
318 close(s);
319
320 if (xflag)
321 s = socks_connect(host, portlist[i], hints,
322 proxyhost, proxyport, proxyhints, socksv);
323 else
324 s = remote_connect(host, portlist[i], hints);
325
326 if (s < 0)
327 continue;
328
329 ret = 0;
330 if (vflag || zflag) {
331 /* For UDP, make sure we are connected */
332 if (uflag) {
333 if (udptest(s) == -1) {
334 ret = 1;
335 continue;
336 }
337 }
338
339 /* Don't lookup port if -n */
340 if (nflag)
341 sv = NULL;
342 else {
343 sv = getservbyport(
344 ntohs(atoi(portlist[i])),
345 uflag ? "udp" : "tcp");
346 }
347
348 printf("Connection to %s %s port [%s/%s] succeeded!\n",
349 host, portlist[i], uflag ? "udp" : "tcp",
350 sv ? sv->s_name : "*");
351 }
352 if (!zflag)
353 readwrite(s);
354 }
355 }
356
357 if (s)
358 close(s);
359
360 exit(ret);
361}
362
363/*
364 * unix_connect()
365 * Return's a socket connected to a local unix socket. Return's -1 on failure.
366 */
367int
368unix_connect(char *path)
369{
370 struct sockaddr_un sun;
371 int s;
372
373 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
374 return (-1);
375 (void)fcntl(s, F_SETFD, 1);
376
377 memset(&sun, 0, sizeof(struct sockaddr_un));
378 sun.sun_family = AF_UNIX;
379 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
380 if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
381 close(s);
382 return (-1);
383 }
384 return (s);
385
386}
387
388/*
389 * unix_listen()
390 * create a unix domain socket, and listen on it.
391 */
392int
393unix_listen(char *path)
394{
395 struct sockaddr_un sun;
396 int s;
397
398 /* create unix domain socket */
399 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
400 return (-1);
401
402 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
403 sun.sun_family = AF_UNIX;
404 if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
405 close(s);
406 return (-1);
407 }
408
409 if (listen(s, 5) < 0) {
410 close(s);
411 return (-1);
412 }
413 return (s);
414}
415
416/*
417 * remote_connect()
418 * Return's a socket connected to a remote host. Properly bind's to a local
419 * port or source address if needed. Return's -1 on failure.
420 */
421int
422remote_connect(char *host, char *port, struct addrinfo hints)
423{
424 struct addrinfo *res, *res0;
425 int s, error;
426
427 if ((error = getaddrinfo(host, port, &hints, &res)))
428 errx(1, "%s", gai_strerror(error));
429
430 res0 = res;
431 do {
432 if ((s = socket(res0->ai_family, res0->ai_socktype,
433 res0->ai_protocol)) < 0)
434 continue;
435
436 /* Bind to a local port or source address if specified */
437 if (sflag || pflag) {
438 struct addrinfo ahints, *ares;
439
440 if (!(sflag && pflag)) {
441 if (!sflag)
442 sflag = NULL;
443 else
444 pflag = NULL;
445 }
446
447 memset(&ahints, 0, sizeof(struct addrinfo));
448 ahints.ai_family = res0->ai_family;
449 ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
450 ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
451 ahints.ai_flags = AI_PASSIVE;
452 if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
453 errx(1, "%s", gai_strerror(error));
454
455 if (bind(s, (struct sockaddr *)ares->ai_addr,
456 ares->ai_addrlen) < 0) {
457 errx(1, "bind failed: %s", strerror(errno));
458 freeaddrinfo(ares);
459 continue;
460 }
461 freeaddrinfo(ares);
462 }
463
464 if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
465 break;
466
467 close(s);
468 s = -1;
469 } while ((res0 = res0->ai_next) != NULL);
470
471 freeaddrinfo(res);
472
473 return (s);
474}
475
476/*
477 * local_listen()
478 * Return's a socket listening on a local port, binds to specified source
479 * address. Return's -1 on failure.
480 */
481int
482local_listen(char *host, char *port, struct addrinfo hints)
483{
484 struct addrinfo *res, *res0;
485 int s, ret, x = 1;
486 int error;
487
488 /* Allow nodename to be null */
489 hints.ai_flags |= AI_PASSIVE;
490
491 /*
492 * In the case of binding to a wildcard address
493 * default to binding to an ipv4 address.
494 */
495 if (host == NULL && hints.ai_family == AF_UNSPEC)
496 hints.ai_family = AF_INET;
497
498 if ((error = getaddrinfo(host, port, &hints, &res)))
499 errx(1, "%s", gai_strerror(error));
500
501 res0 = res;
502 do {
503 if ((s = socket(res0->ai_family, res0->ai_socktype,
504 res0->ai_protocol)) == 0)
505 continue;
506
507 ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
508 if (ret == -1)
509 err(1, NULL);
510
511 if (bind(s, (struct sockaddr *)res0->ai_addr,
512 res0->ai_addrlen) == 0)
513 break;
514
515 close(s);
516 s = -1;
517 } while ((res0 = res0->ai_next) != NULL);
518
519 if (!uflag && s != -1) {
520 if (listen(s, 1) < 0)
521 errx(1, "%s", strerror(errno));
522 }
523
524 freeaddrinfo(res);
525
526 return (s);
527}
528
529/*
530 * readwrite()
531 * Loop that polls on the network file descriptor and stdin.
532 */
533void
534readwrite(int nfd)
535{
536 struct pollfd pfd[2];
537 char buf[BUFSIZ];
538 int wfd = fileno(stdin), n, ret;
539 int lfd = fileno(stdout);
540
541 /* Setup Network FD */
542 pfd[0].fd = nfd;
543 pfd[0].events = POLLIN;
544
545 /* Setup STDIN FD */
546 pfd[1].fd = wfd;
547 pfd[1].events = POLLIN;
548
549 while (pfd[0].fd != -1 || pfd[1].fd != -1) {
550 if (iflag)
551 sleep(iflag);
552
553 if ((n = poll(pfd, 2, timeout)) < 0) {
554 close(nfd);
555 err(1, "Polling Error");
556 }
557
558 if (n == 0)
559 return;
560
561 if (pfd[0].revents & POLLIN) {
562 if ((n = read(nfd, buf, sizeof(buf))) < 0)
563 return;
564 else if (n == 0) {
565 shutdown(nfd, SHUT_RD);
566 pfd[0].fd = -1;
567 pfd[0].events = 0;
568 } else {
569 if (tflag)
570 atelnet(nfd, buf, n);
571 if ((ret = atomicio(write, lfd, buf, n)) != n)
572 return;
573 }
574 }
575
576 if (pfd[1].revents & POLLIN) {
577 if ((n = read(wfd, buf, sizeof(buf))) < 0)
578 return;
579 else if (n == 0) {
580 shutdown(nfd, SHUT_WR);
581 pfd[1].fd = -1;
582 pfd[1].events = 0;
583 } else {
584 if((ret = atomicio(write, nfd, buf, n)) != n)
585 return;
586 }
587 }
588 }
589}
590
591/* Deal with RFC854 WILL/WONT DO/DONT negotiation */
592void
593atelnet(int nfd, unsigned char *buf, unsigned int size)
594{
595 int ret;
596 unsigned char *p, *end;
597 unsigned char obuf[4];
598
599 end = buf + size;
600 obuf[0] = '\0';
601
602 for (p = buf; p < end; p++) {
603 if (*p != IAC)
604 break;
605
606 obuf[0] = IAC;
607 p++;
608 if ((*p == WILL) || (*p == WONT))
609 obuf[1] = DONT;
610 if ((*p == DO) || (*p == DONT))
611 obuf[1] = WONT;
612 if (obuf) {
613 p++;
614 obuf[2] = *p;
615 obuf[3] = '\0';
616 if ((ret = atomicio(write , nfd, obuf, 3)) != 3)
617 warnx("Write Error!");
618 obuf[0] = '\0';
619 }
620 }
621}
622
623/*
624 * build_ports()
625 * Build an array or ports in portlist[], listing each port
626 * that we should try to connect too.
627 */
628void
629build_ports(char *p)
630{
631 char *n, *endp;
632 int hi, lo, cp;
633 int x = 0;
634
635 if ((n = strchr(p, '-')) != NULL) {
636 if (lflag)
637 errx(1, "Cannot use -l with multiple ports!");
638
639 *n = '\0';
640 n++;
641
642 /* Make sure the ports are in order: lowest->highest */
643 hi = (int)strtoul(n, &endp, 10);
644 if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
645 errx(1, "port range not valid");
646 lo = (int)strtoul(p, &endp, 10);
647 if (lo <= 0 || lo > PORT_MAX || *endp != '\0')
648 errx(1, "port range not valid");
649
650 if (lo > hi) {
651 cp = hi;
652 hi = lo;
653 lo = cp;
654 }
655
656 /* Load ports sequentially */
657 for (cp = lo; cp <= hi; cp++) {
658 portlist[x] = calloc(1, PORT_MAX);
659 snprintf(portlist[x], PORT_MAX, "%d", cp);
660 x++;
661 }
662
663 /* Randomly swap ports */
664 if (rflag) {
665 int y;
666 char *c;
667
668 for (x = 0; x <= (hi - lo); x++) {
669 y = (arc4random() & 0xFFFF) % (hi - lo);
670 c = portlist[x];
671 portlist[x] = portlist[y];
672 portlist[y] = c;
673 }
674 }
675 } else {
676 hi = (int)strtoul(p, &endp, 10);
677 if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
678 errx(1, "port range not valid");
679 portlist[0] = calloc(1, PORT_MAX);
680 portlist[0] = p;
681 }
682}
683
684/*
685 * udptest()
686 * Do a few writes to see if the UDP port is there.
687 * XXX - Better way of doing this? Doesn't work for IPv6
688 * Also fails after around 100 ports checked.
689 */
690int
691udptest(int s)
692{
693 int i, rv, ret;
694
695 for (i = 0; i <= 3; i++) {
696 if ((rv = write(s, "X", 1)) == 1)
697 ret = 1;
698 else
699 ret = -1;
700 }
701 return (ret);
702}
703
704void
705help()
706{
707 usage(0);
708 fprintf(stderr, "\tCommand Summary:\n\
709 \t-4 Use IPv4\n\
710 \t-6 Use IPv6\n\
711 \t-U Use UNIX domain socket\n\
712 \t-h This help text\n\
713 \t-i secs\t Delay interval for lines sent, ports scanned\n\
714 \t-k Keep inbound sockets open for multiple connects\n\
715 \t-l Listen mode, for inbound connects\n\
716 \t-n Suppress name/port resolutions\n\
717 \t-p port\t Specify local port for remote connects\n\
718 \t-r Randomize remote ports\n\
719 \t-s addr\t Local source address\n\
720 \t-t Answer TELNET negotiation\n\
721 \t-u UDP mode\n\
722 \t-v Verbose\n\
723 \t-w secs\t Timeout for connects and final net reads\n\
724 \t-x addr[:port]\tSpecify socks5 proxy address and port\n\
725 \t-z Zero-I/O mode [used for scanning]\n\
726 Port numbers can be individual or ranges: lo-hi [inclusive]\n");
727 exit(1);
728}
729
730void
731usage(int ret)
732{
733 fprintf(stderr, "usage: nc [-46Uhklnrtuvz] [-i interval] [-p source port]\n");
734 fprintf(stderr, "\t [-s ip address] [-w timeout] [-x proxy address [:port]]\n");
735 fprintf(stderr, "\t [hostname] [port[s...]]\n");
736 if (ret)
737 exit(1);
738}
diff --git a/src/usr.bin/nc/socks.c b/src/usr.bin/nc/socks.c
new file mode 100644
index 0000000000..af0fe29cff
--- /dev/null
+++ b/src/usr.bin/nc/socks.c
@@ -0,0 +1,171 @@
1/* $OpenBSD: socks.c,v 1.5 2002/02/28 18:05:36 markus Exp $ */
2
3/*
4 * Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Niklas Hallqvist.
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/types.h>
33#include <sys/socket.h>
34#include <netinet/in.h>
35#include <arpa/inet.h>
36
37#include <err.h>
38#include <netdb.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43
44#define SOCKS_PORT "1080"
45#define SOCKS_V5 5
46#define SOCKS_V4 4
47#define SOCKS_NOAUTH 0
48#define SOCKS_NOMETHOD 0xff
49#define SOCKS_CONNECT 1
50#define SOCKS_IPV4 1
51#define SOCKS_MAXCMDSZ 10
52
53int remote_connect(char *, char *, struct addrinfo);
54
55static in_addr_t
56decode_addr (const char *s)
57{
58 struct hostent *hp = gethostbyname (s);
59 struct in_addr retval;
60
61 if (hp)
62 return *(in_addr_t *)hp->h_addr_list[0];
63 if (inet_aton (s, &retval))
64 return retval.s_addr;
65 errx (1, "cannot decode address \"%s\"", s);
66}
67
68static in_port_t
69decode_port (const char *s)
70{
71 struct servent *sp;
72 in_port_t port;
73 char *p;
74
75 port = strtol (s, &p, 10);
76 if (s == p) {
77 sp = getservbyname (s, "tcp");
78 if (sp)
79 return sp->s_port;
80 }
81 if (*s != '\0' && *p == '\0')
82 return htons (port);
83 errx (1, "cannot decode port \"%s\"", s);
84}
85
86int
87socks_connect (char *host, char *port, struct addrinfo hints,
88 char *proxyhost, char *proxyport, struct addrinfo proxyhints,
89 int socksv)
90{
91 int proxyfd;
92 unsigned char buf[SOCKS_MAXCMDSZ];
93 ssize_t cnt;
94 in_addr_t serveraddr;
95 in_port_t serverport;
96
97 if (proxyport)
98 proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
99 else
100 proxyfd = remote_connect(proxyhost, SOCKS_PORT, proxyhints);
101
102 if (!proxyfd)
103 return -1;
104
105 serveraddr = decode_addr (host);
106 serverport = decode_port (port);
107
108 if (socksv == 5) {
109 /* Version 5, one method: no authentication */
110 buf[0] = SOCKS_V5;
111 buf[1] = 1;
112 buf[2] = SOCKS_NOAUTH;
113 cnt = write (proxyfd, buf, 3);
114 if (cnt == -1)
115 err (1, "write failed");
116 if (cnt != 3)
117 errx (1, "short write, %d (expected 3)", cnt);
118
119 read (proxyfd, buf, 2);
120 if (buf[1] == SOCKS_NOMETHOD)
121 errx (1, "authentication method negotiation failed");
122
123 /* Version 5, connect: IPv4 address */
124 buf[0] = SOCKS_V5;
125 buf[1] = SOCKS_CONNECT;
126 buf[2] = 0;
127 buf[3] = SOCKS_IPV4;
128 memcpy (buf + 4, &serveraddr, sizeof serveraddr);
129 memcpy (buf + 8, &serverport, sizeof serverport);
130
131 /* XXX Handle short writes better */
132 cnt = write (proxyfd, buf, 10);
133 if (cnt == -1)
134 err (1, "write failed");
135 if (cnt != 10)
136 errx (1, "short write, %d (expected 10)", cnt);
137
138 /* XXX Handle short reads better */
139 cnt = read (proxyfd, buf, sizeof buf);
140 if (cnt == -1)
141 err (1, "read failed");
142 if (cnt != 10)
143 errx (1, "unexpected reply size %d (expected 10)", cnt);
144 if (buf[1] != 0)
145 errx (1, "connection failed, SOCKS error %d", buf[1]);
146 } else {
147 /* Version 4 */
148 buf[0] = SOCKS_V4;
149 buf[1] = SOCKS_CONNECT; /* connect */
150 memcpy (buf + 2, &serverport, sizeof serverport);
151 memcpy (buf + 4, &serveraddr, sizeof serveraddr);
152 buf[8] = 0; /* empty username */
153
154 cnt = write (proxyfd, buf, 9);
155 if (cnt == -1)
156 err (1, "write failed");
157 if (cnt != 9)
158 errx (1, "short write, %d (expected 9)", cnt);
159
160 /* XXX Handle short reads better */
161 cnt = read (proxyfd, buf, 8);
162 if (cnt == -1)
163 err (1, "read failed");
164 if (cnt != 8)
165 errx (1, "unexpected reply size %d (expected 8)", cnt);
166 if (buf[1] != 90)
167 errx (1, "connection failed, SOCKS error %d", buf[1]);
168 }
169
170 return proxyfd;
171}