summaryrefslogtreecommitdiff
path: root/src/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/usr.bin/nc/Makefile6
-rw-r--r--src/usr.bin/nc/atomicio.c69
-rw-r--r--src/usr.bin/nc/atomicio.h39
-rw-r--r--src/usr.bin/nc/nc.1467
-rw-r--r--src/usr.bin/nc/netcat.c1047
-rw-r--r--src/usr.bin/nc/socks.c340
6 files changed, 0 insertions, 1968 deletions
diff --git a/src/usr.bin/nc/Makefile b/src/usr.bin/nc/Makefile
deleted file mode 100644
index 150f8295bd..0000000000
--- a/src/usr.bin/nc/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
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
deleted file mode 100644
index feb6f19440..0000000000
--- a/src/usr.bin/nc/atomicio.c
+++ /dev/null
@@ -1,69 +0,0 @@
1/* $OpenBSD: atomicio.c,v 1.10 2011/01/08 00:47:19 jeremy Exp $ */
2/*
3 * Copyright (c) 2006 Damien Miller. All rights reserved.
4 * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
5 * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
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#include <sys/param.h>
30
31#include <errno.h>
32#include <poll.h>
33#include <unistd.h>
34
35#include "atomicio.h"
36
37/*
38 * ensure all of data on socket comes through. f==read || f==vwrite
39 */
40size_t
41atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
42{
43 char *s = _s;
44 size_t pos = 0;
45 ssize_t res;
46 struct pollfd pfd;
47
48 pfd.fd = fd;
49 pfd.events = f == read ? POLLIN : POLLOUT;
50 while (n > pos) {
51 res = (f) (fd, s + pos, n - pos);
52 switch (res) {
53 case -1:
54 if (errno == EINTR)
55 continue;
56 if ((errno == EAGAIN) || (errno == ENOBUFS)) {
57 (void)poll(&pfd, 1, -1);
58 continue;
59 }
60 return 0;
61 case 0:
62 errno = EPIPE;
63 return pos;
64 default:
65 pos += (size_t)res;
66 }
67 }
68 return (pos);
69}
diff --git a/src/usr.bin/nc/atomicio.h b/src/usr.bin/nc/atomicio.h
deleted file mode 100644
index 7bf5b25418..0000000000
--- a/src/usr.bin/nc/atomicio.h
+++ /dev/null
@@ -1,39 +0,0 @@
1/* $OpenBSD: atomicio.h,v 1.2 2007/09/07 14:50:44 tobias Exp $ */
2
3/*
4 * Copyright (c) 2006 Damien Miller. All rights reserved.
5 * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
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#ifndef _ATOMICIO_H
30#define _ATOMICIO_H
31
32/*
33 * Ensure all of data on socket comes through. f==read || f==vwrite
34 */
35size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
36
37#define vwrite (ssize_t (*)(int, void *, size_t))write
38
39#endif /* _ATOMICIO_H */
diff --git a/src/usr.bin/nc/nc.1 b/src/usr.bin/nc/nc.1
deleted file mode 100644
index 232b6f5b6e..0000000000
--- a/src/usr.bin/nc/nc.1
+++ /dev/null
@@ -1,467 +0,0 @@
1.\" $OpenBSD: nc.1,v 1.61 2012/07/07 15:33:02 haesbaert 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 $Mdocdate: July 7 2012 $
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.Bk -words
37.Op Fl 46DdhklnrStUuvz
38.Op Fl I Ar length
39.Op Fl i Ar interval
40.Op Fl O Ar length
41.Op Fl P Ar proxy_username
42.Op Fl p Ar source_port
43.Op Fl s Ar source
44.Op Fl T Ar toskeyword
45.Op Fl V Ar rtable
46.Op Fl w Ar timeout
47.Op Fl X Ar proxy_protocol
48.Oo Xo
49.Fl x Ar proxy_address Ns Oo : Ns
50.Ar port Oc
51.Xc Oc
52.Op Ar destination
53.Op Ar port
54.Ek
55.Sh DESCRIPTION
56The
57.Nm
58(or
59.Nm netcat )
60utility is used for just about anything under the sun involving TCP,
61UDP, or
62.Ux Ns -domain
63sockets.
64It can open TCP connections, send UDP packets, listen on arbitrary
65TCP and UDP ports, do port scanning, and deal with both IPv4 and
66IPv6.
67Unlike
68.Xr telnet 1 ,
69.Nm
70scripts nicely, and separates error messages onto standard error instead
71of sending them to standard output, as
72.Xr telnet 1
73does with some.
74.Pp
75Common uses include:
76.Pp
77.Bl -bullet -offset indent -compact
78.It
79simple TCP proxies
80.It
81shell-script based HTTP clients and servers
82.It
83network daemon testing
84.It
85a SOCKS or HTTP ProxyCommand for
86.Xr ssh 1
87.It
88and much, much more
89.El
90.Pp
91The options are as follows:
92.Bl -tag -width Ds
93.It Fl 4
94Forces
95.Nm
96to use IPv4 addresses only.
97.It Fl 6
98Forces
99.Nm
100to use IPv6 addresses only.
101.It Fl D
102Enable debugging on the socket.
103.It Fl d
104Do not attempt to read from stdin.
105.It Fl h
106Prints out
107.Nm
108help.
109.It Fl I Ar length
110Specifies the size of the TCP receive buffer.
111.It Fl i Ar interval
112Specifies a delay time interval between lines of text sent and received.
113Also causes a delay time between connections to multiple ports.
114.It Fl k
115Forces
116.Nm
117to stay listening for another connection after its current connection
118is completed.
119It is an error to use this option without the
120.Fl l
121option.
122When used together with the
123.Fl u
124option, the server socket is not connected and it can receive UDP datagrams from
125multiple hosts.
126.It Fl l
127Used to specify that
128.Nm
129should listen for an incoming connection rather than initiate a
130connection to a remote host.
131It is an error to use this option in conjunction with the
132.Fl p ,
133.Fl s ,
134or
135.Fl z
136options.
137Additionally, any timeouts specified with the
138.Fl w
139option are ignored.
140.It Fl n
141Do not do any DNS or service lookups on any specified addresses,
142hostnames or ports.
143.It Fl O Ar length
144Specifies the size of the TCP send buffer.
145.It Fl P Ar proxy_username
146Specifies a username to present to a proxy server that requires authentication.
147If no username is specified then authentication will not be attempted.
148Proxy authentication is only supported for HTTP CONNECT proxies at present.
149.It Fl p Ar source_port
150Specifies the source port
151.Nm
152should use, subject to privilege restrictions and availability.
153It is an error to use this option in conjunction with the
154.Fl l
155option.
156.It Fl r
157Specifies that source and/or destination ports should be chosen randomly
158instead of sequentially within a range or in the order that the system
159assigns them.
160.It Fl S
161Enables the RFC 2385 TCP MD5 signature option.
162.It Fl s Ar source
163Specifies the IP of the interface which is used to send the packets.
164For
165.Ux Ns -domain
166datagram sockets, specifies the local temporary socket file
167to create and use so that datagrams can be received.
168It is an error to use this option in conjunction with the
169.Fl l
170option.
171.It Fl T Ar toskeyword
172Change IPv4 TOS value.
173.Ar toskeyword
174may be one of
175.Ar critical ,
176.Ar inetcontrol ,
177.Ar lowdelay ,
178.Ar netcontrol ,
179.Ar throughput ,
180.Ar reliability ,
181or one of the DiffServ Code Points:
182.Ar ef ,
183.Ar af11 ... af43 ,
184.Ar cs0 ... cs7 ;
185or a number in either hex or decimal.
186.It Fl t
187Causes
188.Nm
189to send RFC 854 DON'T and WON'T responses to RFC 854 DO and WILL requests.
190This makes it possible to use
191.Nm
192to script telnet sessions.
193.It Fl U
194Specifies to use
195.Ux Ns -domain
196sockets.
197.It Fl u
198Use UDP instead of the default option of TCP.
199For
200.Ux Ns -domain
201sockets, use a datagram socket instead of a stream socket.
202If a
203.Ux Ns -domain
204socket is used, a temporary receiving socket is created in
205.Pa /tmp
206unless the
207.Fl s
208flag is given.
209.It Fl V Ar rtable
210Set the routing table to be used.
211The default is 0.
212.It Fl v
213Have
214.Nm
215give more verbose output.
216.It Fl w Ar timeout
217Connections which cannot be established or are idle timeout after
218.Ar timeout
219seconds.
220The
221.Fl w
222flag has no effect on the
223.Fl l
224option, i.e.\&
225.Nm
226will listen forever for a connection, with or without the
227.Fl w
228flag.
229The default is no timeout.
230.It Fl X Ar proxy_protocol
231Requests that
232.Nm
233should use the specified protocol when talking to the proxy server.
234Supported protocols are
235.Dq 4
236(SOCKS v.4),
237.Dq 5
238(SOCKS v.5)
239and
240.Dq connect
241(HTTPS proxy).
242If the protocol is not specified, SOCKS version 5 is used.
243.It Xo
244.Fl x Ar proxy_address Ns Oo : Ns
245.Ar port Oc
246.Xc
247Requests that
248.Nm
249should connect to
250.Ar destination
251using a proxy at
252.Ar proxy_address
253and
254.Ar port .
255If
256.Ar port
257is not specified, the well-known port for the proxy protocol is used (1080
258for SOCKS, 3128 for HTTPS).
259.It Fl z
260Specifies that
261.Nm
262should just scan for listening daemons, without sending any data to them.
263It is an error to use this option in conjunction with the
264.Fl l
265option.
266.El
267.Pp
268.Ar destination
269can be a numerical IP address or a symbolic hostname
270(unless the
271.Fl n
272option is given).
273In general, a destination must be specified,
274unless the
275.Fl l
276option is given
277(in which case the local host is used).
278For
279.Ux Ns -domain
280sockets, a destination is required and is the socket path to connect to
281(or listen on if the
282.Fl l
283option is given).
284.Pp
285.Ar port
286can be a single integer or a range of ports.
287Ranges are in the form nn-mm.
288In general,
289a destination port must be specified,
290unless the
291.Fl U
292option is given.
293.Sh CLIENT/SERVER MODEL
294It is quite simple to build a very basic client/server model using
295.Nm .
296On one console, start
297.Nm
298listening on a specific port for a connection.
299For example:
300.Pp
301.Dl $ nc -l 1234
302.Pp
303.Nm
304is now listening on port 1234 for a connection.
305On a second console
306.Pq or a second machine ,
307connect to the machine and port being listened on:
308.Pp
309.Dl $ nc 127.0.0.1 1234
310.Pp
311There should now be a connection between the ports.
312Anything typed at the second console will be concatenated to the first,
313and vice-versa.
314After the connection has been set up,
315.Nm
316does not really care which side is being used as a
317.Sq server
318and which side is being used as a
319.Sq client .
320The connection may be terminated using an
321.Dv EOF
322.Pq Sq ^D .
323.Sh DATA TRANSFER
324The example in the previous section can be expanded to build a
325basic data transfer model.
326Any information input into one end of the connection will be output
327to the other end, and input and output can be easily captured in order to
328emulate file transfer.
329.Pp
330Start by using
331.Nm
332to listen on a specific port, with output captured into a file:
333.Pp
334.Dl $ nc -l 1234 \*(Gt filename.out
335.Pp
336Using a second machine, connect to the listening
337.Nm
338process, feeding it the file which is to be transferred:
339.Pp
340.Dl $ nc host.example.com 1234 \*(Lt filename.in
341.Pp
342After the file has been transferred, the connection will close automatically.
343.Sh TALKING TO SERVERS
344It is sometimes useful to talk to servers
345.Dq by hand
346rather than through a user interface.
347It can aid in troubleshooting,
348when it might be necessary to verify what data a server is sending
349in response to commands issued by the client.
350For example, to retrieve the home page of a web site:
351.Bd -literal -offset indent
352$ printf "GET / HTTP/1.0\er\en\er\en" | nc host.example.com 80
353.Ed
354.Pp
355Note that this also displays the headers sent by the web server.
356They can be filtered, using a tool such as
357.Xr sed 1 ,
358if necessary.
359.Pp
360More complicated examples can be built up when the user knows the format
361of requests required by the server.
362As another example, an email may be submitted to an SMTP server using:
363.Bd -literal -offset indent
364$ nc localhost 25 \*(Lt\*(Lt EOF
365HELO host.example.com
366MAIL FROM:\*(Ltuser@host.example.com\*(Gt
367RCPT TO:\*(Ltuser2@host.example.com\*(Gt
368DATA
369Body of email.
370\&.
371QUIT
372EOF
373.Ed
374.Sh PORT SCANNING
375It may be useful to know which ports are open and running services on
376a target machine.
377The
378.Fl z
379flag can be used to tell
380.Nm
381to report open ports,
382rather than initiate a connection.
383For example:
384.Bd -literal -offset indent
385$ nc -z host.example.com 20-30
386Connection to host.example.com 22 port [tcp/ssh] succeeded!
387Connection to host.example.com 25 port [tcp/smtp] succeeded!
388.Ed
389.Pp
390The port range was specified to limit the search to ports 20 \- 30.
391.Pp
392Alternatively, it might be useful to know which server software
393is running, and which versions.
394This information is often contained within the greeting banners.
395In order to retrieve these, it is necessary to first make a connection,
396and then break the connection when the banner has been retrieved.
397This can be accomplished by specifying a small timeout with the
398.Fl w
399flag, or perhaps by issuing a
400.Qq Dv QUIT
401command to the server:
402.Bd -literal -offset indent
403$ echo "QUIT" | nc host.example.com 20-30
404SSH-1.99-OpenSSH_3.6.1p2
405Protocol mismatch.
406220 host.example.com IMS SMTP Receiver Version 0.84 Ready
407.Ed
408.Sh EXAMPLES
409Open a TCP connection to port 42 of host.example.com, using port 31337 as
410the source port, with a timeout of 5 seconds:
411.Pp
412.Dl $ nc -p 31337 -w 5 host.example.com 42
413.Pp
414Open a UDP connection to port 53 of host.example.com:
415.Pp
416.Dl $ nc -u host.example.com 53
417.Pp
418Open a TCP connection to port 42 of host.example.com using 10.1.2.3 as the
419IP for the local end of the connection:
420.Pp
421.Dl $ nc -s 10.1.2.3 host.example.com 42
422.Pp
423Create and listen on a
424.Ux Ns -domain
425stream socket:
426.Pp
427.Dl $ nc -lU /var/tmp/dsocket
428.Pp
429Connect to port 42 of host.example.com via an HTTP proxy at 10.2.3.4,
430port 8080.
431This example could also be used by
432.Xr ssh 1 ;
433see the
434.Cm ProxyCommand
435directive in
436.Xr ssh_config 5
437for more information.
438.Pp
439.Dl $ nc -x10.2.3.4:8080 -Xconnect host.example.com 42
440.Pp
441The same example again, this time enabling proxy authentication with username
442.Dq ruser
443if the proxy requires it:
444.Pp
445.Dl $ nc -x10.2.3.4:8080 -Xconnect -Pruser host.example.com 42
446.Sh SEE ALSO
447.Xr cat 1 ,
448.Xr ssh 1
449.Sh AUTHORS
450Original implementation by *Hobbit*
451.Aq hobbit@avian.org .
452.br
453Rewritten with IPv6 support by
454.An Eric Jackson Aq ericj@monkey.org .
455.Sh CAVEATS
456UDP port scans using the
457.Fl uz
458combination of flags will always report success irrespective of
459the target machine's state.
460However,
461in conjunction with a traffic sniffer either on the target machine
462or an intermediary device,
463the
464.Fl uz
465combination could be useful for communications diagnostics.
466Note that the amount of UDP traffic generated may be limited either
467due to hardware resources and/or configuration settings.
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
deleted file mode 100644
index a034bbab8c..0000000000
--- a/src/usr.bin/nc/netcat.c
+++ /dev/null
@@ -1,1047 +0,0 @@
1/* $OpenBSD: netcat.c,v 1.109 2012/07/07 15:33:02 haesbaert 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 <netinet/in_systm.h>
41#include <netinet/tcp.h>
42#include <netinet/ip.h>
43#include <arpa/telnet.h>
44
45#include <err.h>
46#include <errno.h>
47#include <netdb.h>
48#include <poll.h>
49#include <stdarg.h>
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53#include <unistd.h>
54#include <fcntl.h>
55#include <limits.h>
56#include "atomicio.h"
57
58#ifndef SUN_LEN
59#define SUN_LEN(su) \
60 (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
61#endif
62
63#define PORT_MAX 65535
64#define PORT_MAX_LEN 6
65#define UNIX_DG_TMP_SOCKET_SIZE 19
66
67/* Command Line Options */
68int dflag; /* detached, no stdin */
69unsigned int iflag; /* Interval Flag */
70int kflag; /* More than one connect */
71int lflag; /* Bind to local port */
72int nflag; /* Don't do name look up */
73char *Pflag; /* Proxy username */
74char *pflag; /* Localport flag */
75int rflag; /* Random ports flag */
76char *sflag; /* Source Address */
77int tflag; /* Telnet Emulation */
78int uflag; /* UDP - Default to TCP */
79int vflag; /* Verbosity */
80int xflag; /* Socks proxy */
81int zflag; /* Port Scan Flag */
82int Dflag; /* sodebug */
83int Iflag; /* TCP receive buffer size */
84int Oflag; /* TCP send buffer size */
85int Sflag; /* TCP MD5 signature option */
86int Tflag = -1; /* IP Type of Service */
87u_int rtableid;
88
89int timeout = -1;
90int family = AF_UNSPEC;
91char *portlist[PORT_MAX+1];
92char *unix_dg_tmp_socket;
93
94void atelnet(int, unsigned char *, unsigned int);
95void build_ports(char *);
96void help(void);
97int local_listen(char *, char *, struct addrinfo);
98void readwrite(int);
99int remote_connect(const char *, const char *, struct addrinfo);
100int timeout_connect(int, const struct sockaddr *, socklen_t);
101int socks_connect(const char *, const char *, struct addrinfo,
102 const char *, const char *, struct addrinfo, int, const char *);
103int udptest(int);
104int unix_bind(char *);
105int unix_connect(char *);
106int unix_listen(char *);
107void set_common_sockopts(int);
108int map_tos(char *, int *);
109void report_connect(const struct sockaddr *, socklen_t);
110void usage(int);
111
112int
113main(int argc, char *argv[])
114{
115 int ch, s, ret, socksv;
116 char *host, *uport;
117 struct addrinfo hints;
118 struct servent *sv;
119 socklen_t len;
120 struct sockaddr_storage cliaddr;
121 char *proxy;
122 const char *errstr, *proxyhost = "", *proxyport = NULL;
123 struct addrinfo proxyhints;
124 char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
125
126 ret = 1;
127 s = 0;
128 socksv = 5;
129 host = NULL;
130 uport = NULL;
131 sv = NULL;
132
133 while ((ch = getopt(argc, argv,
134 "46DdhI:i:klnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
135 switch (ch) {
136 case '4':
137 family = AF_INET;
138 break;
139 case '6':
140 family = AF_INET6;
141 break;
142 case 'U':
143 family = AF_UNIX;
144 break;
145 case 'X':
146 if (strcasecmp(optarg, "connect") == 0)
147 socksv = -1; /* HTTP proxy CONNECT */
148 else if (strcmp(optarg, "4") == 0)
149 socksv = 4; /* SOCKS v.4 */
150 else if (strcmp(optarg, "5") == 0)
151 socksv = 5; /* SOCKS v.5 */
152 else
153 errx(1, "unsupported proxy protocol");
154 break;
155 case 'd':
156 dflag = 1;
157 break;
158 case 'h':
159 help();
160 break;
161 case 'i':
162 iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
163 if (errstr)
164 errx(1, "interval %s: %s", errstr, optarg);
165 break;
166 case 'k':
167 kflag = 1;
168 break;
169 case 'l':
170 lflag = 1;
171 break;
172 case 'n':
173 nflag = 1;
174 break;
175 case 'P':
176 Pflag = optarg;
177 break;
178 case 'p':
179 pflag = optarg;
180 break;
181 case 'r':
182 rflag = 1;
183 break;
184 case 's':
185 sflag = optarg;
186 break;
187 case 't':
188 tflag = 1;
189 break;
190 case 'u':
191 uflag = 1;
192 break;
193 case 'V':
194 rtableid = (unsigned int)strtonum(optarg, 0,
195 RT_TABLEID_MAX, &errstr);
196 if (errstr)
197 errx(1, "rtable %s: %s", errstr, optarg);
198 break;
199 case 'v':
200 vflag = 1;
201 break;
202 case 'w':
203 timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
204 if (errstr)
205 errx(1, "timeout %s: %s", errstr, optarg);
206 timeout *= 1000;
207 break;
208 case 'x':
209 xflag = 1;
210 if ((proxy = strdup(optarg)) == NULL)
211 err(1, NULL);
212 break;
213 case 'z':
214 zflag = 1;
215 break;
216 case 'D':
217 Dflag = 1;
218 break;
219 case 'I':
220 Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
221 if (errstr != NULL)
222 errx(1, "TCP receive window %s: %s",
223 errstr, optarg);
224 break;
225 case 'O':
226 Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
227 if (errstr != NULL)
228 errx(1, "TCP send window %s: %s",
229 errstr, optarg);
230 break;
231 case 'S':
232 Sflag = 1;
233 break;
234 case 'T':
235 errstr = NULL;
236 errno = 0;
237 if (map_tos(optarg, &Tflag))
238 break;
239 if (strlen(optarg) > 1 && optarg[0] == '0' &&
240 optarg[1] == 'x')
241 Tflag = (int)strtol(optarg, NULL, 16);
242 else
243 Tflag = (int)strtonum(optarg, 0, 255,
244 &errstr);
245 if (Tflag < 0 || Tflag > 255 || errstr || errno)
246 errx(1, "illegal tos value %s", optarg);
247 break;
248 default:
249 usage(1);
250 }
251 }
252 argc -= optind;
253 argv += optind;
254
255 /* Cruft to make sure options are clean, and used properly. */
256 if (argv[0] && !argv[1] && family == AF_UNIX) {
257 host = argv[0];
258 uport = NULL;
259 } else if (argv[0] && !argv[1]) {
260 if (!lflag)
261 usage(1);
262 uport = argv[0];
263 host = NULL;
264 } else if (argv[0] && argv[1]) {
265 host = argv[0];
266 uport = argv[1];
267 } else
268 usage(1);
269
270 if (lflag && sflag)
271 errx(1, "cannot use -s and -l");
272 if (lflag && pflag)
273 errx(1, "cannot use -p and -l");
274 if (lflag && zflag)
275 errx(1, "cannot use -z and -l");
276 if (!lflag && kflag)
277 errx(1, "must use -l with -k");
278
279 /* Get name of temporary socket for unix datagram client */
280 if ((family == AF_UNIX) && uflag && !lflag) {
281 if (sflag) {
282 unix_dg_tmp_socket = sflag;
283 } else {
284 strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
285 UNIX_DG_TMP_SOCKET_SIZE);
286 if (mktemp(unix_dg_tmp_socket_buf) == NULL)
287 err(1, "mktemp");
288 unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
289 }
290 }
291
292 /* Initialize addrinfo structure. */
293 if (family != AF_UNIX) {
294 memset(&hints, 0, sizeof(struct addrinfo));
295 hints.ai_family = family;
296 hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
297 hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
298 if (nflag)
299 hints.ai_flags |= AI_NUMERICHOST;
300 }
301
302 if (xflag) {
303 if (uflag)
304 errx(1, "no proxy support for UDP mode");
305
306 if (lflag)
307 errx(1, "no proxy support for listen");
308
309 if (family == AF_UNIX)
310 errx(1, "no proxy support for unix sockets");
311
312 /* XXX IPv6 transport to proxy would probably work */
313 if (family == AF_INET6)
314 errx(1, "no proxy support for IPv6");
315
316 if (sflag)
317 errx(1, "no proxy support for local source address");
318
319 proxyhost = strsep(&proxy, ":");
320 proxyport = proxy;
321
322 memset(&proxyhints, 0, sizeof(struct addrinfo));
323 proxyhints.ai_family = family;
324 proxyhints.ai_socktype = SOCK_STREAM;
325 proxyhints.ai_protocol = IPPROTO_TCP;
326 if (nflag)
327 proxyhints.ai_flags |= AI_NUMERICHOST;
328 }
329
330 if (lflag) {
331 int connfd;
332 ret = 0;
333
334 if (family == AF_UNIX) {
335 if (uflag)
336 s = unix_bind(host);
337 else
338 s = unix_listen(host);
339 }
340
341 /* Allow only one connection at a time, but stay alive. */
342 for (;;) {
343 if (family != AF_UNIX)
344 s = local_listen(host, uport, hints);
345 if (s < 0)
346 err(1, NULL);
347 /*
348 * For UDP and -k, don't connect the socket, let it
349 * receive datagrams from multiple socket pairs.
350 */
351 if (uflag && kflag)
352 readwrite(s);
353 /*
354 * For UDP and not -k, we will use recvfrom() initially
355 * to wait for a caller, then use the regular functions
356 * to talk to the caller.
357 */
358 else if (uflag && !kflag) {
359 int rv, plen;
360 char buf[16384];
361 struct sockaddr_storage z;
362
363 len = sizeof(z);
364 plen = 2048;
365 rv = recvfrom(s, buf, plen, MSG_PEEK,
366 (struct sockaddr *)&z, &len);
367 if (rv < 0)
368 err(1, "recvfrom");
369
370 rv = connect(s, (struct sockaddr *)&z, len);
371 if (rv < 0)
372 err(1, "connect");
373
374 if (vflag)
375 report_connect((struct sockaddr *)&z, len);
376
377 readwrite(s);
378 } else {
379 len = sizeof(cliaddr);
380 connfd = accept(s, (struct sockaddr *)&cliaddr,
381 &len);
382 if (connfd == -1)
383 err(1, "accept");
384
385 if (vflag)
386 report_connect((struct sockaddr *)&cliaddr, len);
387
388 readwrite(connfd);
389 close(connfd);
390 }
391
392 if (family != AF_UNIX)
393 close(s);
394 else if (uflag) {
395 if (connect(s, NULL, 0) < 0)
396 err(1, "connect");
397 }
398
399 if (!kflag)
400 break;
401 }
402 } else if (family == AF_UNIX) {
403 ret = 0;
404
405 if ((s = unix_connect(host)) > 0 && !zflag) {
406 readwrite(s);
407 close(s);
408 } else
409 ret = 1;
410
411 if (uflag)
412 unlink(unix_dg_tmp_socket);
413 exit(ret);
414
415 } else {
416 int i = 0;
417
418 /* Construct the portlist[] array. */
419 build_ports(uport);
420
421 /* Cycle through portlist, connecting to each port. */
422 for (i = 0; portlist[i] != NULL; i++) {
423 if (s)
424 close(s);
425
426 if (xflag)
427 s = socks_connect(host, portlist[i], hints,
428 proxyhost, proxyport, proxyhints, socksv,
429 Pflag);
430 else
431 s = remote_connect(host, portlist[i], hints);
432
433 if (s < 0)
434 continue;
435
436 ret = 0;
437 if (vflag || zflag) {
438 /* For UDP, make sure we are connected. */
439 if (uflag) {
440 if (udptest(s) == -1) {
441 ret = 1;
442 continue;
443 }
444 }
445
446 /* Don't look up port if -n. */
447 if (nflag)
448 sv = NULL;
449 else {
450 sv = getservbyport(
451 ntohs(atoi(portlist[i])),
452 uflag ? "udp" : "tcp");
453 }
454
455 fprintf(stderr,
456 "Connection to %s %s port [%s/%s] "
457 "succeeded!\n", host, portlist[i],
458 uflag ? "udp" : "tcp",
459 sv ? sv->s_name : "*");
460 }
461 if (!zflag)
462 readwrite(s);
463 }
464 }
465
466 if (s)
467 close(s);
468
469 exit(ret);
470}
471
472/*
473 * unix_bind()
474 * Returns a unix socket bound to the given path
475 */
476int
477unix_bind(char *path)
478{
479 struct sockaddr_un sun;
480 int s;
481
482 /* Create unix domain socket. */
483 if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM,
484 0)) < 0)
485 return (-1);
486
487 memset(&sun, 0, sizeof(struct sockaddr_un));
488 sun.sun_family = AF_UNIX;
489
490 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
491 sizeof(sun.sun_path)) {
492 close(s);
493 errno = ENAMETOOLONG;
494 return (-1);
495 }
496
497 if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
498 close(s);
499 return (-1);
500 }
501 return (s);
502}
503
504/*
505 * unix_connect()
506 * Returns a socket connected to a local unix socket. Returns -1 on failure.
507 */
508int
509unix_connect(char *path)
510{
511 struct sockaddr_un sun;
512 int s;
513
514 if (uflag) {
515 if ((s = unix_bind(unix_dg_tmp_socket)) < 0)
516 return (-1);
517 } else {
518 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
519 return (-1);
520 }
521 (void)fcntl(s, F_SETFD, 1);
522
523 memset(&sun, 0, sizeof(struct sockaddr_un));
524 sun.sun_family = AF_UNIX;
525
526 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
527 sizeof(sun.sun_path)) {
528 close(s);
529 errno = ENAMETOOLONG;
530 return (-1);
531 }
532 if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
533 close(s);
534 return (-1);
535 }
536 return (s);
537
538}
539
540/*
541 * unix_listen()
542 * Create a unix domain socket, and listen on it.
543 */
544int
545unix_listen(char *path)
546{
547 int s;
548 if ((s = unix_bind(path)) < 0)
549 return (-1);
550
551 if (listen(s, 5) < 0) {
552 close(s);
553 return (-1);
554 }
555 return (s);
556}
557
558/*
559 * remote_connect()
560 * Returns a socket connected to a remote host. Properly binds to a local
561 * port or source address if needed. Returns -1 on failure.
562 */
563int
564remote_connect(const char *host, const char *port, struct addrinfo hints)
565{
566 struct addrinfo *res, *res0;
567 int s, error, on = 1;
568
569 if ((error = getaddrinfo(host, port, &hints, &res)))
570 errx(1, "getaddrinfo: %s", gai_strerror(error));
571
572 res0 = res;
573 do {
574 if ((s = socket(res0->ai_family, res0->ai_socktype,
575 res0->ai_protocol)) < 0)
576 continue;
577
578 if (rtableid) {
579 if (setsockopt(s, SOL_SOCKET, SO_RTABLE, &rtableid,
580 sizeof(rtableid)) == -1)
581 err(1, "setsockopt SO_RTABLE");
582 }
583
584 /* Bind to a local port or source address if specified. */
585 if (sflag || pflag) {
586 struct addrinfo ahints, *ares;
587
588 /* try SO_BINDANY, but don't insist */
589 setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
590 memset(&ahints, 0, sizeof(struct addrinfo));
591 ahints.ai_family = res0->ai_family;
592 ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
593 ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
594 ahints.ai_flags = AI_PASSIVE;
595 if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
596 errx(1, "getaddrinfo: %s", gai_strerror(error));
597
598 if (bind(s, (struct sockaddr *)ares->ai_addr,
599 ares->ai_addrlen) < 0)
600 errx(1, "bind failed: %s", strerror(errno));
601 freeaddrinfo(ares);
602 }
603
604 set_common_sockopts(s);
605
606 if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
607 break;
608 else if (vflag)
609 warn("connect to %s port %s (%s) failed", host, port,
610 uflag ? "udp" : "tcp");
611
612 close(s);
613 s = -1;
614 } while ((res0 = res0->ai_next) != NULL);
615
616 freeaddrinfo(res);
617
618 return (s);
619}
620
621int
622timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
623{
624 struct pollfd pfd;
625 socklen_t optlen;
626 int flags, optval;
627 int ret;
628
629 if (timeout != -1) {
630 flags = fcntl(s, F_GETFL, 0);
631 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
632 err(1, "set non-blocking mode");
633 }
634
635 if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
636 pfd.fd = s;
637 pfd.events = POLLOUT;
638 if ((ret = poll(&pfd, 1, timeout)) == 1) {
639 optlen = sizeof(optval);
640 if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
641 &optval, &optlen)) == 0) {
642 errno = optval;
643 ret = optval == 0 ? 0 : -1;
644 }
645 } else if (ret == 0) {
646 errno = ETIMEDOUT;
647 ret = -1;
648 } else
649 err(1, "poll failed");
650 }
651
652 if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
653 err(1, "restoring flags");
654
655 return (ret);
656}
657
658/*
659 * local_listen()
660 * Returns a socket listening on a local port, binds to specified source
661 * address. Returns -1 on failure.
662 */
663int
664local_listen(char *host, char *port, struct addrinfo hints)
665{
666 struct addrinfo *res, *res0;
667 int s, ret, x = 1;
668 int error;
669
670 /* Allow nodename to be null. */
671 hints.ai_flags |= AI_PASSIVE;
672
673 /*
674 * In the case of binding to a wildcard address
675 * default to binding to an ipv4 address.
676 */
677 if (host == NULL && hints.ai_family == AF_UNSPEC)
678 hints.ai_family = AF_INET;
679
680 if ((error = getaddrinfo(host, port, &hints, &res)))
681 errx(1, "getaddrinfo: %s", gai_strerror(error));
682
683 res0 = res;
684 do {
685 if ((s = socket(res0->ai_family, res0->ai_socktype,
686 res0->ai_protocol)) < 0)
687 continue;
688
689 if (rtableid) {
690 if (setsockopt(s, IPPROTO_IP, SO_RTABLE, &rtableid,
691 sizeof(rtableid)) == -1)
692 err(1, "setsockopt SO_RTABLE");
693 }
694
695 ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
696 if (ret == -1)
697 err(1, NULL);
698
699 set_common_sockopts(s);
700
701 if (bind(s, (struct sockaddr *)res0->ai_addr,
702 res0->ai_addrlen) == 0)
703 break;
704
705 close(s);
706 s = -1;
707 } while ((res0 = res0->ai_next) != NULL);
708
709 if (!uflag && s != -1) {
710 if (listen(s, 1) < 0)
711 err(1, "listen");
712 }
713
714 freeaddrinfo(res);
715
716 return (s);
717}
718
719/*
720 * readwrite()
721 * Loop that polls on the network file descriptor and stdin.
722 */
723void
724readwrite(int nfd)
725{
726 struct pollfd pfd[2];
727 unsigned char buf[16384];
728 int n, wfd = fileno(stdin);
729 int lfd = fileno(stdout);
730 int plen;
731
732 plen = 2048;
733
734 /* Setup Network FD */
735 pfd[0].fd = nfd;
736 pfd[0].events = POLLIN;
737
738 /* Set up STDIN FD. */
739 pfd[1].fd = wfd;
740 pfd[1].events = POLLIN;
741
742 while (pfd[0].fd != -1) {
743 if (iflag)
744 sleep(iflag);
745
746 if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
747 close(nfd);
748 err(1, "Polling Error");
749 }
750
751 if (n == 0)
752 return;
753
754 if (pfd[0].revents & POLLIN) {
755 if ((n = read(nfd, buf, plen)) < 0)
756 return;
757 else if (n == 0) {
758 shutdown(nfd, SHUT_RD);
759 pfd[0].fd = -1;
760 pfd[0].events = 0;
761 } else {
762 if (tflag)
763 atelnet(nfd, buf, n);
764 if (atomicio(vwrite, lfd, buf, n) != n)
765 return;
766 }
767 }
768
769 if (!dflag && pfd[1].revents & POLLIN) {
770 if ((n = read(wfd, buf, plen)) < 0)
771 return;
772 else if (n == 0) {
773 shutdown(nfd, SHUT_WR);
774 pfd[1].fd = -1;
775 pfd[1].events = 0;
776 } else {
777 if (atomicio(vwrite, nfd, buf, n) != n)
778 return;
779 }
780 }
781 }
782}
783
784/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
785void
786atelnet(int nfd, unsigned char *buf, unsigned int size)
787{
788 unsigned char *p, *end;
789 unsigned char obuf[4];
790
791 if (size < 3)
792 return;
793 end = buf + size - 2;
794
795 for (p = buf; p < end; p++) {
796 if (*p != IAC)
797 continue;
798
799 obuf[0] = IAC;
800 p++;
801 if ((*p == WILL) || (*p == WONT))
802 obuf[1] = DONT;
803 else if ((*p == DO) || (*p == DONT))
804 obuf[1] = WONT;
805 else
806 continue;
807
808 p++;
809 obuf[2] = *p;
810 if (atomicio(vwrite, nfd, obuf, 3) != 3)
811 warn("Write Error!");
812 }
813}
814
815/*
816 * build_ports()
817 * Build an array of ports in portlist[], listing each port
818 * that we should try to connect to.
819 */
820void
821build_ports(char *p)
822{
823 const char *errstr;
824 char *n;
825 int hi, lo, cp;
826 int x = 0;
827
828 if ((n = strchr(p, '-')) != NULL) {
829 *n = '\0';
830 n++;
831
832 /* Make sure the ports are in order: lowest->highest. */
833 hi = strtonum(n, 1, PORT_MAX, &errstr);
834 if (errstr)
835 errx(1, "port number %s: %s", errstr, n);
836 lo = strtonum(p, 1, PORT_MAX, &errstr);
837 if (errstr)
838 errx(1, "port number %s: %s", errstr, p);
839
840 if (lo > hi) {
841 cp = hi;
842 hi = lo;
843 lo = cp;
844 }
845
846 /* Load ports sequentially. */
847 for (cp = lo; cp <= hi; cp++) {
848 portlist[x] = calloc(1, PORT_MAX_LEN);
849 if (portlist[x] == NULL)
850 err(1, NULL);
851 snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
852 x++;
853 }
854
855 /* Randomly swap ports. */
856 if (rflag) {
857 int y;
858 char *c;
859
860 for (x = 0; x <= (hi - lo); x++) {
861 y = (arc4random() & 0xFFFF) % (hi - lo);
862 c = portlist[x];
863 portlist[x] = portlist[y];
864 portlist[y] = c;
865 }
866 }
867 } else {
868 hi = strtonum(p, 1, PORT_MAX, &errstr);
869 if (errstr)
870 errx(1, "port number %s: %s", errstr, p);
871 portlist[0] = strdup(p);
872 if (portlist[0] == NULL)
873 err(1, NULL);
874 }
875}
876
877/*
878 * udptest()
879 * Do a few writes to see if the UDP port is there.
880 * Fails once PF state table is full.
881 */
882int
883udptest(int s)
884{
885 int i, ret;
886
887 for (i = 0; i <= 3; i++) {
888 if (write(s, "X", 1) == 1)
889 ret = 1;
890 else
891 ret = -1;
892 }
893 return (ret);
894}
895
896void
897set_common_sockopts(int s)
898{
899 int x = 1;
900
901 if (Sflag) {
902 if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
903 &x, sizeof(x)) == -1)
904 err(1, NULL);
905 }
906 if (Dflag) {
907 if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
908 &x, sizeof(x)) == -1)
909 err(1, NULL);
910 }
911 if (Tflag != -1) {
912 if (setsockopt(s, IPPROTO_IP, IP_TOS,
913 &Tflag, sizeof(Tflag)) == -1)
914 err(1, "set IP ToS");
915 }
916 if (Iflag) {
917 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
918 &Iflag, sizeof(Iflag)) == -1)
919 err(1, "set TCP receive buffer size");
920 }
921 if (Oflag) {
922 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
923 &Oflag, sizeof(Oflag)) == -1)
924 err(1, "set TCP send buffer size");
925 }
926}
927
928int
929map_tos(char *s, int *val)
930{
931 /* DiffServ Codepoints and other TOS mappings */
932 const struct toskeywords {
933 const char *keyword;
934 int val;
935 } *t, toskeywords[] = {
936 { "af11", IPTOS_DSCP_AF11 },
937 { "af12", IPTOS_DSCP_AF12 },
938 { "af13", IPTOS_DSCP_AF13 },
939 { "af21", IPTOS_DSCP_AF21 },
940 { "af22", IPTOS_DSCP_AF22 },
941 { "af23", IPTOS_DSCP_AF23 },
942 { "af31", IPTOS_DSCP_AF31 },
943 { "af32", IPTOS_DSCP_AF32 },
944 { "af33", IPTOS_DSCP_AF33 },
945 { "af41", IPTOS_DSCP_AF41 },
946 { "af42", IPTOS_DSCP_AF42 },
947 { "af43", IPTOS_DSCP_AF43 },
948 { "critical", IPTOS_PREC_CRITIC_ECP },
949 { "cs0", IPTOS_DSCP_CS0 },
950 { "cs1", IPTOS_DSCP_CS1 },
951 { "cs2", IPTOS_DSCP_CS2 },
952 { "cs3", IPTOS_DSCP_CS3 },
953 { "cs4", IPTOS_DSCP_CS4 },
954 { "cs5", IPTOS_DSCP_CS5 },
955 { "cs6", IPTOS_DSCP_CS6 },
956 { "cs7", IPTOS_DSCP_CS7 },
957 { "ef", IPTOS_DSCP_EF },
958 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL },
959 { "lowdelay", IPTOS_LOWDELAY },
960 { "netcontrol", IPTOS_PREC_NETCONTROL },
961 { "reliability", IPTOS_RELIABILITY },
962 { "throughput", IPTOS_THROUGHPUT },
963 { NULL, -1 },
964 };
965
966 for (t = toskeywords; t->keyword != NULL; t++) {
967 if (strcmp(s, t->keyword) == 0) {
968 *val = t->val;
969 return (1);
970 }
971 }
972
973 return (0);
974}
975
976void
977report_connect(const struct sockaddr *sa, socklen_t salen)
978{
979 char remote_host[NI_MAXHOST];
980 char remote_port[NI_MAXSERV];
981 int herr;
982 int flags = NI_NUMERICSERV;
983
984 if (nflag)
985 flags |= NI_NUMERICHOST;
986
987 if ((herr = getnameinfo(sa, salen,
988 remote_host, sizeof(remote_host),
989 remote_port, sizeof(remote_port),
990 flags)) != 0) {
991 if (herr == EAI_SYSTEM)
992 err(1, "getnameinfo");
993 else
994 errx(1, "getnameinfo: %s", gai_strerror(herr));
995 }
996
997 fprintf(stderr,
998 "Connection from %s %s "
999 "received!\n", remote_host, remote_port);
1000}
1001
1002void
1003help(void)
1004{
1005 usage(0);
1006 fprintf(stderr, "\tCommand Summary:\n\
1007 \t-4 Use IPv4\n\
1008 \t-6 Use IPv6\n\
1009 \t-D Enable the debug socket option\n\
1010 \t-d Detach from stdin\n\
1011 \t-h This help text\n\
1012 \t-I length TCP receive buffer length\n\
1013 \t-i secs\t Delay interval for lines sent, ports scanned\n\
1014 \t-k Keep inbound sockets open for multiple connects\n\
1015 \t-l Listen mode, for inbound connects\n\
1016 \t-n Suppress name/port resolutions\n\
1017 \t-O length TCP send buffer length\n\
1018 \t-P proxyuser\tUsername for proxy authentication\n\
1019 \t-p port\t Specify local port for remote connects\n\
1020 \t-r Randomize remote ports\n\
1021 \t-S Enable the TCP MD5 signature option\n\
1022 \t-s addr\t Local source address\n\
1023 \t-T toskeyword\tSet IP Type of Service\n\
1024 \t-t Answer TELNET negotiation\n\
1025 \t-U Use UNIX domain socket\n\
1026 \t-u UDP mode\n\
1027 \t-V rtable Specify alternate routing table\n\
1028 \t-v Verbose\n\
1029 \t-w secs\t Timeout for connects and final net reads\n\
1030 \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
1031 \t-x addr[:port]\tSpecify proxy address and port\n\
1032 \t-z Zero-I/O mode [used for scanning]\n\
1033 Port numbers can be individual or ranges: lo-hi [inclusive]\n");
1034 exit(1);
1035}
1036
1037void
1038usage(int ret)
1039{
1040 fprintf(stderr,
1041 "usage: nc [-46DdhklnrStUuvz] [-I length] [-i interval] [-O length]\n"
1042 "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n"
1043 "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n"
1044 "\t [-x proxy_address[:port]] [destination] [port]\n");
1045 if (ret)
1046 exit(1);
1047}
diff --git a/src/usr.bin/nc/socks.c b/src/usr.bin/nc/socks.c
deleted file mode 100644
index f8adda463a..0000000000
--- a/src/usr.bin/nc/socks.c
+++ /dev/null
@@ -1,340 +0,0 @@
1/* $OpenBSD: socks.c,v 1.20 2012/03/08 09:56:28 espie Exp $ */
2
3/*
4 * Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
5 * Copyright (c) 2004, 2005 Damien Miller. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <err.h>
34#include <errno.h>
35#include <netdb.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
40#include <resolv.h>
41#include <readpassphrase.h>
42#include "atomicio.h"
43
44#define SOCKS_PORT "1080"
45#define HTTP_PROXY_PORT "3128"
46#define HTTP_MAXHDRS 64
47#define SOCKS_V5 5
48#define SOCKS_V4 4
49#define SOCKS_NOAUTH 0
50#define SOCKS_NOMETHOD 0xff
51#define SOCKS_CONNECT 1
52#define SOCKS_IPV4 1
53#define SOCKS_DOMAIN 3
54#define SOCKS_IPV6 4
55
56int remote_connect(const char *, const char *, struct addrinfo);
57int socks_connect(const char *, const char *, struct addrinfo,
58 const char *, const char *, struct addrinfo, int,
59 const char *);
60
61static int
62decode_addrport(const char *h, const char *p, struct sockaddr *addr,
63 socklen_t addrlen, int v4only, int numeric)
64{
65 int r;
66 struct addrinfo hints, *res;
67
68 bzero(&hints, sizeof(hints));
69 hints.ai_family = v4only ? PF_INET : PF_UNSPEC;
70 hints.ai_flags = numeric ? AI_NUMERICHOST : 0;
71 hints.ai_socktype = SOCK_STREAM;
72 r = getaddrinfo(h, p, &hints, &res);
73 /* Don't fatal when attempting to convert a numeric address */
74 if (r != 0) {
75 if (!numeric) {
76 errx(1, "getaddrinfo(\"%.64s\", \"%.64s\"): %s", h, p,
77 gai_strerror(r));
78 }
79 return (-1);
80 }
81 if (addrlen < res->ai_addrlen) {
82 freeaddrinfo(res);
83 errx(1, "internal error: addrlen < res->ai_addrlen");
84 }
85 memcpy(addr, res->ai_addr, res->ai_addrlen);
86 freeaddrinfo(res);
87 return (0);
88}
89
90static int
91proxy_read_line(int fd, char *buf, size_t bufsz)
92{
93 size_t off;
94
95 for(off = 0;;) {
96 if (off >= bufsz)
97 errx(1, "proxy read too long");
98 if (atomicio(read, fd, buf + off, 1) != 1)
99 err(1, "proxy read");
100 /* Skip CR */
101 if (buf[off] == '\r')
102 continue;
103 if (buf[off] == '\n') {
104 buf[off] = '\0';
105 break;
106 }
107 off++;
108 }
109 return (off);
110}
111
112static const char *
113getproxypass(const char *proxyuser, const char *proxyhost)
114{
115 char prompt[512];
116 static char pw[256];
117
118 snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ",
119 proxyuser, proxyhost);
120 if (readpassphrase(prompt, pw, sizeof(pw), RPP_REQUIRE_TTY) == NULL)
121 errx(1, "Unable to read proxy passphrase");
122 return (pw);
123}
124
125int
126socks_connect(const char *host, const char *port,
127 struct addrinfo hints __attribute__ ((__unused__)),
128 const char *proxyhost, const char *proxyport, struct addrinfo proxyhints,
129 int socksv, const char *proxyuser)
130{
131 int proxyfd, r, authretry = 0;
132 size_t hlen, wlen;
133 unsigned char buf[1024];
134 size_t cnt;
135 struct sockaddr_storage addr;
136 struct sockaddr_in *in4 = (struct sockaddr_in *)&addr;
137 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr;
138 in_port_t serverport;
139 const char *proxypass = NULL;
140
141 if (proxyport == NULL)
142 proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT;
143
144 /* Abuse API to lookup port */
145 if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr,
146 sizeof(addr), 1, 1) == -1)
147 errx(1, "unknown port \"%.64s\"", port);
148 serverport = in4->sin_port;
149
150 again:
151 if (authretry++ > 3)
152 errx(1, "Too many authentication failures");
153
154 proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
155
156 if (proxyfd < 0)
157 return (-1);
158
159 if (socksv == 5) {
160 if (decode_addrport(host, port, (struct sockaddr *)&addr,
161 sizeof(addr), 0, 1) == -1)
162 addr.ss_family = 0; /* used in switch below */
163
164 /* Version 5, one method: no authentication */
165 buf[0] = SOCKS_V5;
166 buf[1] = 1;
167 buf[2] = SOCKS_NOAUTH;
168 cnt = atomicio(vwrite, proxyfd, buf, 3);
169 if (cnt != 3)
170 err(1, "write failed (%zu/3)", cnt);
171
172 cnt = atomicio(read, proxyfd, buf, 2);
173 if (cnt != 2)
174 err(1, "read failed (%zu/3)", cnt);
175
176 if (buf[1] == SOCKS_NOMETHOD)
177 errx(1, "authentication method negotiation failed");
178
179 switch (addr.ss_family) {
180 case 0:
181 /* Version 5, connect: domain name */
182
183 /* Max domain name length is 255 bytes */
184 hlen = strlen(host);
185 if (hlen > 255)
186 errx(1, "host name too long for SOCKS5");
187 buf[0] = SOCKS_V5;
188 buf[1] = SOCKS_CONNECT;
189 buf[2] = 0;
190 buf[3] = SOCKS_DOMAIN;
191 buf[4] = hlen;
192 memcpy(buf + 5, host, hlen);
193 memcpy(buf + 5 + hlen, &serverport, sizeof serverport);
194 wlen = 7 + hlen;
195 break;
196 case AF_INET:
197 /* Version 5, connect: IPv4 address */
198 buf[0] = SOCKS_V5;
199 buf[1] = SOCKS_CONNECT;
200 buf[2] = 0;
201 buf[3] = SOCKS_IPV4;
202 memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
203 memcpy(buf + 8, &in4->sin_port, sizeof in4->sin_port);
204 wlen = 10;
205 break;
206 case AF_INET6:
207 /* Version 5, connect: IPv6 address */
208 buf[0] = SOCKS_V5;
209 buf[1] = SOCKS_CONNECT;
210 buf[2] = 0;
211 buf[3] = SOCKS_IPV6;
212 memcpy(buf + 4, &in6->sin6_addr, sizeof in6->sin6_addr);
213 memcpy(buf + 20, &in6->sin6_port,
214 sizeof in6->sin6_port);
215 wlen = 22;
216 break;
217 default:
218 errx(1, "internal error: silly AF");
219 }
220
221 cnt = atomicio(vwrite, proxyfd, buf, wlen);
222 if (cnt != wlen)
223 err(1, "write failed (%zu/%zu)", cnt, wlen);
224
225 cnt = atomicio(read, proxyfd, buf, 4);
226 if (cnt != 4)
227 err(1, "read failed (%zu/4)", cnt);
228 if (buf[1] != 0)
229 errx(1, "connection failed, SOCKS error %d", buf[1]);
230 switch (buf[3]) {
231 case SOCKS_IPV4:
232 cnt = atomicio(read, proxyfd, buf + 4, 6);
233 if (cnt != 6)
234 err(1, "read failed (%zu/6)", cnt);
235 break;
236 case SOCKS_IPV6:
237 cnt = atomicio(read, proxyfd, buf + 4, 18);
238 if (cnt != 18)
239 err(1, "read failed (%zu/18)", cnt);
240 break;
241 default:
242 errx(1, "connection failed, unsupported address type");
243 }
244 } else if (socksv == 4) {
245 /* This will exit on lookup failure */
246 decode_addrport(host, port, (struct sockaddr *)&addr,
247 sizeof(addr), 1, 0);
248
249 /* Version 4 */
250 buf[0] = SOCKS_V4;
251 buf[1] = SOCKS_CONNECT; /* connect */
252 memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port);
253 memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
254 buf[8] = 0; /* empty username */
255 wlen = 9;
256
257 cnt = atomicio(vwrite, proxyfd, buf, wlen);
258 if (cnt != wlen)
259 err(1, "write failed (%zu/%zu)", cnt, wlen);
260
261 cnt = atomicio(read, proxyfd, buf, 8);
262 if (cnt != 8)
263 err(1, "read failed (%zu/8)", cnt);
264 if (buf[1] != 90)
265 errx(1, "connection failed, SOCKS error %d", buf[1]);
266 } else if (socksv == -1) {
267 /* HTTP proxy CONNECT */
268
269 /* Disallow bad chars in hostname */
270 if (strcspn(host, "\r\n\t []:") != strlen(host))
271 errx(1, "Invalid hostname");
272
273 /* Try to be sane about numeric IPv6 addresses */
274 if (strchr(host, ':') != NULL) {
275 r = snprintf(buf, sizeof(buf),
276 "CONNECT [%s]:%d HTTP/1.0\r\n",
277 host, ntohs(serverport));
278 } else {
279 r = snprintf(buf, sizeof(buf),
280 "CONNECT %s:%d HTTP/1.0\r\n",
281 host, ntohs(serverport));
282 }
283 if (r == -1 || (size_t)r >= sizeof(buf))
284 errx(1, "hostname too long");
285 r = strlen(buf);
286
287 cnt = atomicio(vwrite, proxyfd, buf, r);
288 if (cnt != r)
289 err(1, "write failed (%zu/%d)", cnt, r);
290
291 if (authretry > 1) {
292 char resp[1024];
293
294 proxypass = getproxypass(proxyuser, proxyhost);
295 r = snprintf(buf, sizeof(buf), "%s:%s",
296 proxyuser, proxypass);
297 if (r == -1 || (size_t)r >= sizeof(buf) ||
298 b64_ntop(buf, strlen(buf), resp,
299 sizeof(resp)) == -1)
300 errx(1, "Proxy username/password too long");
301 r = snprintf(buf, sizeof(buf), "Proxy-Authorization: "
302 "Basic %s\r\n", resp);
303 if (r == -1 || (size_t)r >= sizeof(buf))
304 errx(1, "Proxy auth response too long");
305 r = strlen(buf);
306 if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != r)
307 err(1, "write failed (%zu/%d)", cnt, r);
308 }
309
310 /* Terminate headers */
311 if ((r = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2)
312 err(1, "write failed (2/%d)", r);
313
314 /* Read status reply */
315 proxy_read_line(proxyfd, buf, sizeof(buf));
316 if (proxyuser != NULL &&
317 strncmp(buf, "HTTP/1.0 407 ", 12) == 0) {
318 if (authretry > 1) {
319 fprintf(stderr, "Proxy authentication "
320 "failed\n");
321 }
322 close(proxyfd);
323 goto again;
324 } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0 &&
325 strncmp(buf, "HTTP/1.1 200 ", 12) != 0)
326 errx(1, "Proxy error: \"%s\"", buf);
327
328 /* Headers continue until we hit an empty line */
329 for (r = 0; r < HTTP_MAXHDRS; r++) {
330 proxy_read_line(proxyfd, buf, sizeof(buf));
331 if (*buf == '\0')
332 break;
333 }
334 if (*buf != '\0')
335 errx(1, "Too many proxy headers received");
336 } else
337 errx(1, "Unknown proxy protocol %d", socksv);
338
339 return (proxyfd);
340}