netcat.c revision 214047
1214047Sdelphij/* $OpenBSD: netcat.c,v 1.98 2010/07/03 04:44:51 guenther Exp $ */ 2141261Sdelphij/* 3141261Sdelphij * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> 4141261Sdelphij * 5141261Sdelphij * Redistribution and use in source and binary forms, with or without 6141261Sdelphij * modification, are permitted provided that the following conditions 7141261Sdelphij * are met: 8141261Sdelphij * 9141261Sdelphij * 1. Redistributions of source code must retain the above copyright 10141261Sdelphij * notice, this list of conditions and the following disclaimer. 11141261Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 12141261Sdelphij * notice, this list of conditions and the following disclaimer in the 13141261Sdelphij * documentation and/or other materials provided with the distribution. 14141261Sdelphij * 3. The name of the author may not be used to endorse or promote products 15141261Sdelphij * derived from this software without specific prior written permission. 16141261Sdelphij * 17141261Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18141261Sdelphij * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19141261Sdelphij * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20141261Sdelphij * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21141261Sdelphij * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22141261Sdelphij * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23141261Sdelphij * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24141261Sdelphij * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25141261Sdelphij * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26141261Sdelphij * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27141394Sdelphij * 28141394Sdelphij * $FreeBSD: head/contrib/netcat/netcat.c 214047 2010-10-19 00:01:53Z delphij $ 29141261Sdelphij */ 30141261Sdelphij 31141261Sdelphij/* 32141261Sdelphij * Re-written nc(1) for OpenBSD. Original implementation by 33141261Sdelphij * *Hobbit* <hobbit@avian.org>. 34141261Sdelphij */ 35141261Sdelphij 36141394Sdelphij#include <sys/limits.h> 37141261Sdelphij#include <sys/types.h> 38141261Sdelphij#include <sys/socket.h> 39202640Sdelphij#include <sys/sysctl.h> 40141261Sdelphij#include <sys/time.h> 41141261Sdelphij#include <sys/un.h> 42141261Sdelphij 43141261Sdelphij#include <netinet/in.h> 44158798Sdelphij#include <netinet/in_systm.h> 45141394Sdelphij#ifdef IPSEC 46171135Sgnn#include <netipsec/ipsec.h> 47141394Sdelphij#endif 48141261Sdelphij#include <netinet/tcp.h> 49158798Sdelphij#include <netinet/ip.h> 50141261Sdelphij#include <arpa/telnet.h> 51141261Sdelphij 52141261Sdelphij#include <err.h> 53141261Sdelphij#include <errno.h> 54186343Sdelphij#include <getopt.h> 55141261Sdelphij#include <netdb.h> 56141261Sdelphij#include <poll.h> 57141261Sdelphij#include <stdarg.h> 58141261Sdelphij#include <stdio.h> 59141261Sdelphij#include <stdlib.h> 60141261Sdelphij#include <string.h> 61141261Sdelphij#include <unistd.h> 62141261Sdelphij#include <fcntl.h> 63158798Sdelphij#include <limits.h> 64158798Sdelphij#include "atomicio.h" 65141261Sdelphij 66141261Sdelphij#ifndef SUN_LEN 67141261Sdelphij#define SUN_LEN(su) \ 68141261Sdelphij (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) 69141261Sdelphij#endif 70141261Sdelphij 71141261Sdelphij#define PORT_MAX 65535 72141261Sdelphij#define PORT_MAX_LEN 6 73141261Sdelphij 74141261Sdelphij/* Command Line Options */ 75141261Sdelphijint dflag; /* detached, no stdin */ 76167964Sdelphijunsigned int iflag; /* Interval Flag */ 77158798Sdelphijint jflag; /* use jumbo frames if we can */ 78141261Sdelphijint kflag; /* More than one connect */ 79141261Sdelphijint lflag; /* Bind to local port */ 80141261Sdelphijint nflag; /* Don't do name look up */ 81186343Sdelphijint FreeBSD_Oflag; /* Do not use TCP options */ 82158798Sdelphijchar *Pflag; /* Proxy username */ 83141261Sdelphijchar *pflag; /* Localport flag */ 84141261Sdelphijint rflag; /* Random ports flag */ 85141261Sdelphijchar *sflag; /* Source Address */ 86141261Sdelphijint tflag; /* Telnet Emulation */ 87141261Sdelphijint uflag; /* UDP - Default to TCP */ 88141261Sdelphijint vflag; /* Verbosity */ 89141261Sdelphijint xflag; /* Socks proxy */ 90141261Sdelphijint zflag; /* Port Scan Flag */ 91141261Sdelphijint Dflag; /* sodebug */ 92186343Sdelphijint Iflag; /* TCP receive buffer size */ 93186343Sdelphijint Oflag; /* TCP send buffer size */ 94141261Sdelphijint Sflag; /* TCP MD5 signature option */ 95158798Sdelphijint Tflag = -1; /* IP Type of Service */ 96214047Sdelphiju_int rtableid; 97141261Sdelphij 98141261Sdelphijint timeout = -1; 99141261Sdelphijint family = AF_UNSPEC; 100141261Sdelphijchar *portlist[PORT_MAX+1]; 101141261Sdelphij 102141261Sdelphijvoid atelnet(int, unsigned char *, unsigned int); 103141261Sdelphijvoid build_ports(char *); 104141261Sdelphijvoid help(void); 105141261Sdelphijint local_listen(char *, char *, struct addrinfo); 106141261Sdelphijvoid readwrite(int); 107158798Sdelphijint remote_connect(const char *, const char *, struct addrinfo); 108158798Sdelphijint socks_connect(const char *, const char *, struct addrinfo, 109158798Sdelphij const char *, const char *, struct addrinfo, int, const char *); 110141261Sdelphijint udptest(int); 111141261Sdelphijint unix_connect(char *); 112141261Sdelphijint unix_listen(char *); 113158798Sdelphijvoid set_common_sockopts(int); 114158798Sdelphijint parse_iptos(char *); 115141261Sdelphijvoid usage(int); 116141261Sdelphij 117141394Sdelphij#ifdef IPSEC 118141394Sdelphijvoid add_ipsec_policy(int, char *); 119141394Sdelphij 120141394Sdelphijchar *ipsec_policy[2]; 121141394Sdelphij#endif 122141394Sdelphij 123141261Sdelphijint 124141261Sdelphijmain(int argc, char *argv[]) 125141261Sdelphij{ 126141394Sdelphij int ch, s, ret, socksv, ipsec_count; 127202640Sdelphij int numfibs; 128202640Sdelphij size_t intsize = sizeof(int); 129167964Sdelphij char *host, *uport; 130141261Sdelphij struct addrinfo hints; 131141261Sdelphij struct servent *sv; 132141261Sdelphij socklen_t len; 133141261Sdelphij struct sockaddr_storage cliaddr; 134141261Sdelphij char *proxy; 135167964Sdelphij const char *errstr, *proxyhost = "", *proxyport = NULL; 136141261Sdelphij struct addrinfo proxyhints; 137186343Sdelphij struct option longopts[] = { 138186343Sdelphij { "no-tcpopt", no_argument, &FreeBSD_Oflag, 1 }, 139186343Sdelphij { NULL, 0, NULL, 0 } 140186343Sdelphij }; 141141261Sdelphij 142141261Sdelphij ret = 1; 143141394Sdelphij ipsec_count = 0; 144141261Sdelphij s = 0; 145141261Sdelphij socksv = 5; 146141261Sdelphij host = NULL; 147141261Sdelphij uport = NULL; 148141261Sdelphij sv = NULL; 149141261Sdelphij 150186343Sdelphij while ((ch = getopt_long(argc, argv, 151206675Sdelphij "46DdEe:hI:i:jklnoO:P:p:rSs:tT:UuV:vw:X:x:z", 152186343Sdelphij longopts, NULL)) != -1) { 153141261Sdelphij switch (ch) { 154141261Sdelphij case '4': 155141261Sdelphij family = AF_INET; 156141261Sdelphij break; 157141261Sdelphij case '6': 158141261Sdelphij family = AF_INET6; 159141261Sdelphij break; 160141261Sdelphij case 'U': 161141261Sdelphij family = AF_UNIX; 162141261Sdelphij break; 163141261Sdelphij case 'X': 164141261Sdelphij if (strcasecmp(optarg, "connect") == 0) 165141261Sdelphij socksv = -1; /* HTTP proxy CONNECT */ 166141261Sdelphij else if (strcmp(optarg, "4") == 0) 167141261Sdelphij socksv = 4; /* SOCKS v.4 */ 168141261Sdelphij else if (strcmp(optarg, "5") == 0) 169141261Sdelphij socksv = 5; /* SOCKS v.5 */ 170141261Sdelphij else 171141261Sdelphij errx(1, "unsupported proxy protocol"); 172141261Sdelphij break; 173141261Sdelphij case 'd': 174141261Sdelphij dflag = 1; 175141261Sdelphij break; 176141394Sdelphij case 'e': 177141394Sdelphij#ifdef IPSEC 178141394Sdelphij ipsec_policy[ipsec_count++ % 2] = optarg; 179141394Sdelphij#else 180141394Sdelphij errx(1, "IPsec support unavailable."); 181141394Sdelphij#endif 182141394Sdelphij break; 183141394Sdelphij case 'E': 184141394Sdelphij#ifdef IPSEC 185141394Sdelphij ipsec_policy[0] = "in ipsec esp/transport//require"; 186141394Sdelphij ipsec_policy[1] = "out ipsec esp/transport//require"; 187141394Sdelphij#else 188141394Sdelphij errx(1, "IPsec support unavailable."); 189141394Sdelphij#endif 190141394Sdelphij break; 191141261Sdelphij case 'h': 192141261Sdelphij help(); 193141261Sdelphij break; 194141261Sdelphij case 'i': 195167964Sdelphij iflag = strtonum(optarg, 0, UINT_MAX, &errstr); 196167964Sdelphij if (errstr) 197167964Sdelphij errx(1, "interval %s: %s", errstr, optarg); 198141261Sdelphij break; 199158798Sdelphij#ifdef SO_JUMBO 200158798Sdelphij case 'j': 201158798Sdelphij jflag = 1; 202158798Sdelphij break; 203158798Sdelphij#endif 204141261Sdelphij case 'k': 205141261Sdelphij kflag = 1; 206141261Sdelphij break; 207141261Sdelphij case 'l': 208141261Sdelphij lflag = 1; 209141261Sdelphij break; 210141261Sdelphij case 'n': 211141261Sdelphij nflag = 1; 212141261Sdelphij break; 213141394Sdelphij case 'o': 214206675Sdelphij fprintf(stderr, "option -o is deprecated.\n"); 215141394Sdelphij break; 216158798Sdelphij case 'P': 217158798Sdelphij Pflag = optarg; 218158798Sdelphij break; 219141261Sdelphij case 'p': 220141261Sdelphij pflag = optarg; 221141261Sdelphij break; 222141261Sdelphij case 'r': 223141261Sdelphij rflag = 1; 224141261Sdelphij break; 225141261Sdelphij case 's': 226141261Sdelphij sflag = optarg; 227141261Sdelphij break; 228141261Sdelphij case 't': 229141261Sdelphij tflag = 1; 230141261Sdelphij break; 231141261Sdelphij case 'u': 232141261Sdelphij uflag = 1; 233141261Sdelphij break; 234202640Sdelphij case 'V': 235202640Sdelphij if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1) 236202640Sdelphij errx(1, "Multiple FIBS not supported"); 237214047Sdelphij rtableid = (unsigned int)strtonum(optarg, 0, 238202640Sdelphij numfibs - 1, &errstr); 239202640Sdelphij if (errstr) 240214047Sdelphij errx(1, "rtable %s: %s", errstr, optarg); 241202640Sdelphij break; 242141261Sdelphij case 'v': 243141261Sdelphij vflag = 1; 244141261Sdelphij break; 245141261Sdelphij case 'w': 246167964Sdelphij timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr); 247167964Sdelphij if (errstr) 248167964Sdelphij errx(1, "timeout %s: %s", errstr, optarg); 249141261Sdelphij timeout *= 1000; 250141261Sdelphij break; 251141261Sdelphij case 'x': 252141261Sdelphij xflag = 1; 253141261Sdelphij if ((proxy = strdup(optarg)) == NULL) 254141261Sdelphij err(1, NULL); 255141261Sdelphij break; 256141261Sdelphij case 'z': 257141261Sdelphij zflag = 1; 258141261Sdelphij break; 259141261Sdelphij case 'D': 260141261Sdelphij Dflag = 1; 261141261Sdelphij break; 262186343Sdelphij case 'I': 263186343Sdelphij Iflag = strtonum(optarg, 1, 65536 << 14, &errstr); 264186343Sdelphij if (errstr != NULL) 265186343Sdelphij errx(1, "TCP receive window %s: %s", 266186343Sdelphij errstr, optarg); 267186343Sdelphij break; 268186343Sdelphij case 'O': 269186343Sdelphij Oflag = strtonum(optarg, 1, 65536 << 14, &errstr); 270186343Sdelphij if (errstr != NULL) { 271186343Sdelphij if (strcmp(errstr, "invalid") != 0) 272186343Sdelphij errx(1, "TCP send window %s: %s", 273186343Sdelphij errstr, optarg); 274186343Sdelphij } 275186343Sdelphij break; 276141261Sdelphij case 'S': 277141261Sdelphij Sflag = 1; 278141261Sdelphij break; 279158798Sdelphij case 'T': 280158798Sdelphij Tflag = parse_iptos(optarg); 281158798Sdelphij break; 282141261Sdelphij default: 283141261Sdelphij usage(1); 284141261Sdelphij } 285141261Sdelphij } 286141261Sdelphij argc -= optind; 287141261Sdelphij argv += optind; 288141261Sdelphij 289141261Sdelphij /* Cruft to make sure options are clean, and used properly. */ 290141261Sdelphij if (argv[0] && !argv[1] && family == AF_UNIX) { 291141261Sdelphij if (uflag) 292141261Sdelphij errx(1, "cannot use -u and -U"); 293141261Sdelphij host = argv[0]; 294141261Sdelphij uport = NULL; 295141261Sdelphij } else if (argv[0] && !argv[1]) { 296141261Sdelphij if (!lflag) 297141261Sdelphij usage(1); 298141261Sdelphij uport = argv[0]; 299141261Sdelphij host = NULL; 300141261Sdelphij } else if (argv[0] && argv[1]) { 301141261Sdelphij host = argv[0]; 302141261Sdelphij uport = argv[1]; 303141261Sdelphij } else 304141261Sdelphij usage(1); 305141261Sdelphij 306141261Sdelphij if (lflag && sflag) 307141261Sdelphij errx(1, "cannot use -s and -l"); 308141261Sdelphij if (lflag && pflag) 309141261Sdelphij errx(1, "cannot use -p and -l"); 310141261Sdelphij if (lflag && zflag) 311141261Sdelphij errx(1, "cannot use -z and -l"); 312141261Sdelphij if (!lflag && kflag) 313141261Sdelphij errx(1, "must use -l with -k"); 314141261Sdelphij 315141261Sdelphij /* Initialize addrinfo structure. */ 316141261Sdelphij if (family != AF_UNIX) { 317141261Sdelphij memset(&hints, 0, sizeof(struct addrinfo)); 318141261Sdelphij hints.ai_family = family; 319141261Sdelphij hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; 320141261Sdelphij hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; 321141261Sdelphij if (nflag) 322141261Sdelphij hints.ai_flags |= AI_NUMERICHOST; 323141261Sdelphij } 324141261Sdelphij 325141261Sdelphij if (xflag) { 326141261Sdelphij if (uflag) 327141261Sdelphij errx(1, "no proxy support for UDP mode"); 328141261Sdelphij 329141261Sdelphij if (lflag) 330141261Sdelphij errx(1, "no proxy support for listen"); 331141261Sdelphij 332141261Sdelphij if (family == AF_UNIX) 333141261Sdelphij errx(1, "no proxy support for unix sockets"); 334141261Sdelphij 335141261Sdelphij /* XXX IPv6 transport to proxy would probably work */ 336141261Sdelphij if (family == AF_INET6) 337141261Sdelphij errx(1, "no proxy support for IPv6"); 338141261Sdelphij 339141261Sdelphij if (sflag) 340141261Sdelphij errx(1, "no proxy support for local source address"); 341141261Sdelphij 342141261Sdelphij proxyhost = strsep(&proxy, ":"); 343141261Sdelphij proxyport = proxy; 344141261Sdelphij 345141261Sdelphij memset(&proxyhints, 0, sizeof(struct addrinfo)); 346141261Sdelphij proxyhints.ai_family = family; 347141261Sdelphij proxyhints.ai_socktype = SOCK_STREAM; 348141261Sdelphij proxyhints.ai_protocol = IPPROTO_TCP; 349141261Sdelphij if (nflag) 350141261Sdelphij proxyhints.ai_flags |= AI_NUMERICHOST; 351141261Sdelphij } 352141261Sdelphij 353141261Sdelphij if (lflag) { 354141261Sdelphij int connfd; 355141261Sdelphij ret = 0; 356141261Sdelphij 357141261Sdelphij if (family == AF_UNIX) 358141261Sdelphij s = unix_listen(host); 359141261Sdelphij 360141261Sdelphij /* Allow only one connection at a time, but stay alive. */ 361141261Sdelphij for (;;) { 362141261Sdelphij if (family != AF_UNIX) 363141261Sdelphij s = local_listen(host, uport, hints); 364141261Sdelphij if (s < 0) 365141261Sdelphij err(1, NULL); 366141261Sdelphij /* 367141261Sdelphij * For UDP, we will use recvfrom() initially 368141261Sdelphij * to wait for a caller, then use the regular 369141261Sdelphij * functions to talk to the caller. 370141261Sdelphij */ 371141261Sdelphij if (uflag) { 372158798Sdelphij int rv, plen; 373214047Sdelphij char buf[16384]; 374141261Sdelphij struct sockaddr_storage z; 375141261Sdelphij 376141261Sdelphij len = sizeof(z); 377214047Sdelphij plen = jflag ? 16384 : 2048; 378158798Sdelphij rv = recvfrom(s, buf, plen, MSG_PEEK, 379141261Sdelphij (struct sockaddr *)&z, &len); 380141261Sdelphij if (rv < 0) 381141261Sdelphij err(1, "recvfrom"); 382141261Sdelphij 383141261Sdelphij rv = connect(s, (struct sockaddr *)&z, len); 384141261Sdelphij if (rv < 0) 385141261Sdelphij err(1, "connect"); 386141261Sdelphij 387141261Sdelphij connfd = s; 388141261Sdelphij } else { 389158798Sdelphij len = sizeof(cliaddr); 390141261Sdelphij connfd = accept(s, (struct sockaddr *)&cliaddr, 391141261Sdelphij &len); 392141261Sdelphij } 393141261Sdelphij 394141261Sdelphij readwrite(connfd); 395141261Sdelphij close(connfd); 396141261Sdelphij if (family != AF_UNIX) 397141261Sdelphij close(s); 398141261Sdelphij 399141261Sdelphij if (!kflag) 400141261Sdelphij break; 401141261Sdelphij } 402141261Sdelphij } else if (family == AF_UNIX) { 403141261Sdelphij ret = 0; 404141261Sdelphij 405141261Sdelphij if ((s = unix_connect(host)) > 0 && !zflag) { 406141261Sdelphij readwrite(s); 407141261Sdelphij close(s); 408141261Sdelphij } else 409141261Sdelphij ret = 1; 410141261Sdelphij 411141261Sdelphij exit(ret); 412141261Sdelphij 413141261Sdelphij } else { 414141261Sdelphij int i = 0; 415141261Sdelphij 416141261Sdelphij /* Construct the portlist[] array. */ 417141261Sdelphij build_ports(uport); 418141261Sdelphij 419141261Sdelphij /* Cycle through portlist, connecting to each port. */ 420141261Sdelphij for (i = 0; portlist[i] != NULL; i++) { 421141261Sdelphij if (s) 422141261Sdelphij close(s); 423141261Sdelphij 424141261Sdelphij if (xflag) 425141261Sdelphij s = socks_connect(host, portlist[i], hints, 426158798Sdelphij proxyhost, proxyport, proxyhints, socksv, 427158798Sdelphij Pflag); 428141261Sdelphij else 429141261Sdelphij s = remote_connect(host, portlist[i], hints); 430141261Sdelphij 431141261Sdelphij if (s < 0) 432141261Sdelphij continue; 433141261Sdelphij 434141261Sdelphij ret = 0; 435141261Sdelphij if (vflag || zflag) { 436141261Sdelphij /* For UDP, make sure we are connected. */ 437141261Sdelphij if (uflag) { 438141261Sdelphij if (udptest(s) == -1) { 439141261Sdelphij ret = 1; 440141261Sdelphij continue; 441141261Sdelphij } 442141261Sdelphij } 443141261Sdelphij 444141261Sdelphij /* Don't look up port if -n. */ 445141261Sdelphij if (nflag) 446141261Sdelphij sv = NULL; 447141261Sdelphij else { 448141261Sdelphij sv = getservbyport( 449141261Sdelphij ntohs(atoi(portlist[i])), 450141261Sdelphij uflag ? "udp" : "tcp"); 451141261Sdelphij } 452141261Sdelphij 453205561Sdelphij fprintf(stderr, 454205561Sdelphij "Connection to %s %s port [%s/%s] " 455205561Sdelphij "succeeded!\n", host, portlist[i], 456205561Sdelphij uflag ? "udp" : "tcp", 457141261Sdelphij sv ? sv->s_name : "*"); 458141261Sdelphij } 459141261Sdelphij if (!zflag) 460141261Sdelphij readwrite(s); 461141261Sdelphij } 462141261Sdelphij } 463141261Sdelphij 464141261Sdelphij if (s) 465141261Sdelphij close(s); 466141261Sdelphij 467141261Sdelphij exit(ret); 468141261Sdelphij} 469141261Sdelphij 470141261Sdelphij/* 471141261Sdelphij * unix_connect() 472141261Sdelphij * Returns a socket connected to a local unix socket. Returns -1 on failure. 473141261Sdelphij */ 474141261Sdelphijint 475141261Sdelphijunix_connect(char *path) 476141261Sdelphij{ 477141261Sdelphij struct sockaddr_un sun; 478141261Sdelphij int s; 479141261Sdelphij 480141261Sdelphij if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 481141261Sdelphij return (-1); 482141261Sdelphij (void)fcntl(s, F_SETFD, 1); 483141261Sdelphij 484141261Sdelphij memset(&sun, 0, sizeof(struct sockaddr_un)); 485141261Sdelphij sun.sun_family = AF_UNIX; 486141261Sdelphij 487141261Sdelphij if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= 488141261Sdelphij sizeof(sun.sun_path)) { 489141261Sdelphij close(s); 490141261Sdelphij errno = ENAMETOOLONG; 491141261Sdelphij return (-1); 492141261Sdelphij } 493141261Sdelphij if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { 494141261Sdelphij close(s); 495141261Sdelphij return (-1); 496141261Sdelphij } 497141261Sdelphij return (s); 498141261Sdelphij 499141261Sdelphij} 500141261Sdelphij 501141261Sdelphij/* 502141261Sdelphij * unix_listen() 503141261Sdelphij * Create a unix domain socket, and listen on it. 504141261Sdelphij */ 505141261Sdelphijint 506141261Sdelphijunix_listen(char *path) 507141261Sdelphij{ 508141261Sdelphij struct sockaddr_un sun; 509141261Sdelphij int s; 510141261Sdelphij 511141261Sdelphij /* Create unix domain socket. */ 512141261Sdelphij if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 513141261Sdelphij return (-1); 514141261Sdelphij 515141261Sdelphij memset(&sun, 0, sizeof(struct sockaddr_un)); 516141261Sdelphij sun.sun_family = AF_UNIX; 517141261Sdelphij 518141261Sdelphij if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= 519141261Sdelphij sizeof(sun.sun_path)) { 520141261Sdelphij close(s); 521141261Sdelphij errno = ENAMETOOLONG; 522141261Sdelphij return (-1); 523141261Sdelphij } 524141261Sdelphij 525141261Sdelphij if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { 526141261Sdelphij close(s); 527141261Sdelphij return (-1); 528141261Sdelphij } 529141261Sdelphij 530141261Sdelphij if (listen(s, 5) < 0) { 531141261Sdelphij close(s); 532141261Sdelphij return (-1); 533141261Sdelphij } 534141261Sdelphij return (s); 535141261Sdelphij} 536141261Sdelphij 537141261Sdelphij/* 538141261Sdelphij * remote_connect() 539141261Sdelphij * Returns a socket connected to a remote host. Properly binds to a local 540141261Sdelphij * port or source address if needed. Returns -1 on failure. 541141261Sdelphij */ 542141261Sdelphijint 543158798Sdelphijremote_connect(const char *host, const char *port, struct addrinfo hints) 544141261Sdelphij{ 545141261Sdelphij struct addrinfo *res, *res0; 546186343Sdelphij int s, error, on = 1; 547141261Sdelphij 548141261Sdelphij if ((error = getaddrinfo(host, port, &hints, &res))) 549141261Sdelphij errx(1, "getaddrinfo: %s", gai_strerror(error)); 550141261Sdelphij 551141261Sdelphij res0 = res; 552141261Sdelphij do { 553141261Sdelphij if ((s = socket(res0->ai_family, res0->ai_socktype, 554141261Sdelphij res0->ai_protocol)) < 0) 555141261Sdelphij continue; 556141394Sdelphij#ifdef IPSEC 557141394Sdelphij if (ipsec_policy[0] != NULL) 558141394Sdelphij add_ipsec_policy(s, ipsec_policy[0]); 559141394Sdelphij if (ipsec_policy[1] != NULL) 560141394Sdelphij add_ipsec_policy(s, ipsec_policy[1]); 561141394Sdelphij#endif 562141261Sdelphij 563214047Sdelphij if (rtableid) { 564214047Sdelphij if (setfib(rtableid) == -1) 565202640Sdelphij err(1, "setfib"); 566202640Sdelphij } 567202640Sdelphij 568141261Sdelphij /* Bind to a local port or source address if specified. */ 569141261Sdelphij if (sflag || pflag) { 570141261Sdelphij struct addrinfo ahints, *ares; 571141261Sdelphij 572206689Sdelphij /* try IP_BINDANY, but don't insist */ 573206689Sdelphij setsockopt(s, IPPROTO_IP, IP_BINDANY, &on, sizeof(on)); 574141261Sdelphij memset(&ahints, 0, sizeof(struct addrinfo)); 575141261Sdelphij ahints.ai_family = res0->ai_family; 576141261Sdelphij ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; 577141261Sdelphij ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; 578141261Sdelphij ahints.ai_flags = AI_PASSIVE; 579141261Sdelphij if ((error = getaddrinfo(sflag, pflag, &ahints, &ares))) 580141261Sdelphij errx(1, "getaddrinfo: %s", gai_strerror(error)); 581141261Sdelphij 582141261Sdelphij if (bind(s, (struct sockaddr *)ares->ai_addr, 583141261Sdelphij ares->ai_addrlen) < 0) 584141261Sdelphij errx(1, "bind failed: %s", strerror(errno)); 585141261Sdelphij freeaddrinfo(ares); 586141261Sdelphij } 587141261Sdelphij 588158798Sdelphij set_common_sockopts(s); 589158798Sdelphij 590141261Sdelphij if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0) 591141261Sdelphij break; 592141261Sdelphij else if (vflag) 593141261Sdelphij warn("connect to %s port %s (%s) failed", host, port, 594141261Sdelphij uflag ? "udp" : "tcp"); 595141261Sdelphij 596141261Sdelphij close(s); 597141261Sdelphij s = -1; 598141261Sdelphij } while ((res0 = res0->ai_next) != NULL); 599141261Sdelphij 600141261Sdelphij freeaddrinfo(res); 601141261Sdelphij 602141261Sdelphij return (s); 603141261Sdelphij} 604141261Sdelphij 605141261Sdelphij/* 606141261Sdelphij * local_listen() 607141261Sdelphij * Returns a socket listening on a local port, binds to specified source 608141261Sdelphij * address. Returns -1 on failure. 609141261Sdelphij */ 610141261Sdelphijint 611141261Sdelphijlocal_listen(char *host, char *port, struct addrinfo hints) 612141261Sdelphij{ 613141261Sdelphij struct addrinfo *res, *res0; 614141261Sdelphij int s, ret, x = 1; 615141261Sdelphij int error; 616141261Sdelphij 617141261Sdelphij /* Allow nodename to be null. */ 618141261Sdelphij hints.ai_flags |= AI_PASSIVE; 619141261Sdelphij 620141261Sdelphij /* 621141261Sdelphij * In the case of binding to a wildcard address 622141261Sdelphij * default to binding to an ipv4 address. 623141261Sdelphij */ 624141261Sdelphij if (host == NULL && hints.ai_family == AF_UNSPEC) 625141261Sdelphij hints.ai_family = AF_INET; 626141261Sdelphij 627141261Sdelphij if ((error = getaddrinfo(host, port, &hints, &res))) 628141261Sdelphij errx(1, "getaddrinfo: %s", gai_strerror(error)); 629141261Sdelphij 630141261Sdelphij res0 = res; 631141261Sdelphij do { 632141261Sdelphij if ((s = socket(res0->ai_family, res0->ai_socktype, 633158798Sdelphij res0->ai_protocol)) < 0) 634141261Sdelphij continue; 635141261Sdelphij 636214047Sdelphij if (rtableid) { 637214047Sdelphij if (setfib(rtableid) == -1) 638202640Sdelphij err(1, "setfib"); 639202640Sdelphij } 640202640Sdelphij 641141261Sdelphij ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x)); 642141261Sdelphij if (ret == -1) 643141261Sdelphij err(1, NULL); 644141394Sdelphij#ifdef IPSEC 645141394Sdelphij if (ipsec_policy[0] != NULL) 646141394Sdelphij add_ipsec_policy(s, ipsec_policy[0]); 647141394Sdelphij if (ipsec_policy[1] != NULL) 648141394Sdelphij add_ipsec_policy(s, ipsec_policy[1]); 649141394Sdelphij#endif 650186343Sdelphij if (FreeBSD_Oflag) { 651177837Sbms if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT, 652186343Sdelphij &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1) 653177837Sbms err(1, "disable TCP options"); 654177837Sbms } 655141261Sdelphij 656141261Sdelphij if (bind(s, (struct sockaddr *)res0->ai_addr, 657141261Sdelphij res0->ai_addrlen) == 0) 658141261Sdelphij break; 659141261Sdelphij 660141261Sdelphij close(s); 661141261Sdelphij s = -1; 662141261Sdelphij } while ((res0 = res0->ai_next) != NULL); 663141261Sdelphij 664141261Sdelphij if (!uflag && s != -1) { 665141261Sdelphij if (listen(s, 1) < 0) 666141261Sdelphij err(1, "listen"); 667141261Sdelphij } 668141261Sdelphij 669141261Sdelphij freeaddrinfo(res); 670141261Sdelphij 671141261Sdelphij return (s); 672141261Sdelphij} 673141261Sdelphij 674141261Sdelphij/* 675141261Sdelphij * readwrite() 676141261Sdelphij * Loop that polls on the network file descriptor and stdin. 677141261Sdelphij */ 678141261Sdelphijvoid 679141261Sdelphijreadwrite(int nfd) 680141261Sdelphij{ 681141261Sdelphij struct pollfd pfd[2]; 682214047Sdelphij unsigned char buf[16384]; 683158798Sdelphij int n, wfd = fileno(stdin); 684141261Sdelphij int lfd = fileno(stdout); 685158798Sdelphij int plen; 686141261Sdelphij 687214047Sdelphij plen = jflag ? 16384 : 2048; 688158798Sdelphij 689141261Sdelphij /* Setup Network FD */ 690141261Sdelphij pfd[0].fd = nfd; 691141261Sdelphij pfd[0].events = POLLIN; 692141261Sdelphij 693141261Sdelphij /* Set up STDIN FD. */ 694141261Sdelphij pfd[1].fd = wfd; 695141261Sdelphij pfd[1].events = POLLIN; 696141261Sdelphij 697141261Sdelphij while (pfd[0].fd != -1) { 698141261Sdelphij if (iflag) 699141261Sdelphij sleep(iflag); 700141261Sdelphij 701141261Sdelphij if ((n = poll(pfd, 2 - dflag, timeout)) < 0) { 702141261Sdelphij close(nfd); 703141261Sdelphij err(1, "Polling Error"); 704141261Sdelphij } 705141261Sdelphij 706141261Sdelphij if (n == 0) 707141261Sdelphij return; 708141261Sdelphij 709141261Sdelphij if (pfd[0].revents & POLLIN) { 710158798Sdelphij if ((n = read(nfd, buf, plen)) < 0) 711141261Sdelphij return; 712141261Sdelphij else if (n == 0) { 713141261Sdelphij shutdown(nfd, SHUT_RD); 714141261Sdelphij pfd[0].fd = -1; 715141261Sdelphij pfd[0].events = 0; 716141261Sdelphij } else { 717141261Sdelphij if (tflag) 718141261Sdelphij atelnet(nfd, buf, n); 719158798Sdelphij if (atomicio(vwrite, lfd, buf, n) != n) 720141261Sdelphij return; 721141261Sdelphij } 722141261Sdelphij } 723141261Sdelphij 724141261Sdelphij if (!dflag && pfd[1].revents & POLLIN) { 725206675Sdelphij if ((n = read(wfd, buf, plen)) < 0) 726141261Sdelphij return; 727206675Sdelphij else if (n == 0) { 728141261Sdelphij shutdown(nfd, SHUT_WR); 729141261Sdelphij pfd[1].fd = -1; 730141261Sdelphij pfd[1].events = 0; 731141261Sdelphij } else { 732158798Sdelphij if (atomicio(vwrite, nfd, buf, n) != n) 733141261Sdelphij return; 734141261Sdelphij } 735141261Sdelphij } 736141261Sdelphij } 737141261Sdelphij} 738141261Sdelphij 739141261Sdelphij/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */ 740141261Sdelphijvoid 741141261Sdelphijatelnet(int nfd, unsigned char *buf, unsigned int size) 742141261Sdelphij{ 743141261Sdelphij unsigned char *p, *end; 744141261Sdelphij unsigned char obuf[4]; 745141261Sdelphij 746205561Sdelphij if (size < 3) 747205561Sdelphij return; 748205561Sdelphij end = buf + size - 2; 749141261Sdelphij 750141261Sdelphij for (p = buf; p < end; p++) { 751141261Sdelphij if (*p != IAC) 752205561Sdelphij continue; 753141261Sdelphij 754141261Sdelphij obuf[0] = IAC; 755141261Sdelphij p++; 756141261Sdelphij if ((*p == WILL) || (*p == WONT)) 757141261Sdelphij obuf[1] = DONT; 758205561Sdelphij else if ((*p == DO) || (*p == DONT)) 759141261Sdelphij obuf[1] = WONT; 760205561Sdelphij else 761205561Sdelphij continue; 762205561Sdelphij 763205561Sdelphij p++; 764205561Sdelphij obuf[2] = *p; 765205561Sdelphij if (atomicio(vwrite, nfd, obuf, 3) != 3) 766205561Sdelphij warn("Write Error!"); 767141261Sdelphij } 768141261Sdelphij} 769141261Sdelphij 770141261Sdelphij/* 771141261Sdelphij * build_ports() 772141261Sdelphij * Build an array or ports in portlist[], listing each port 773141261Sdelphij * that we should try to connect to. 774141261Sdelphij */ 775141261Sdelphijvoid 776141261Sdelphijbuild_ports(char *p) 777141261Sdelphij{ 778167964Sdelphij const char *errstr; 779167964Sdelphij char *n; 780141261Sdelphij int hi, lo, cp; 781141261Sdelphij int x = 0; 782141261Sdelphij 783141261Sdelphij if ((n = strchr(p, '-')) != NULL) { 784141261Sdelphij if (lflag) 785141261Sdelphij errx(1, "Cannot use -l with multiple ports!"); 786141261Sdelphij 787141261Sdelphij *n = '\0'; 788141261Sdelphij n++; 789141261Sdelphij 790141261Sdelphij /* Make sure the ports are in order: lowest->highest. */ 791167964Sdelphij hi = strtonum(n, 1, PORT_MAX, &errstr); 792167964Sdelphij if (errstr) 793167964Sdelphij errx(1, "port number %s: %s", errstr, n); 794167964Sdelphij lo = strtonum(p, 1, PORT_MAX, &errstr); 795167964Sdelphij if (errstr) 796167964Sdelphij errx(1, "port number %s: %s", errstr, p); 797141261Sdelphij 798141261Sdelphij if (lo > hi) { 799141261Sdelphij cp = hi; 800141261Sdelphij hi = lo; 801141261Sdelphij lo = cp; 802141261Sdelphij } 803141261Sdelphij 804141261Sdelphij /* Load ports sequentially. */ 805141261Sdelphij for (cp = lo; cp <= hi; cp++) { 806141261Sdelphij portlist[x] = calloc(1, PORT_MAX_LEN); 807141261Sdelphij if (portlist[x] == NULL) 808141261Sdelphij err(1, NULL); 809141261Sdelphij snprintf(portlist[x], PORT_MAX_LEN, "%d", cp); 810141261Sdelphij x++; 811141261Sdelphij } 812141261Sdelphij 813141261Sdelphij /* Randomly swap ports. */ 814141261Sdelphij if (rflag) { 815141261Sdelphij int y; 816141261Sdelphij char *c; 817141261Sdelphij 818141261Sdelphij for (x = 0; x <= (hi - lo); x++) { 819141261Sdelphij y = (arc4random() & 0xFFFF) % (hi - lo); 820141261Sdelphij c = portlist[x]; 821141261Sdelphij portlist[x] = portlist[y]; 822141261Sdelphij portlist[y] = c; 823141261Sdelphij } 824141261Sdelphij } 825141261Sdelphij } else { 826167964Sdelphij hi = strtonum(p, 1, PORT_MAX, &errstr); 827167964Sdelphij if (errstr) 828167964Sdelphij errx(1, "port number %s: %s", errstr, p); 829214047Sdelphij portlist[0] = strdup(p); 830141261Sdelphij if (portlist[0] == NULL) 831141261Sdelphij err(1, NULL); 832141261Sdelphij } 833141261Sdelphij} 834141261Sdelphij 835141261Sdelphij/* 836141261Sdelphij * udptest() 837141261Sdelphij * Do a few writes to see if the UDP port is there. 838141261Sdelphij * XXX - Better way of doing this? Doesn't work for IPv6. 839141261Sdelphij * Also fails after around 100 ports checked. 840141261Sdelphij */ 841141261Sdelphijint 842141261Sdelphijudptest(int s) 843141261Sdelphij{ 844141261Sdelphij int i, ret; 845141261Sdelphij 846141261Sdelphij for (i = 0; i <= 3; i++) { 847141261Sdelphij if (write(s, "X", 1) == 1) 848141261Sdelphij ret = 1; 849141261Sdelphij else 850141261Sdelphij ret = -1; 851141261Sdelphij } 852141261Sdelphij return (ret); 853141261Sdelphij} 854141261Sdelphij 855141261Sdelphijvoid 856158798Sdelphijset_common_sockopts(int s) 857158798Sdelphij{ 858158798Sdelphij int x = 1; 859158798Sdelphij 860158798Sdelphij if (Sflag) { 861158798Sdelphij if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, 862158798Sdelphij &x, sizeof(x)) == -1) 863158798Sdelphij err(1, NULL); 864158798Sdelphij } 865158798Sdelphij if (Dflag) { 866158798Sdelphij if (setsockopt(s, SOL_SOCKET, SO_DEBUG, 867158798Sdelphij &x, sizeof(x)) == -1) 868158798Sdelphij err(1, NULL); 869158798Sdelphij } 870158798Sdelphij#ifdef SO_JUMBO 871158798Sdelphij if (jflag) { 872158798Sdelphij if (setsockopt(s, SOL_SOCKET, SO_JUMBO, 873158798Sdelphij &x, sizeof(x)) == -1) 874158798Sdelphij err(1, NULL); 875158798Sdelphij } 876158798Sdelphij#endif 877158798Sdelphij if (Tflag != -1) { 878158798Sdelphij if (setsockopt(s, IPPROTO_IP, IP_TOS, 879158798Sdelphij &Tflag, sizeof(Tflag)) == -1) 880158798Sdelphij err(1, "set IP ToS"); 881158798Sdelphij } 882186343Sdelphij if (Iflag) { 883186343Sdelphij if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 884186343Sdelphij &Iflag, sizeof(Iflag)) == -1) 885186343Sdelphij err(1, "set TCP receive buffer size"); 886186343Sdelphij } 887177837Sbms if (Oflag) { 888186343Sdelphij if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 889186343Sdelphij &Oflag, sizeof(Oflag)) == -1) 890186343Sdelphij err(1, "set TCP send buffer size"); 891186343Sdelphij } 892186343Sdelphij if (FreeBSD_Oflag) { 893177837Sbms if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT, 894186343Sdelphij &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1) 895177837Sbms err(1, "disable TCP options"); 896177837Sbms } 897158798Sdelphij} 898158798Sdelphij 899158798Sdelphijint 900158798Sdelphijparse_iptos(char *s) 901158798Sdelphij{ 902158798Sdelphij int tos = -1; 903158798Sdelphij 904158798Sdelphij if (strcmp(s, "lowdelay") == 0) 905158798Sdelphij return (IPTOS_LOWDELAY); 906158798Sdelphij if (strcmp(s, "throughput") == 0) 907158798Sdelphij return (IPTOS_THROUGHPUT); 908158798Sdelphij if (strcmp(s, "reliability") == 0) 909158798Sdelphij return (IPTOS_RELIABILITY); 910158798Sdelphij 911158798Sdelphij if (sscanf(s, "0x%x", &tos) != 1 || tos < 0 || tos > 0xff) 912158798Sdelphij errx(1, "invalid IP Type of Service"); 913158798Sdelphij return (tos); 914158798Sdelphij} 915158798Sdelphij 916158798Sdelphijvoid 917141261Sdelphijhelp(void) 918141261Sdelphij{ 919141261Sdelphij usage(0); 920141261Sdelphij fprintf(stderr, "\tCommand Summary:\n\ 921141261Sdelphij \t-4 Use IPv4\n\ 922178927Santoine \t-6 Use IPv6\n\ 923178927Santoine \t-D Enable the debug socket option\n\ 924178927Santoine \t-d Detach from stdin\n"); 925141394Sdelphij#ifdef IPSEC 926141394Sdelphij fprintf(stderr, "\ 927178927Santoine \t-E Use IPsec ESP\n\ 928178927Santoine \t-e policy Use specified IPsec policy\n"); 929141394Sdelphij#endif 930141394Sdelphij fprintf(stderr, "\ 931141261Sdelphij \t-h This help text\n\ 932186343Sdelphij \t-I length TCP receive buffer length\n\ 933141261Sdelphij \t-i secs\t Delay interval for lines sent, ports scanned\n\ 934141261Sdelphij \t-k Keep inbound sockets open for multiple connects\n\ 935141261Sdelphij \t-l Listen mode, for inbound connects\n\ 936141261Sdelphij \t-n Suppress name/port resolutions\n\ 937186343Sdelphij \t--no-tcpopt Disable TCP options\n\ 938186343Sdelphij \t-O length TCP send buffer length\n\ 939158798Sdelphij \t-P proxyuser\tUsername for proxy authentication\n\ 940141261Sdelphij \t-p port\t Specify local port for remote connects\n\ 941141261Sdelphij \t-r Randomize remote ports\n\ 942141261Sdelphij \t-S Enable the TCP MD5 signature option\n\ 943141261Sdelphij \t-s addr\t Local source address\n\ 944158798Sdelphij \t-T ToS\t Set IP Type of Service\n\ 945141261Sdelphij \t-t Answer TELNET negotiation\n\ 946141261Sdelphij \t-U Use UNIX domain socket\n\ 947141261Sdelphij \t-u UDP mode\n\ 948214047Sdelphij \t-V rtable Specify alternate routing table\n\ 949141261Sdelphij \t-v Verbose\n\ 950141261Sdelphij \t-w secs\t Timeout for connects and final net reads\n\ 951141261Sdelphij \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\ 952141261Sdelphij \t-x addr[:port]\tSpecify proxy address and port\n\ 953141261Sdelphij \t-z Zero-I/O mode [used for scanning]\n\ 954141261Sdelphij Port numbers can be individual or ranges: lo-hi [inclusive]\n"); 955141394Sdelphij#ifdef IPSEC 956141394Sdelphij fprintf(stderr, "See ipsec_set_policy(3) for -e argument format\n"); 957141394Sdelphij#endif 958141261Sdelphij exit(1); 959141261Sdelphij} 960141261Sdelphij 961141394Sdelphij#ifdef IPSEC 962141261Sdelphijvoid 963141394Sdelphijadd_ipsec_policy(int s, char *policy) 964141394Sdelphij{ 965141394Sdelphij char *raw; 966141394Sdelphij int e; 967141394Sdelphij 968141394Sdelphij raw = ipsec_set_policy(policy, strlen(policy)); 969141394Sdelphij if (raw == NULL) 970141394Sdelphij errx(1, "ipsec_set_policy `%s': %s", policy, 971141394Sdelphij ipsec_strerror()); 972141394Sdelphij e = setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, raw, 973141394Sdelphij ipsec_get_policylen(raw)); 974141394Sdelphij if (e < 0) 975141394Sdelphij err(1, "ipsec policy cannot be configured"); 976141394Sdelphij free(raw); 977141394Sdelphij if (vflag) 978141394Sdelphij fprintf(stderr, "ipsec policy configured: `%s'\n", policy); 979141394Sdelphij return; 980141394Sdelphij} 981141394Sdelphij#endif /* IPSEC */ 982141394Sdelphij 983141394Sdelphijvoid 984141261Sdelphijusage(int ret) 985141261Sdelphij{ 986193008Sdelphij fprintf(stderr, 987141394Sdelphij#ifdef IPSEC 988206675Sdelphij "usage: nc [-46DdEhklnrStUuvz] [-e policy] [-I length] [-i interval] [-O length]\n" 989141394Sdelphij#else 990206675Sdelphij "usage: nc [-46DdhklnrStUuvz] [-I length] [-i interval] [-O length]\n" 991141394Sdelphij#endif 992193008Sdelphij "\t [-P proxy_username] [-p source_port] [-s source_ip_address] [-T ToS]\n" 993214047Sdelphij "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n" 994202640Sdelphij "\t [-x proxy_address[:port]] [hostname] [port]\n"); 995141261Sdelphij if (ret) 996141261Sdelphij exit(1); 997141261Sdelphij} 998