1 /* $OpenBSD: netcat.c,v 1.89 2007/02/20 14:11:17 jmc 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 /*
35 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
36 * Use is subject to license terms.
37 */
38
39 /*
40 * Portions Copyright 2008 Erik Trauschke
41 * Copyright 2024 Oxide Computer Company
42 * Copyright 2024 MNX Cloud, Inc.
43 */
44
45 #include <sys/types.h>
46 #include <sys/socket.h>
47 #include <sys/time.h>
48 #include <sys/un.h>
49
50 #include <netinet/in.h>
51 #include <netinet/in_systm.h>
52 #include <netinet/tcp.h>
53 #include <netinet/ip.h>
54 #include <arpa/telnet.h>
55
56 #include <err.h>
57 #include <errno.h>
58 #include <netdb.h>
59 #include <poll.h>
60 #include <stdarg.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <unistd.h>
65 #include <fcntl.h>
66 #include <limits.h>
67 #include <signal.h>
68
69 #include "atomicio.h"
70
71 #ifndef SUN_LEN
72 #define SUN_LEN(su) \
73 (sizeof (*(su)) - sizeof ((su)->sun_path) + strlen((su)->sun_path))
74 #endif
75
76 #define PORT_MIN 1
77 #define PORT_MAX 65535
78 #define PORT_MAX_LEN 6
79 #define PLIST_SZ 32 /* initial capacity of the portlist */
80
81 /* Command Line Options */
82 int dflag; /* detached, no stdin */
83 unsigned int iflag; /* Interval Flag */
84 int kflag; /* More than one connect */
85 int lflag; /* Bind to local port */
86 int nflag; /* Don't do name lookup */
87 const char *Pflag; /* Proxy username */
88 char *pflag; /* Localport flag */
89 int rflag; /* Random ports flag */
90 const char *sflag; /* Source Address */
91 int tflag; /* Telnet Emulation */
92 int uflag; /* UDP - Default to TCP */
93 int vflag; /* Verbosity */
94 int xflag; /* Socks proxy */
95 int Xflag; /* indicator of Socks version set */
96 int zflag; /* Port Scan Flag */
97 int Bflag; /* Use IP_SEC_OPT to bypass policy */
98 int Dflag; /* sodebug */
99 int Sflag; /* TCP MD5 signature option */
100 int Tflag = -1; /* IP Type of Service */
101
102 int timeout = -1;
103 int family = AF_UNSPEC;
104 int ttl = -1;
105 int minttl = -1;
106
107 /*
108 * portlist structure
109 * Used to store a list of ports given by the user and maintaining
110 * information about the number of ports stored.
111 */
112 struct {
113 uint16_t *list; /* list containing the ports */
114 uint_t listsize; /* capacity of the list (number of entries) */
115 uint_t numports; /* number of ports in the list */
116 } ports;
117
118 void atelnet(int, unsigned char *, unsigned int);
119 void build_ports(char *);
120 void help(void);
121 int local_listen(const char *, const char *, struct addrinfo);
122 void readwrite(int);
123 int remote_connect(const char *, const char *, struct addrinfo);
124 int socks_connect(const char *, const char *,
125 const char *, const char *, struct addrinfo, int, const char *);
126 int udptest(int);
127 int unix_connect(const char *);
128 int unix_listen(const char *);
129 void set_common_sockopts(int, int);
130 int parse_iptos(const char *);
131 void usage(int);
132 const char *print_addr(char *, size_t, struct sockaddr *, int, int);
133
134 int
main(int argc,char * argv[])135 main(int argc, char *argv[])
136 {
137 int ch, s, ret, socksv;
138 char *host, *uport, *proxy;
139 struct addrinfo hints;
140 struct servent *sv;
141 socklen_t len;
142 struct sockaddr_storage cliaddr;
143 const char *errstr, *proxyhost = "", *proxyport = NULL;
144 struct addrinfo proxyhints;
145 char port[PORT_MAX_LEN];
146
147 ret = 1;
148 s = -1;
149 socksv = 5;
150 host = NULL;
151 uport = NULL;
152 sv = NULL;
153
154 while ((ch = getopt(argc, argv,
155 "46BDdhi:klm:M:nP:p:rs:ST:tUuvw:X:x:z")) != -1) {
156 switch (ch) {
157 case '4':
158 family = AF_INET;
159 break;
160 case '6':
161 family = AF_INET6;
162 break;
163 case 'U':
164 family = AF_UNIX;
165 break;
166 case 'B':
167 Bflag = 1;
168 break;
169 case 'X':
170 Xflag = 1;
171 if (strcasecmp(optarg, "connect") == 0)
172 socksv = -1; /* HTTP proxy CONNECT */
173 else if (strcmp(optarg, "4") == 0)
174 socksv = 4; /* SOCKS v.4 */
175 else if (strcmp(optarg, "5") == 0)
176 socksv = 5; /* SOCKS v.5 */
177 else
178 errx(1, "unsupported proxy protocol");
179 break;
180 case 'd':
181 dflag = 1;
182 break;
183 case 'h':
184 help();
185 break;
186 case 'i':
187 iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
188 if (errstr)
189 errx(1, "interval %s: %s", errstr, optarg);
190 break;
191 case 'k':
192 kflag = 1;
193 break;
194 case 'M':
195 ttl = strtonumx(optarg, 1, 255, &errstr, 0);
196 if (errstr != NULL) {
197 errx(1, "ttl is %s: %s, valid values are "
198 "between 1 and 255", errstr, optarg);
199 }
200 break;
201 case 'm':
202 minttl = strtonumx(optarg, 0, 255, &errstr, 0);
203 if (errstr != NULL) {
204 errx(1, "minimum ttl is %s: %s, valid values "
205 "are between 0 and 255", errstr, optarg);
206 }
207 break;
208 case 'l':
209 lflag = 1;
210 break;
211 case 'n':
212 nflag = 1;
213 break;
214 case 'P':
215 Pflag = optarg;
216 break;
217 case 'p':
218 pflag = optarg;
219 break;
220 case 'r':
221 rflag = 1;
222 break;
223 case 's':
224 sflag = optarg;
225 break;
226 case 't':
227 tflag = 1;
228 break;
229 case 'u':
230 uflag = 1;
231 break;
232 case 'v':
233 vflag = 1;
234 break;
235 case 'w':
236 timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
237 if (errstr)
238 errx(1, "timeout %s: %s", errstr, optarg);
239 timeout *= 1000;
240 break;
241 case 'x':
242 xflag = 1;
243 if ((proxy = strdup(optarg)) == NULL)
244 err(1, NULL);
245 break;
246 case 'z':
247 zflag = 1;
248 break;
249 case 'D':
250 Dflag = 1;
251 break;
252 case 'S':
253 Sflag = 1;
254 break;
255 case 'T':
256 Tflag = parse_iptos(optarg);
257 break;
258 default:
259 usage(1);
260 }
261 }
262 argc -= optind;
263 argv += optind;
264
265 /* Cruft to make sure options are clean, and used properly. */
266 if (argv[0] && !argv[1] && family == AF_UNIX) {
267 if (uflag)
268 errx(1, "cannot use -u and -U");
269 host = argv[0];
270 uport = NULL;
271 } else if (argv[0] && !argv[1]) {
272 if (!lflag)
273 usage(1);
274 uport = argv[0];
275 host = NULL;
276 } else if (argv[0] && argv[1]) {
277 if (family == AF_UNIX)
278 usage(1);
279 host = argv[0];
280 uport = argv[1];
281 } else {
282 if (!(lflag && pflag))
283 usage(1);
284 }
285
286 if (argc > 2)
287 usage(1);
288
289 if (lflag && sflag)
290 errx(1, "cannot use -s and -l");
291 if (lflag && rflag)
292 errx(1, "cannot use -r and -l");
293 if (lflag && Bflag)
294 errx(1, "cannot use -B and -l");
295 if (lflag && (timeout >= 0))
296 warnx("-w has no effect with -l");
297 if (lflag && pflag) {
298 if (uport)
299 usage(1);
300 uport = pflag;
301 }
302 if (lflag && zflag)
303 errx(1, "cannot use -z and -l");
304 if (!lflag && kflag)
305 errx(1, "must use -l with -k");
306 if (lflag && (Pflag || xflag || Xflag))
307 errx(1, "cannot use -l with -P, -X or -x");
308
309 /* Initialize addrinfo structure. */
310 if (family != AF_UNIX) {
311 (void) memset(&hints, 0, sizeof (struct addrinfo));
312 hints.ai_family = family;
313 hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
314 hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
315 if (nflag)
316 hints.ai_flags |= AI_NUMERICHOST;
317 }
318
319 if (xflag) {
320 if (uflag)
321 errx(1, "no proxy support for UDP mode");
322
323 if (lflag)
324 errx(1, "no proxy support for listen");
325
326 if (family == AF_UNIX)
327 errx(1, "no proxy support for unix sockets");
328
329 if (family == AF_INET6)
330 errx(1, "no proxy support for IPv6");
331
332 if (sflag)
333 errx(1, "no proxy support for local source address");
334
335 if ((proxyhost = strtok(proxy, ":")) == NULL)
336 errx(1, "missing port specification");
337 proxyport = strtok(NULL, ":");
338
339 (void) memset(&proxyhints, 0, sizeof (struct addrinfo));
340 proxyhints.ai_family = family;
341 proxyhints.ai_socktype = SOCK_STREAM;
342 proxyhints.ai_protocol = IPPROTO_TCP;
343 if (nflag)
344 proxyhints.ai_flags |= AI_NUMERICHOST;
345 }
346
347 if (lflag) {
348 int connfd;
349 ret = 0;
350
351 if (family == AF_UNIX) {
352 if (host == NULL)
353 usage(1);
354 s = unix_listen(host);
355 }
356
357 /* Allow only one connection at a time, but stay alive. */
358 for (;;) {
359 if (family != AF_UNIX) {
360 /* check if uport is valid */
361 if (strtonum(uport, PORT_MIN, PORT_MAX,
362 &errstr) == 0)
363 errx(1, "port number %s: %s",
364 uport, errstr);
365 s = local_listen(host, uport, hints);
366 }
367 if (s < 0)
368 err(1, NULL);
369 /*
370 * For UDP, we will use recvfrom() initially
371 * to wait for a caller, then use the regular
372 * functions to talk to the caller.
373 */
374 if (uflag) {
375 int rv, plen;
376 char buf[8192];
377 struct sockaddr_storage z;
378
379 len = sizeof (z);
380 plen = 1024;
381 rv = recvfrom(s, buf, plen, MSG_PEEK,
382 (struct sockaddr *)&z, &len);
383 if (rv < 0)
384 err(1, "recvfrom");
385
386 rv = connect(s, (struct sockaddr *)&z, len);
387 if (rv < 0)
388 err(1, "connect");
389
390 connfd = s;
391 } else {
392 len = sizeof (cliaddr);
393 connfd = accept(s, (struct sockaddr *)&cliaddr,
394 &len);
395 if ((connfd != -1) && vflag) {
396 char ntop[NI_MAXHOST + NI_MAXSERV];
397 (void) fprintf(stderr,
398 "Received connection from %s\n",
399 print_addr(ntop, sizeof (ntop),
400 (struct sockaddr *)&cliaddr, len,
401 nflag ? NI_NUMERICHOST : 0));
402 }
403 }
404
405 readwrite(connfd);
406 (void) close(connfd);
407 if (family != AF_UNIX)
408 (void) close(s);
409
410 if (!kflag)
411 break;
412 }
413 } else if (family == AF_UNIX) {
414 ret = 0;
415
416 if ((s = unix_connect(host)) > 0 && !zflag) {
417 readwrite(s);
418 (void) close(s);
419 } else
420 ret = 1;
421
422 exit(ret);
423
424 } else { /* AF_INET or AF_INET6 */
425 int i;
426
427 /* Construct the portlist. */
428 build_ports(uport);
429
430 /* Cycle through portlist, connecting to each port. */
431 for (i = 0; i < ports.numports; i++) {
432 (void) snprintf(port, sizeof (port), "%u",
433 ports.list[i]);
434
435 if (s != -1)
436 (void) close(s);
437
438 if (xflag)
439 s = socks_connect(host, port,
440 proxyhost, proxyport, proxyhints, socksv,
441 Pflag);
442 else
443 s = remote_connect(host, port, hints);
444
445 if (s < 0)
446 continue;
447
448 ret = 0;
449 if (vflag || zflag) {
450 /* For UDP, make sure we are connected. */
451 if (uflag) {
452 if (udptest(s) == -1) {
453 ret = 1;
454 continue;
455 }
456 }
457
458 /* Don't look up port if -n. */
459 if (nflag)
460 sv = NULL;
461 else {
462 sv = getservbyport(
463 ntohs(ports.list[i]),
464 uflag ? "udp" : "tcp");
465 }
466
467 (void) fprintf(stderr, "Connection to %s %s "
468 "port [%s/%s] succeeded!\n",
469 host, port, uflag ? "udp" : "tcp",
470 sv ? sv->s_name : "*");
471 }
472 if (!zflag)
473 readwrite(s);
474 }
475 free(ports.list);
476 }
477
478 if (s != -1)
479 (void) close(s);
480
481 return (ret);
482 }
483
484 /*
485 * print IP address and (optionally) a port
486 */
487 const char *
print_addr(char * ntop,size_t ntlen,struct sockaddr * addr,int len,int flags)488 print_addr(char *ntop, size_t ntlen, struct sockaddr *addr, int len, int flags)
489 {
490 char port[NI_MAXSERV];
491 int e;
492
493 /* print port always as number */
494 if ((e = getnameinfo(addr, len, ntop, ntlen,
495 port, sizeof (port), flags|NI_NUMERICSERV)) != 0) {
496 return ((char *)gai_strerror(e));
497 }
498
499 (void) strlcat(ntop, " port ", ntlen);
500 (void) strlcat(ntop, port, ntlen);
501
502 return (ntop);
503 }
504
505 /*
506 * unix_connect()
507 * Returns a socket connected to a local unix socket. Returns -1 on failure.
508 */
509 int
unix_connect(const char * path)510 unix_connect(const char *path)
511 {
512 struct sockaddr_un sunaddr;
513 int s;
514
515 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
516 return (-1);
517
518 (void) memset(&sunaddr, 0, sizeof (struct sockaddr_un));
519 sunaddr.sun_family = AF_UNIX;
520
521 if (strlcpy(sunaddr.sun_path, path, sizeof (sunaddr.sun_path)) >=
522 sizeof (sunaddr.sun_path)) {
523 (void) close(s);
524 errno = ENAMETOOLONG;
525 return (-1);
526 }
527 if (connect(s, (struct sockaddr *)&sunaddr, SUN_LEN(&sunaddr)) < 0) {
528 (void) close(s);
529 return (-1);
530 }
531 return (s);
532 }
533
534 /*
535 * unix_listen()
536 * Create a unix domain socket, and listen on it.
537 */
538 int
unix_listen(const char * path)539 unix_listen(const char *path)
540 {
541 struct sockaddr_un sunaddr;
542 int s;
543
544 /* Create unix domain socket. */
545 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
546 return (-1);
547
548 (void) memset(&sunaddr, 0, sizeof (struct sockaddr_un));
549 sunaddr.sun_family = AF_UNIX;
550
551 if (strlcpy(sunaddr.sun_path, path, sizeof (sunaddr.sun_path)) >=
552 sizeof (sunaddr.sun_path)) {
553 (void) close(s);
554 errno = ENAMETOOLONG;
555 return (-1);
556 }
557
558 if (bind(s, (struct sockaddr *)&sunaddr, SUN_LEN(&sunaddr)) < 0) {
559 (void) close(s);
560 return (-1);
561 }
562
563 if (listen(s, 5) < 0) {
564 (void) close(s);
565 return (-1);
566 }
567 return (s);
568 }
569
570 /*
571 * remote_connect()
572 * Returns a socket connected to a remote host. Properly binds to a local
573 * port or source address if needed. Returns -1 on failure.
574 */
575 int
remote_connect(const char * host,const char * port,struct addrinfo hints)576 remote_connect(const char *host, const char *port, struct addrinfo hints)
577 {
578 struct addrinfo *res, *res0;
579 int s, error;
580
581 if ((error = getaddrinfo(host, port, &hints, &res)))
582 errx(1, "getaddrinfo: %s", gai_strerror(error));
583
584 res0 = res;
585 do {
586 if ((s = socket(res0->ai_family, res0->ai_socktype,
587 res0->ai_protocol)) < 0) {
588 warn("failed to create socket");
589 continue;
590 }
591
592 /* Bind to a local port or source address if specified. */
593 if (sflag || pflag) {
594 struct addrinfo ahints, *ares;
595
596 (void) memset(&ahints, 0, sizeof (struct addrinfo));
597 ahints.ai_family = res0->ai_family;
598 ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
599 ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
600 ahints.ai_flags = AI_PASSIVE;
601 if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
602 errx(1, "getaddrinfo: %s", gai_strerror(error));
603
604 if (bind(s, (struct sockaddr *)ares->ai_addr,
605 ares->ai_addrlen) < 0)
606 errx(1, "bind failed: %s", strerror(errno));
607 freeaddrinfo(ares);
608
609 if (vflag && !lflag) {
610 if (sflag != NULL)
611 (void) fprintf(stderr,
612 "Using source address: %s\n",
613 sflag);
614 if (pflag != NULL)
615 (void) fprintf(stderr,
616 "Using source port: %s\n", pflag);
617 }
618 }
619
620 set_common_sockopts(s, res0->ai_family);
621
622 if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
623 break;
624 else if (vflag) {
625 char ntop[NI_MAXHOST + NI_MAXSERV];
626 warn("connect to %s [host %s] (%s) failed",
627 print_addr(ntop, sizeof (ntop),
628 res0->ai_addr, res0->ai_addrlen, NI_NUMERICHOST),
629 host, uflag ? "udp" : "tcp");
630 }
631
632 (void) close(s);
633 s = -1;
634 } while ((res0 = res0->ai_next) != NULL);
635
636 freeaddrinfo(res);
637
638 return (s);
639 }
640
641 /*
642 * local_listen()
643 * Returns a socket listening on a local port, binds to specified source
644 * address. Returns -1 on failure.
645 */
646 int
local_listen(const char * host,const char * port,struct addrinfo hints)647 local_listen(const char *host, const char *port, struct addrinfo hints)
648 {
649 struct addrinfo *res, *res0;
650 int s, ret, x = 1;
651 int error;
652
653 /* Allow nodename to be null. */
654 hints.ai_flags |= AI_PASSIVE;
655
656 if ((error = getaddrinfo(host, port, &hints, &res)))
657 errx(1, "getaddrinfo: %s", gai_strerror(error));
658
659 res0 = res;
660 do {
661 if ((s = socket(res0->ai_family, res0->ai_socktype,
662 res0->ai_protocol)) < 0) {
663 warn("failed to create socket");
664 continue;
665 }
666
667 ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x));
668 if (ret == -1)
669 err(1, NULL);
670
671 set_common_sockopts(s, res0->ai_family);
672
673 if (bind(s, (struct sockaddr *)res0->ai_addr,
674 res0->ai_addrlen) == 0)
675 break;
676
677 (void) close(s);
678 s = -1;
679 } while ((res0 = res0->ai_next) != NULL);
680
681 if (!uflag && s != -1) {
682 if (listen(s, 1) < 0)
683 err(1, "listen");
684 }
685
686 freeaddrinfo(res);
687
688 return (s);
689 }
690
691 /*
692 * readwrite()
693 * Loop that polls on the network file descriptor and stdin.
694 */
695 void
readwrite(int nfd)696 readwrite(int nfd)
697 {
698 struct pollfd pfd[2];
699 unsigned char buf[8192];
700 int n, wfd = fileno(stdin);
701 int lfd = fileno(stdout);
702 int plen;
703
704 plen = 1024;
705
706 /* Setup Network FD */
707 pfd[0].fd = nfd;
708 pfd[0].events = POLLIN;
709
710 /* Set up STDIN FD. */
711 pfd[1].fd = wfd;
712 pfd[1].events = POLLIN;
713
714 while (pfd[0].fd != -1) {
715 if (iflag)
716 (void) sleep(iflag);
717
718 if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
719 (void) close(nfd);
720 err(1, "Polling Error");
721 }
722
723 if (n == 0)
724 return;
725
726 if (pfd[0].revents & (POLLIN|POLLHUP)) {
727 if ((n = read(nfd, buf, plen)) < 0)
728 return;
729 else if (n == 0) {
730 (void) shutdown(nfd, SHUT_RD);
731 pfd[0].fd = -1;
732 pfd[0].events = 0;
733 } else {
734 if (tflag)
735 atelnet(nfd, buf, n);
736 if (atomicio(vwrite, lfd, buf, n) != n)
737 return;
738 }
739 }
740
741 /*
742 * handle the case of disconnected pipe: after pipe
743 * is closed (indicated by POLLHUP) there may still
744 * be some data lingering (POLLIN). After we read
745 * the data, only POLLHUP remains, read() returns 0
746 * and we are finished.
747 */
748 if (!dflag && (pfd[1].revents & (POLLIN|POLLHUP))) {
749 if ((n = read(wfd, buf, plen)) < 0)
750 return;
751 else if (n == 0) {
752 (void) shutdown(nfd, SHUT_WR);
753 pfd[1].fd = -1;
754 pfd[1].events = 0;
755 } else {
756 if (atomicio(vwrite, nfd, buf, n) != n)
757 return;
758 }
759 }
760 }
761 }
762
763 /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
764 void
atelnet(int nfd,unsigned char * buf,unsigned int size)765 atelnet(int nfd, unsigned char *buf, unsigned int size)
766 {
767 unsigned char *p, *end;
768 unsigned char obuf[4];
769
770 end = buf + size;
771 obuf[0] = '\0';
772
773 for (p = buf; p < end; p++) {
774 if (*p != IAC)
775 break;
776
777 obuf[0] = IAC;
778 obuf[1] = 0;
779 p++;
780 /* refuse all options */
781 if ((*p == WILL) || (*p == WONT))
782 obuf[1] = DONT;
783 if ((*p == DO) || (*p == DONT))
784 obuf[1] = WONT;
785 if (obuf[1]) {
786 p++;
787 obuf[2] = *p;
788 obuf[3] = '\0';
789 if (atomicio(vwrite, nfd, obuf, 3) != 3)
790 warn("Write Error!");
791 obuf[0] = '\0';
792 }
793 }
794 }
795
796 /*
797 * build_ports()
798 * Build an array of ports in ports.list[], listing each port
799 * that we should try to connect to.
800 */
801 void
build_ports(char * p)802 build_ports(char *p)
803 {
804 const char *errstr;
805 const char *token;
806 char *n;
807 int lo, hi, cp;
808 int i;
809
810 /* Set up initial portlist. */
811 ports.list = malloc(PLIST_SZ * sizeof (uint16_t));
812 if (ports.list == NULL)
813 err(1, NULL);
814 ports.listsize = PLIST_SZ;
815 ports.numports = 0;
816
817 /* Cycle through list of given ports sep. by "," */
818 while ((token = strsep(&p, ",")) != NULL) {
819 if (*token == '\0')
820 errx(1, "Invalid port/portlist format: "
821 "zero length port");
822
823 /* check if it is a range */
824 if ((n = strchr(token, '-')) != NULL)
825 *n++ = '\0';
826
827 lo = strtonum(token, PORT_MIN, PORT_MAX, &errstr);
828 if (errstr)
829 errx(1, "port number %s: %s", errstr, token);
830
831 if (n == NULL) {
832 hi = lo;
833 } else {
834 hi = strtonum(n, PORT_MIN, PORT_MAX, &errstr);
835 if (errstr)
836 errx(1, "port number %s: %s", errstr, n);
837 if (lo > hi) {
838 cp = hi;
839 hi = lo;
840 lo = cp;
841 }
842 }
843
844 /*
845 * Grow the portlist if needed.
846 * We double the size and add size of current range
847 * to make sure we don't have to resize that often.
848 */
849 if (hi - lo + ports.numports + 1 >= ports.listsize) {
850 ports.listsize = ports.listsize * 2 + hi - lo;
851 ports.list = realloc(ports.list,
852 ports.listsize * sizeof (uint16_t));
853 if (ports.list == NULL)
854 err(1, NULL);
855 }
856
857 /* Load ports sequentially. */
858 for (i = lo; i <= hi; i++)
859 ports.list[ports.numports++] = i;
860 }
861
862 /* Randomly swap ports. */
863 if (rflag) {
864 int y;
865 uint16_t u;
866
867 if (ports.numports < 2) {
868 warnx("can not swap %d port randomly",
869 ports.numports);
870 return;
871 }
872 srandom(time(NULL));
873 for (i = 0; i < ports.numports; i++) {
874 y = random() % (ports.numports - 1);
875 u = ports.list[i];
876 ports.list[i] = ports.list[y];
877 ports.list[y] = u;
878 }
879 }
880 }
881
882 /*
883 * udptest()
884 * Do a few writes to see if the UDP port is there.
885 * XXX - Better way of doing this? Doesn't work for IPv6.
886 * Also fails after around 100 ports checked.
887 */
888 int
udptest(int s)889 udptest(int s)
890 {
891 int i, ret;
892
893 for (i = 0; i <= 3; i++) {
894 if (write(s, "X", 1) == 1)
895 ret = 1;
896 else
897 ret = -1;
898 }
899 return (ret);
900 }
901
902 void
set_common_sockopts(int s,int af)903 set_common_sockopts(int s, int af)
904 {
905 int x = 1;
906
907 if (Sflag) {
908 if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
909 &x, sizeof (x)) == -1) {
910 err(1, NULL);
911 }
912 }
913
914 if (Bflag) {
915 ipsec_req_t req = { IPSEC_PREF_NEVER, IPSEC_PREF_NEVER,
916 IPSEC_PREF_NEVER, 0, 0, 0 };
917 int level;
918
919 switch (af) {
920 case AF_INET:
921 level = IPPROTO_IP;
922 break;
923 case AF_INET6:
924 level = IPPROTO_IPV6;
925 break;
926 default:
927 err(1, "cannot set IPsec bypass on unsupported socket "
928 "family 0x%x", af);
929 }
930 /* IP_SEC_OPT == IPV6_SEC_OPT, so we're good regardless... */
931 if (setsockopt(s, level, IP_SEC_OPT, &req, sizeof (req)) < 0) {
932 err(1, "IPsec bypass attempt");
933 }
934 }
935
936 if (Dflag) {
937 if (setsockopt(s, SOL_SOCKET, SO_DEBUG, &x, sizeof (x)) == -1)
938 err(1, NULL);
939 }
940 if (Tflag != -1) {
941 switch (af) {
942 case AF_INET:
943 if (setsockopt(s, IPPROTO_IP, IP_TOS, &Tflag,
944 sizeof (Tflag)) == -1) {
945 err(1, "failed to set IP ToS socket option");
946 }
947 break;
948 case AF_INET6:
949 if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &Tflag,
950 sizeof (Tflag)) == -1) {
951 err(1, "failed to set IPv6 traffic class "
952 "socket option");
953 }
954 break;
955 default:
956 err(1, "cannot set TTL/Hops on unsupported socket "
957 "family 0x%x", af);
958 }
959 }
960
961 if (ttl != -1) {
962 switch (af) {
963 case AF_INET:
964 if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl,
965 sizeof (ttl)) != 0) {
966 err(1, "failed to set IP TTL socket option");
967 }
968 break;
969 case AF_INET6:
970 if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,
971 sizeof (ttl)) != 0) {
972 err(1, "failed to set IPv6 unicast hops socket "
973 "option");
974 }
975 break;
976 default:
977 err(1, "cannot set TTL/Hops on unsupported socket "
978 "family 0x%x", af);
979 }
980 }
981
982 if (minttl != -1) {
983 switch (af) {
984 case AF_INET:
985 if (setsockopt(s, IPPROTO_IP, IP_MINTTL, &minttl,
986 sizeof (minttl)) != 0) {
987 err(1, "failed to set IP minimum TTL socket "
988 "option");
989 }
990 break;
991 case AF_INET6:
992 if (setsockopt(s, IPPROTO_IPV6, IPV6_MINHOPCOUNT,
993 &minttl, sizeof (minttl)) != 0) {
994 err(1, "failed to set IPv6 minimum hop count "
995 "socket option");
996 }
997 break;
998 default:
999 err(1, "cannot set minimum TTL/Hops on unsupported "
1000 "socket family 0x%x", af);
1001 }
1002 }
1003
1004 }
1005
1006 int
parse_iptos(const char * s)1007 parse_iptos(const char *s)
1008 {
1009 int tos;
1010 const char *errstr;
1011
1012 if (strcmp(s, "lowdelay") == 0)
1013 return (IPTOS_LOWDELAY);
1014 if (strcmp(s, "throughput") == 0)
1015 return (IPTOS_THROUGHPUT);
1016 if (strcmp(s, "reliability") == 0)
1017 return (IPTOS_RELIABILITY);
1018
1019 tos = strtonumx(s, 0, 255, &errstr, 0);
1020 if (errstr != NULL) {
1021 errx(1, "IP ToS/IPv6 TC is %s: %s, valid values are "
1022 "between 0 and 255", errstr, optarg);
1023 }
1024
1025 return (tos);
1026 }
1027
1028 void
help(void)1029 help(void)
1030 {
1031 usage(0);
1032 (void) fprintf(stderr, "\tCommand Summary:\n\
1033 \t-4 Use IPv4\n\
1034 \t-6 Use IPv6\n\
1035 \t-B Bypass IPsec policy to force cleartext\n\
1036 \t-D Enable the debug socket option\n\
1037 \t-d Detach from stdin\n\
1038 \t-h This help text\n\
1039 \t-i secs\t Delay interval for lines sent, ports scanned\n\
1040 \t-k Keep inbound sockets open for multiple connects\n\
1041 \t-l Listen mode, for inbound connects\n\
1042 \t-l Listen mode, for inbound connects\n\
1043 \t-M ttl\t Set the outbound IPv4 TTL / IPv6 Hop Limit\n\
1044 \t-m minttl Set the inbound minimum IPv4 TTL / IPv6 Hop Limit\n\
1045 \t-n Suppress name/port resolutions\n\
1046 \t-P proxyuser\tUsername for proxy authentication\n\
1047 \t-p port\t Specify local port or listen port\n\
1048 \t-r Randomize remote ports\n\
1049 \t-S Enable TCP MD5 signature socket option\n\
1050 \t-s addr\t Local source address\n\
1051 \t-T ToS\t Set IP Type of Service\n\
1052 \t-t Answer TELNET negotiation\n\
1053 \t-U Use UNIX domain socket\n\
1054 \t-u UDP mode\n\
1055 \t-v Verbose\n\
1056 \t-w secs\t Timeout for connects and final net reads\n\
1057 \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
1058 \t-x addr[:port]\tSpecify proxy address and port\n\
1059 \t-z Zero-I/O mode [used for scanning]\n\
1060 Port numbers can be individuals, ranges (lo-hi; inclusive) and\n\
1061 combinations of both separated by comma (e.g. 10,22-25,80)\n");
1062 exit(1);
1063 }
1064
1065 void
usage(int ret)1066 usage(int ret)
1067 {
1068 (void) fprintf(stderr,
1069 "usage: nc [-46BDdhklnrStUuvz] [-i interval] [-M ttl] [-m minttl]\n"
1070 "\t [-P proxy_username] [-p port] [-s source_ip_address] "
1071 "[-T ToS]\n"
1072 "\t [-w timeout] [-X proxy_protocol] [-x proxy_address[:port]]\n"
1073 "\t [hostname] [port[s]]\n");
1074 if (ret)
1075 exit(1);
1076 }
1077