summaryrefslogtreecommitdiff
path: root/src/usr.bin/nc/netcat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr.bin/nc/netcat.c')
-rw-r--r--src/usr.bin/nc/netcat.c872
1 files changed, 0 insertions, 872 deletions
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
deleted file mode 100644
index 48b2b673ba..0000000000
--- a/src/usr.bin/nc/netcat.c
+++ /dev/null
@@ -1,872 +0,0 @@
1/* $OpenBSD: netcat.c,v 1.91 2008/05/09 09:00:11 markus 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
66/* Command Line Options */
67int dflag; /* detached, no stdin */
68unsigned int iflag; /* Interval Flag */
69int jflag; /* use jumbo frames if we can */
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 */
87
88int timeout = -1;
89int family = AF_UNSPEC;
90char *portlist[PORT_MAX+1];
91
92void atelnet(int, unsigned char *, unsigned int);
93void build_ports(char *);
94void help(void);
95int local_listen(char *, char *, struct addrinfo);
96void readwrite(int);
97int remote_connect(const char *, const char *, struct addrinfo);
98int socks_connect(const char *, const char *, struct addrinfo,
99 const char *, const char *, struct addrinfo, int, const char *);
100int udptest(int);
101int unix_connect(char *);
102int unix_listen(char *);
103void set_common_sockopts(int);
104int parse_iptos(char *);
105void usage(int);
106
107int
108main(int argc, char *argv[])
109{
110 int ch, s, ret, socksv;
111 char *host, *uport;
112 struct addrinfo hints;
113 struct servent *sv;
114 socklen_t len;
115 struct sockaddr_storage cliaddr;
116 char *proxy;
117 const char *errstr, *proxyhost = "", *proxyport = NULL;
118 struct addrinfo proxyhints;
119
120 ret = 1;
121 s = 0;
122 socksv = 5;
123 host = NULL;
124 uport = NULL;
125 sv = NULL;
126
127 while ((ch = getopt(argc, argv,
128 "46DdhI:i:jklnO:P:p:rSs:tT:Uuvw:X:x:z")) != -1) {
129 switch (ch) {
130 case '4':
131 family = AF_INET;
132 break;
133 case '6':
134 family = AF_INET6;
135 break;
136 case 'U':
137 family = AF_UNIX;
138 break;
139 case 'X':
140 if (strcasecmp(optarg, "connect") == 0)
141 socksv = -1; /* HTTP proxy CONNECT */
142 else if (strcmp(optarg, "4") == 0)
143 socksv = 4; /* SOCKS v.4 */
144 else if (strcmp(optarg, "5") == 0)
145 socksv = 5; /* SOCKS v.5 */
146 else
147 errx(1, "unsupported proxy protocol");
148 break;
149 case 'd':
150 dflag = 1;
151 break;
152 case 'h':
153 help();
154 break;
155 case 'i':
156 iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
157 if (errstr)
158 errx(1, "interval %s: %s", errstr, optarg);
159 break;
160 case 'j':
161 jflag = 1;
162 break;
163 case 'k':
164 kflag = 1;
165 break;
166 case 'l':
167 lflag = 1;
168 break;
169 case 'n':
170 nflag = 1;
171 break;
172 case 'P':
173 Pflag = optarg;
174 break;
175 case 'p':
176 pflag = optarg;
177 break;
178 case 'r':
179 rflag = 1;
180 break;
181 case 's':
182 sflag = optarg;
183 break;
184 case 't':
185 tflag = 1;
186 break;
187 case 'u':
188 uflag = 1;
189 break;
190 case 'v':
191 vflag = 1;
192 break;
193 case 'w':
194 timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
195 if (errstr)
196 errx(1, "timeout %s: %s", errstr, optarg);
197 timeout *= 1000;
198 break;
199 case 'x':
200 xflag = 1;
201 if ((proxy = strdup(optarg)) == NULL)
202 err(1, NULL);
203 break;
204 case 'z':
205 zflag = 1;
206 break;
207 case 'D':
208 Dflag = 1;
209 break;
210 case 'I':
211 Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
212 if (errstr != NULL)
213 errx(1, "TCP receive window %s: %s",
214 errstr, optarg);
215 break;
216 case 'O':
217 Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
218 if (errstr != NULL)
219 errx(1, "TCP send window %s: %s",
220 errstr, optarg);
221 break;
222 case 'S':
223 Sflag = 1;
224 break;
225 case 'T':
226 Tflag = parse_iptos(optarg);
227 break;
228 default:
229 usage(1);
230 }
231 }
232 argc -= optind;
233 argv += optind;
234
235 /* Cruft to make sure options are clean, and used properly. */
236 if (argv[0] && !argv[1] && family == AF_UNIX) {
237 if (uflag)
238 errx(1, "cannot use -u and -U");
239 host = argv[0];
240 uport = NULL;
241 } else if (argv[0] && !argv[1]) {
242 if (!lflag)
243 usage(1);
244 uport = argv[0];
245 host = NULL;
246 } else if (argv[0] && argv[1]) {
247 host = argv[0];
248 uport = argv[1];
249 } else
250 usage(1);
251
252 if (lflag && sflag)
253 errx(1, "cannot use -s and -l");
254 if (lflag && pflag)
255 errx(1, "cannot use -p and -l");
256 if (lflag && zflag)
257 errx(1, "cannot use -z and -l");
258 if (!lflag && kflag)
259 errx(1, "must use -l with -k");
260
261 /* Initialize addrinfo structure. */
262 if (family != AF_UNIX) {
263 memset(&hints, 0, sizeof(struct addrinfo));
264 hints.ai_family = family;
265 hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
266 hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
267 if (nflag)
268 hints.ai_flags |= AI_NUMERICHOST;
269 }
270
271 if (xflag) {
272 if (uflag)
273 errx(1, "no proxy support for UDP mode");
274
275 if (lflag)
276 errx(1, "no proxy support for listen");
277
278 if (family == AF_UNIX)
279 errx(1, "no proxy support for unix sockets");
280
281 /* XXX IPv6 transport to proxy would probably work */
282 if (family == AF_INET6)
283 errx(1, "no proxy support for IPv6");
284
285 if (sflag)
286 errx(1, "no proxy support for local source address");
287
288 proxyhost = strsep(&proxy, ":");
289 proxyport = proxy;
290
291 memset(&proxyhints, 0, sizeof(struct addrinfo));
292 proxyhints.ai_family = family;
293 proxyhints.ai_socktype = SOCK_STREAM;
294 proxyhints.ai_protocol = IPPROTO_TCP;
295 if (nflag)
296 proxyhints.ai_flags |= AI_NUMERICHOST;
297 }
298
299 if (lflag) {
300 int connfd;
301 ret = 0;
302
303 if (family == AF_UNIX)
304 s = unix_listen(host);
305
306 /* Allow only one connection at a time, but stay alive. */
307 for (;;) {
308 if (family != AF_UNIX)
309 s = local_listen(host, uport, hints);
310 if (s < 0)
311 err(1, NULL);
312 /*
313 * For UDP, we will use recvfrom() initially
314 * to wait for a caller, then use the regular
315 * functions to talk to the caller.
316 */
317 if (uflag) {
318 int rv, plen;
319 char buf[8192];
320 struct sockaddr_storage z;
321
322 len = sizeof(z);
323 plen = jflag ? 8192 : 1024;
324 rv = recvfrom(s, buf, plen, MSG_PEEK,
325 (struct sockaddr *)&z, &len);
326 if (rv < 0)
327 err(1, "recvfrom");
328
329 rv = connect(s, (struct sockaddr *)&z, len);
330 if (rv < 0)
331 err(1, "connect");
332
333 connfd = s;
334 } else {
335 len = sizeof(cliaddr);
336 connfd = accept(s, (struct sockaddr *)&cliaddr,
337 &len);
338 }
339
340 readwrite(connfd);
341 close(connfd);
342 if (family != AF_UNIX)
343 close(s);
344
345 if (!kflag)
346 break;
347 }
348 } else if (family == AF_UNIX) {
349 ret = 0;
350
351 if ((s = unix_connect(host)) > 0 && !zflag) {
352 readwrite(s);
353 close(s);
354 } else
355 ret = 1;
356
357 exit(ret);
358
359 } else {
360 int i = 0;
361
362 /* Construct the portlist[] array. */
363 build_ports(uport);
364
365 /* Cycle through portlist, connecting to each port. */
366 for (i = 0; portlist[i] != NULL; i++) {
367 if (s)
368 close(s);
369
370 if (xflag)
371 s = socks_connect(host, portlist[i], hints,
372 proxyhost, proxyport, proxyhints, socksv,
373 Pflag);
374 else
375 s = remote_connect(host, portlist[i], hints);
376
377 if (s < 0)
378 continue;
379
380 ret = 0;
381 if (vflag || zflag) {
382 /* For UDP, make sure we are connected. */
383 if (uflag) {
384 if (udptest(s) == -1) {
385 ret = 1;
386 continue;
387 }
388 }
389
390 /* Don't look up port if -n. */
391 if (nflag)
392 sv = NULL;
393 else {
394 sv = getservbyport(
395 ntohs(atoi(portlist[i])),
396 uflag ? "udp" : "tcp");
397 }
398
399 printf("Connection to %s %s port [%s/%s] succeeded!\n",
400 host, portlist[i], uflag ? "udp" : "tcp",
401 sv ? sv->s_name : "*");
402 }
403 if (!zflag)
404 readwrite(s);
405 }
406 }
407
408 if (s)
409 close(s);
410
411 exit(ret);
412}
413
414/*
415 * unix_connect()
416 * Returns a socket connected to a local unix socket. Returns -1 on failure.
417 */
418int
419unix_connect(char *path)
420{
421 struct sockaddr_un sun;
422 int s;
423
424 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
425 return (-1);
426 (void)fcntl(s, F_SETFD, 1);
427
428 memset(&sun, 0, sizeof(struct sockaddr_un));
429 sun.sun_family = AF_UNIX;
430
431 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
432 sizeof(sun.sun_path)) {
433 close(s);
434 errno = ENAMETOOLONG;
435 return (-1);
436 }
437 if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
438 close(s);
439 return (-1);
440 }
441 return (s);
442
443}
444
445/*
446 * unix_listen()
447 * Create a unix domain socket, and listen on it.
448 */
449int
450unix_listen(char *path)
451{
452 struct sockaddr_un sun;
453 int s;
454
455 /* Create unix domain socket. */
456 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
457 return (-1);
458
459 memset(&sun, 0, sizeof(struct sockaddr_un));
460 sun.sun_family = AF_UNIX;
461
462 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
463 sizeof(sun.sun_path)) {
464 close(s);
465 errno = ENAMETOOLONG;
466 return (-1);
467 }
468
469 if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
470 close(s);
471 return (-1);
472 }
473
474 if (listen(s, 5) < 0) {
475 close(s);
476 return (-1);
477 }
478 return (s);
479}
480
481/*
482 * remote_connect()
483 * Returns a socket connected to a remote host. Properly binds to a local
484 * port or source address if needed. Returns -1 on failure.
485 */
486int
487remote_connect(const char *host, const char *port, struct addrinfo hints)
488{
489 struct addrinfo *res, *res0;
490 int s, error, on = 1;
491
492 if ((error = getaddrinfo(host, port, &hints, &res)))
493 errx(1, "getaddrinfo: %s", gai_strerror(error));
494
495 res0 = res;
496 do {
497 if ((s = socket(res0->ai_family, res0->ai_socktype,
498 res0->ai_protocol)) < 0)
499 continue;
500
501 /* Bind to a local port or source address if specified. */
502 if (sflag || pflag) {
503 struct addrinfo ahints, *ares;
504
505 /* try SO_BINDANY, but don't insist */
506 setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
507 memset(&ahints, 0, sizeof(struct addrinfo));
508 ahints.ai_family = res0->ai_family;
509 ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
510 ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
511 ahints.ai_flags = AI_PASSIVE;
512 if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
513 errx(1, "getaddrinfo: %s", gai_strerror(error));
514
515 if (bind(s, (struct sockaddr *)ares->ai_addr,
516 ares->ai_addrlen) < 0)
517 errx(1, "bind failed: %s", strerror(errno));
518 freeaddrinfo(ares);
519 }
520
521 set_common_sockopts(s);
522
523 if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
524 break;
525 else if (vflag)
526 warn("connect to %s port %s (%s) failed", host, port,
527 uflag ? "udp" : "tcp");
528
529 close(s);
530 s = -1;
531 } while ((res0 = res0->ai_next) != NULL);
532
533 freeaddrinfo(res);
534
535 return (s);
536}
537
538/*
539 * local_listen()
540 * Returns a socket listening on a local port, binds to specified source
541 * address. Returns -1 on failure.
542 */
543int
544local_listen(char *host, char *port, struct addrinfo hints)
545{
546 struct addrinfo *res, *res0;
547 int s, ret, x = 1;
548 int error;
549
550 /* Allow nodename to be null. */
551 hints.ai_flags |= AI_PASSIVE;
552
553 /*
554 * In the case of binding to a wildcard address
555 * default to binding to an ipv4 address.
556 */
557 if (host == NULL && hints.ai_family == AF_UNSPEC)
558 hints.ai_family = AF_INET;
559
560 if ((error = getaddrinfo(host, port, &hints, &res)))
561 errx(1, "getaddrinfo: %s", gai_strerror(error));
562
563 res0 = res;
564 do {
565 if ((s = socket(res0->ai_family, res0->ai_socktype,
566 res0->ai_protocol)) < 0)
567 continue;
568
569 ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
570 if (ret == -1)
571 err(1, NULL);
572
573 set_common_sockopts(s);
574
575 if (bind(s, (struct sockaddr *)res0->ai_addr,
576 res0->ai_addrlen) == 0)
577 break;
578
579 close(s);
580 s = -1;
581 } while ((res0 = res0->ai_next) != NULL);
582
583 if (!uflag && s != -1) {
584 if (listen(s, 1) < 0)
585 err(1, "listen");
586 }
587
588 freeaddrinfo(res);
589
590 return (s);
591}
592
593/*
594 * readwrite()
595 * Loop that polls on the network file descriptor and stdin.
596 */
597void
598readwrite(int nfd)
599{
600 struct pollfd pfd[2];
601 unsigned char buf[8192];
602 int n, wfd = fileno(stdin);
603 int lfd = fileno(stdout);
604 int plen;
605
606 plen = jflag ? 8192 : 1024;
607
608 /* Setup Network FD */
609 pfd[0].fd = nfd;
610 pfd[0].events = POLLIN;
611
612 /* Set up STDIN FD. */
613 pfd[1].fd = wfd;
614 pfd[1].events = POLLIN;
615
616 while (pfd[0].fd != -1) {
617 if (iflag)
618 sleep(iflag);
619
620 if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
621 close(nfd);
622 err(1, "Polling Error");
623 }
624
625 if (n == 0)
626 return;
627
628 if (pfd[0].revents & POLLIN) {
629 if ((n = read(nfd, buf, plen)) < 0)
630 return;
631 else if (n == 0) {
632 shutdown(nfd, SHUT_RD);
633 pfd[0].fd = -1;
634 pfd[0].events = 0;
635 } else {
636 if (tflag)
637 atelnet(nfd, buf, n);
638 if (atomicio(vwrite, lfd, buf, n) != n)
639 return;
640 }
641 }
642
643 if (!dflag && pfd[1].revents & POLLIN) {
644 if ((n = read(wfd, buf, plen)) < 0)
645 return;
646 else if (n == 0) {
647 shutdown(nfd, SHUT_WR);
648 pfd[1].fd = -1;
649 pfd[1].events = 0;
650 } else {
651 if (atomicio(vwrite, nfd, buf, n) != n)
652 return;
653 }
654 }
655 }
656}
657
658/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
659void
660atelnet(int nfd, unsigned char *buf, unsigned int size)
661{
662 unsigned char *p, *end;
663 unsigned char obuf[4];
664
665 end = buf + size;
666 obuf[0] = '\0';
667
668 for (p = buf; p < end; p++) {
669 if (*p != IAC)
670 break;
671
672 obuf[0] = IAC;
673 p++;
674 if ((*p == WILL) || (*p == WONT))
675 obuf[1] = DONT;
676 if ((*p == DO) || (*p == DONT))
677 obuf[1] = WONT;
678 if (obuf) {
679 p++;
680 obuf[2] = *p;
681 obuf[3] = '\0';
682 if (atomicio(vwrite, nfd, obuf, 3) != 3)
683 warn("Write Error!");
684 obuf[0] = '\0';
685 }
686 }
687}
688
689/*
690 * build_ports()
691 * Build an array or ports in portlist[], listing each port
692 * that we should try to connect to.
693 */
694void
695build_ports(char *p)
696{
697 const char *errstr;
698 char *n;
699 int hi, lo, cp;
700 int x = 0;
701
702 if ((n = strchr(p, '-')) != NULL) {
703 if (lflag)
704 errx(1, "Cannot use -l with multiple ports!");
705
706 *n = '\0';
707 n++;
708
709 /* Make sure the ports are in order: lowest->highest. */
710 hi = strtonum(n, 1, PORT_MAX, &errstr);
711 if (errstr)
712 errx(1, "port number %s: %s", errstr, n);
713 lo = strtonum(p, 1, PORT_MAX, &errstr);
714 if (errstr)
715 errx(1, "port number %s: %s", errstr, p);
716
717 if (lo > hi) {
718 cp = hi;
719 hi = lo;
720 lo = cp;
721 }
722
723 /* Load ports sequentially. */
724 for (cp = lo; cp <= hi; cp++) {
725 portlist[x] = calloc(1, PORT_MAX_LEN);
726 if (portlist[x] == NULL)
727 err(1, NULL);
728 snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
729 x++;
730 }
731
732 /* Randomly swap ports. */
733 if (rflag) {
734 int y;
735 char *c;
736
737 for (x = 0; x <= (hi - lo); x++) {
738 y = (arc4random() & 0xFFFF) % (hi - lo);
739 c = portlist[x];
740 portlist[x] = portlist[y];
741 portlist[y] = c;
742 }
743 }
744 } else {
745 hi = strtonum(p, 1, PORT_MAX, &errstr);
746 if (errstr)
747 errx(1, "port number %s: %s", errstr, p);
748 portlist[0] = calloc(1, PORT_MAX_LEN);
749 if (portlist[0] == NULL)
750 err(1, NULL);
751 portlist[0] = p;
752 }
753}
754
755/*
756 * udptest()
757 * Do a few writes to see if the UDP port is there.
758 * XXX - Better way of doing this? Doesn't work for IPv6.
759 * Also fails after around 100 ports checked.
760 */
761int
762udptest(int s)
763{
764 int i, ret;
765
766 for (i = 0; i <= 3; i++) {
767 if (write(s, "X", 1) == 1)
768 ret = 1;
769 else
770 ret = -1;
771 }
772 return (ret);
773}
774
775void
776set_common_sockopts(int s)
777{
778 int x = 1;
779
780 if (Sflag) {
781 if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
782 &x, sizeof(x)) == -1)
783 err(1, NULL);
784 }
785 if (Dflag) {
786 if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
787 &x, sizeof(x)) == -1)
788 err(1, NULL);
789 }
790 if (jflag) {
791 if (setsockopt(s, SOL_SOCKET, SO_JUMBO,
792 &x, sizeof(x)) == -1)
793 err(1, NULL);
794 }
795 if (Tflag != -1) {
796 if (setsockopt(s, IPPROTO_IP, IP_TOS,
797 &Tflag, sizeof(Tflag)) == -1)
798 err(1, "set IP ToS");
799 }
800 if (Iflag) {
801 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
802 &Iflag, sizeof(Iflag)) == -1)
803 err(1, "set TCP receive buffer size");
804 }
805 if (Oflag) {
806 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
807 &Oflag, sizeof(Oflag)) == -1)
808 err(1, "set TCP send buffer size");
809 }
810}
811
812int
813parse_iptos(char *s)
814{
815 int tos = -1;
816
817 if (strcmp(s, "lowdelay") == 0)
818 return (IPTOS_LOWDELAY);
819 if (strcmp(s, "throughput") == 0)
820 return (IPTOS_THROUGHPUT);
821 if (strcmp(s, "reliability") == 0)
822 return (IPTOS_RELIABILITY);
823
824 if (sscanf(s, "0x%x", &tos) != 1 || tos < 0 || tos > 0xff)
825 errx(1, "invalid IP Type of Service");
826 return (tos);
827}
828
829void
830help(void)
831{
832 usage(0);
833 fprintf(stderr, "\tCommand Summary:\n\
834 \t-4 Use IPv4\n\
835 \t-6 Use IPv6\n\
836 \t-D Enable the debug socket option\n\
837 \t-d Detach from stdin\n\
838 \t-h This help text\n\
839 \t-I length TCP receive buffer length\n\
840 \t-i secs\t Delay interval for lines sent, ports scanned\n\
841 \t-k Keep inbound sockets open for multiple connects\n\
842 \t-l Listen mode, for inbound connects\n\
843 \t-n Suppress name/port resolutions\n\
844 \t-O length TCP send buffer length\n\
845 \t-P proxyuser\tUsername for proxy authentication\n\
846 \t-p port\t Specify local port for remote connects\n\
847 \t-r Randomize remote ports\n\
848 \t-S Enable the TCP MD5 signature option\n\
849 \t-s addr\t Local source address\n\
850 \t-T ToS\t Set IP Type of Service\n\
851 \t-t Answer TELNET negotiation\n\
852 \t-U Use UNIX domain socket\n\
853 \t-u UDP mode\n\
854 \t-v Verbose\n\
855 \t-w secs\t Timeout for connects and final net reads\n\
856 \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
857 \t-x addr[:port]\tSpecify proxy address and port\n\
858 \t-z Zero-I/O mode [used for scanning]\n\
859 Port numbers can be individual or ranges: lo-hi [inclusive]\n");
860 exit(1);
861}
862
863void
864usage(int ret)
865{
866 fprintf(stderr, "usage: nc [-46DdhklnrStUuvz] [-I receive_buffer_len] [-i interval]\n");
867 fprintf(stderr, "\t [-O send_buffer_len] [-P proxy_username] [-p source_port]\n");
868 fprintf(stderr, "\t [-s source_ip_address] [-T ToS] [-w timeout] [-X proxy_protocol]\n");
869 fprintf(stderr, "\t [-x proxy_address[:port]] [hostname] [port[s]]\n");
870 if (ret)
871 exit(1);
872}