netcat.c revision 141261
1141261Sdelphij/* $OpenBSD: netcat.c,v 1.76 2004/12/10 16:51:31 hshoexer 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. 27141261Sdelphij */ 28141261Sdelphij 29141261Sdelphij/* 30141261Sdelphij * Re-written nc(1) for OpenBSD. Original implementation by 31141261Sdelphij * *Hobbit* <hobbit@avian.org>. 32141261Sdelphij */ 33141261Sdelphij 34141261Sdelphij#include <sys/types.h> 35141261Sdelphij#include <sys/socket.h> 36141261Sdelphij#include <sys/time.h> 37141261Sdelphij#include <sys/un.h> 38141261Sdelphij 39141261Sdelphij#include <netinet/in.h> 40141261Sdelphij#include <netinet/tcp.h> 41141261Sdelphij#include <arpa/telnet.h> 42141261Sdelphij 43141261Sdelphij#include <err.h> 44141261Sdelphij#include <errno.h> 45141261Sdelphij#include <netdb.h> 46141261Sdelphij#include <poll.h> 47141261Sdelphij#include <stdarg.h> 48141261Sdelphij#include <stdio.h> 49141261Sdelphij#include <stdlib.h> 50141261Sdelphij#include <string.h> 51141261Sdelphij#include <unistd.h> 52141261Sdelphij#include <fcntl.h> 53141261Sdelphij 54141261Sdelphij#ifndef SUN_LEN 55141261Sdelphij#define SUN_LEN(su) \ 56141261Sdelphij (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) 57141261Sdelphij#endif 58141261Sdelphij 59141261Sdelphij#define PORT_MAX 65535 60141261Sdelphij#define PORT_MAX_LEN 6 61141261Sdelphij 62141261Sdelphij/* Command Line Options */ 63141261Sdelphijint dflag; /* detached, no stdin */ 64141261Sdelphijint iflag; /* Interval Flag */ 65141261Sdelphijint kflag; /* More than one connect */ 66141261Sdelphijint lflag; /* Bind to local port */ 67141261Sdelphijint nflag; /* Don't do name look up */ 68141261Sdelphijchar *pflag; /* Localport flag */ 69141261Sdelphijint rflag; /* Random ports flag */ 70141261Sdelphijchar *sflag; /* Source Address */ 71141261Sdelphijint tflag; /* Telnet Emulation */ 72141261Sdelphijint uflag; /* UDP - Default to TCP */ 73141261Sdelphijint vflag; /* Verbosity */ 74141261Sdelphijint xflag; /* Socks proxy */ 75141261Sdelphijint zflag; /* Port Scan Flag */ 76141261Sdelphijint Dflag; /* sodebug */ 77141261Sdelphijint Sflag; /* TCP MD5 signature option */ 78141261Sdelphij 79141261Sdelphijint timeout = -1; 80141261Sdelphijint family = AF_UNSPEC; 81141261Sdelphijchar *portlist[PORT_MAX+1]; 82141261Sdelphij 83141261Sdelphijssize_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t); 84141261Sdelphijvoid atelnet(int, unsigned char *, unsigned int); 85141261Sdelphijvoid build_ports(char *); 86141261Sdelphijvoid help(void); 87141261Sdelphijint local_listen(char *, char *, struct addrinfo); 88141261Sdelphijvoid readwrite(int); 89141261Sdelphijint remote_connect(char *, char *, struct addrinfo); 90141261Sdelphijint socks_connect(char *, char *, struct addrinfo, char *, char *, 91141261Sdelphij struct addrinfo, int); 92141261Sdelphijint udptest(int); 93141261Sdelphijint unix_connect(char *); 94141261Sdelphijint unix_listen(char *); 95141261Sdelphijvoid usage(int); 96141261Sdelphij 97141261Sdelphijint 98141261Sdelphijmain(int argc, char *argv[]) 99141261Sdelphij{ 100141261Sdelphij int ch, s, ret, socksv; 101141261Sdelphij char *host, *uport, *endp; 102141261Sdelphij struct addrinfo hints; 103141261Sdelphij struct servent *sv; 104141261Sdelphij socklen_t len; 105141261Sdelphij struct sockaddr_storage cliaddr; 106141261Sdelphij char *proxy; 107141261Sdelphij char *proxyhost = "", *proxyport = NULL; 108141261Sdelphij struct addrinfo proxyhints; 109141261Sdelphij 110141261Sdelphij ret = 1; 111141261Sdelphij s = 0; 112141261Sdelphij socksv = 5; 113141261Sdelphij host = NULL; 114141261Sdelphij uport = NULL; 115141261Sdelphij endp = NULL; 116141261Sdelphij sv = NULL; 117141261Sdelphij 118141261Sdelphij while ((ch = getopt(argc, argv, "46Ddhi:klnp:rSs:tUuvw:X:x:z")) != -1) { 119141261Sdelphij switch (ch) { 120141261Sdelphij case '4': 121141261Sdelphij family = AF_INET; 122141261Sdelphij break; 123141261Sdelphij case '6': 124141261Sdelphij family = AF_INET6; 125141261Sdelphij break; 126141261Sdelphij case 'U': 127141261Sdelphij family = AF_UNIX; 128141261Sdelphij break; 129141261Sdelphij case 'X': 130141261Sdelphij if (strcasecmp(optarg, "connect") == 0) 131141261Sdelphij socksv = -1; /* HTTP proxy CONNECT */ 132141261Sdelphij else if (strcmp(optarg, "4") == 0) 133141261Sdelphij socksv = 4; /* SOCKS v.4 */ 134141261Sdelphij else if (strcmp(optarg, "5") == 0) 135141261Sdelphij socksv = 5; /* SOCKS v.5 */ 136141261Sdelphij else 137141261Sdelphij errx(1, "unsupported proxy protocol"); 138141261Sdelphij break; 139141261Sdelphij case 'd': 140141261Sdelphij dflag = 1; 141141261Sdelphij break; 142141261Sdelphij case 'h': 143141261Sdelphij help(); 144141261Sdelphij break; 145141261Sdelphij case 'i': 146141261Sdelphij iflag = (int)strtoul(optarg, &endp, 10); 147141261Sdelphij if (iflag < 0 || *endp != '\0') 148141261Sdelphij errx(1, "interval cannot be negative"); 149141261Sdelphij break; 150141261Sdelphij case 'k': 151141261Sdelphij kflag = 1; 152141261Sdelphij break; 153141261Sdelphij case 'l': 154141261Sdelphij lflag = 1; 155141261Sdelphij break; 156141261Sdelphij case 'n': 157141261Sdelphij nflag = 1; 158141261Sdelphij break; 159141261Sdelphij case 'p': 160141261Sdelphij pflag = optarg; 161141261Sdelphij break; 162141261Sdelphij case 'r': 163141261Sdelphij rflag = 1; 164141261Sdelphij break; 165141261Sdelphij case 's': 166141261Sdelphij sflag = optarg; 167141261Sdelphij break; 168141261Sdelphij case 't': 169141261Sdelphij tflag = 1; 170141261Sdelphij break; 171141261Sdelphij case 'u': 172141261Sdelphij uflag = 1; 173141261Sdelphij break; 174141261Sdelphij case 'v': 175141261Sdelphij vflag = 1; 176141261Sdelphij break; 177141261Sdelphij case 'w': 178141261Sdelphij timeout = (int)strtoul(optarg, &endp, 10); 179141261Sdelphij if (timeout < 0 || *endp != '\0') 180141261Sdelphij errx(1, "timeout cannot be negative"); 181141261Sdelphij if (timeout >= (INT_MAX / 1000)) 182141261Sdelphij errx(1, "timeout too large"); 183141261Sdelphij timeout *= 1000; 184141261Sdelphij break; 185141261Sdelphij case 'x': 186141261Sdelphij xflag = 1; 187141261Sdelphij if ((proxy = strdup(optarg)) == NULL) 188141261Sdelphij err(1, NULL); 189141261Sdelphij break; 190141261Sdelphij case 'z': 191141261Sdelphij zflag = 1; 192141261Sdelphij break; 193141261Sdelphij case 'D': 194141261Sdelphij Dflag = 1; 195141261Sdelphij break; 196141261Sdelphij case 'S': 197141261Sdelphij Sflag = 1; 198141261Sdelphij break; 199141261Sdelphij default: 200141261Sdelphij usage(1); 201141261Sdelphij } 202141261Sdelphij } 203141261Sdelphij argc -= optind; 204141261Sdelphij argv += optind; 205141261Sdelphij 206141261Sdelphij /* Cruft to make sure options are clean, and used properly. */ 207141261Sdelphij if (argv[0] && !argv[1] && family == AF_UNIX) { 208141261Sdelphij if (uflag) 209141261Sdelphij errx(1, "cannot use -u and -U"); 210141261Sdelphij host = argv[0]; 211141261Sdelphij uport = NULL; 212141261Sdelphij } else if (argv[0] && !argv[1]) { 213141261Sdelphij if (!lflag) 214141261Sdelphij usage(1); 215141261Sdelphij uport = argv[0]; 216141261Sdelphij host = NULL; 217141261Sdelphij } else if (argv[0] && argv[1]) { 218141261Sdelphij host = argv[0]; 219141261Sdelphij uport = argv[1]; 220141261Sdelphij } else 221141261Sdelphij usage(1); 222141261Sdelphij 223141261Sdelphij if (lflag && sflag) 224141261Sdelphij errx(1, "cannot use -s and -l"); 225141261Sdelphij if (lflag && pflag) 226141261Sdelphij errx(1, "cannot use -p and -l"); 227141261Sdelphij if (lflag && zflag) 228141261Sdelphij errx(1, "cannot use -z and -l"); 229141261Sdelphij if (!lflag && kflag) 230141261Sdelphij errx(1, "must use -l with -k"); 231141261Sdelphij 232141261Sdelphij /* Initialize addrinfo structure. */ 233141261Sdelphij if (family != AF_UNIX) { 234141261Sdelphij memset(&hints, 0, sizeof(struct addrinfo)); 235141261Sdelphij hints.ai_family = family; 236141261Sdelphij hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; 237141261Sdelphij hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; 238141261Sdelphij if (nflag) 239141261Sdelphij hints.ai_flags |= AI_NUMERICHOST; 240141261Sdelphij } 241141261Sdelphij 242141261Sdelphij if (xflag) { 243141261Sdelphij if (uflag) 244141261Sdelphij errx(1, "no proxy support for UDP mode"); 245141261Sdelphij 246141261Sdelphij if (lflag) 247141261Sdelphij errx(1, "no proxy support for listen"); 248141261Sdelphij 249141261Sdelphij if (family == AF_UNIX) 250141261Sdelphij errx(1, "no proxy support for unix sockets"); 251141261Sdelphij 252141261Sdelphij /* XXX IPv6 transport to proxy would probably work */ 253141261Sdelphij if (family == AF_INET6) 254141261Sdelphij errx(1, "no proxy support for IPv6"); 255141261Sdelphij 256141261Sdelphij if (sflag) 257141261Sdelphij errx(1, "no proxy support for local source address"); 258141261Sdelphij 259141261Sdelphij proxyhost = strsep(&proxy, ":"); 260141261Sdelphij proxyport = proxy; 261141261Sdelphij 262141261Sdelphij memset(&proxyhints, 0, sizeof(struct addrinfo)); 263141261Sdelphij proxyhints.ai_family = family; 264141261Sdelphij proxyhints.ai_socktype = SOCK_STREAM; 265141261Sdelphij proxyhints.ai_protocol = IPPROTO_TCP; 266141261Sdelphij if (nflag) 267141261Sdelphij proxyhints.ai_flags |= AI_NUMERICHOST; 268141261Sdelphij } 269141261Sdelphij 270141261Sdelphij if (lflag) { 271141261Sdelphij int connfd; 272141261Sdelphij ret = 0; 273141261Sdelphij 274141261Sdelphij if (family == AF_UNIX) 275141261Sdelphij s = unix_listen(host); 276141261Sdelphij 277141261Sdelphij /* Allow only one connection at a time, but stay alive. */ 278141261Sdelphij for (;;) { 279141261Sdelphij if (family != AF_UNIX) 280141261Sdelphij s = local_listen(host, uport, hints); 281141261Sdelphij if (s < 0) 282141261Sdelphij err(1, NULL); 283141261Sdelphij /* 284141261Sdelphij * For UDP, we will use recvfrom() initially 285141261Sdelphij * to wait for a caller, then use the regular 286141261Sdelphij * functions to talk to the caller. 287141261Sdelphij */ 288141261Sdelphij if (uflag) { 289141261Sdelphij int rv; 290141261Sdelphij char buf[1024]; 291141261Sdelphij struct sockaddr_storage z; 292141261Sdelphij 293141261Sdelphij len = sizeof(z); 294141261Sdelphij rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK, 295141261Sdelphij (struct sockaddr *)&z, &len); 296141261Sdelphij if (rv < 0) 297141261Sdelphij err(1, "recvfrom"); 298141261Sdelphij 299141261Sdelphij rv = connect(s, (struct sockaddr *)&z, len); 300141261Sdelphij if (rv < 0) 301141261Sdelphij err(1, "connect"); 302141261Sdelphij 303141261Sdelphij connfd = s; 304141261Sdelphij } else { 305141261Sdelphij connfd = accept(s, (struct sockaddr *)&cliaddr, 306141261Sdelphij &len); 307141261Sdelphij } 308141261Sdelphij 309141261Sdelphij readwrite(connfd); 310141261Sdelphij close(connfd); 311141261Sdelphij if (family != AF_UNIX) 312141261Sdelphij close(s); 313141261Sdelphij 314141261Sdelphij if (!kflag) 315141261Sdelphij break; 316141261Sdelphij } 317141261Sdelphij } else if (family == AF_UNIX) { 318141261Sdelphij ret = 0; 319141261Sdelphij 320141261Sdelphij if ((s = unix_connect(host)) > 0 && !zflag) { 321141261Sdelphij readwrite(s); 322141261Sdelphij close(s); 323141261Sdelphij } else 324141261Sdelphij ret = 1; 325141261Sdelphij 326141261Sdelphij exit(ret); 327141261Sdelphij 328141261Sdelphij } else { 329141261Sdelphij int i = 0; 330141261Sdelphij 331141261Sdelphij /* Construct the portlist[] array. */ 332141261Sdelphij build_ports(uport); 333141261Sdelphij 334141261Sdelphij /* Cycle through portlist, connecting to each port. */ 335141261Sdelphij for (i = 0; portlist[i] != NULL; i++) { 336141261Sdelphij if (s) 337141261Sdelphij close(s); 338141261Sdelphij 339141261Sdelphij if (xflag) 340141261Sdelphij s = socks_connect(host, portlist[i], hints, 341141261Sdelphij proxyhost, proxyport, proxyhints, socksv); 342141261Sdelphij else 343141261Sdelphij s = remote_connect(host, portlist[i], hints); 344141261Sdelphij 345141261Sdelphij if (s < 0) 346141261Sdelphij continue; 347141261Sdelphij 348141261Sdelphij ret = 0; 349141261Sdelphij if (vflag || zflag) { 350141261Sdelphij /* For UDP, make sure we are connected. */ 351141261Sdelphij if (uflag) { 352141261Sdelphij if (udptest(s) == -1) { 353141261Sdelphij ret = 1; 354141261Sdelphij continue; 355141261Sdelphij } 356141261Sdelphij } 357141261Sdelphij 358141261Sdelphij /* Don't look up port if -n. */ 359141261Sdelphij if (nflag) 360141261Sdelphij sv = NULL; 361141261Sdelphij else { 362141261Sdelphij sv = getservbyport( 363141261Sdelphij ntohs(atoi(portlist[i])), 364141261Sdelphij uflag ? "udp" : "tcp"); 365141261Sdelphij } 366141261Sdelphij 367141261Sdelphij printf("Connection to %s %s port [%s/%s] succeeded!\n", 368141261Sdelphij host, portlist[i], uflag ? "udp" : "tcp", 369141261Sdelphij sv ? sv->s_name : "*"); 370141261Sdelphij } 371141261Sdelphij if (!zflag) 372141261Sdelphij readwrite(s); 373141261Sdelphij } 374141261Sdelphij } 375141261Sdelphij 376141261Sdelphij if (s) 377141261Sdelphij close(s); 378141261Sdelphij 379141261Sdelphij exit(ret); 380141261Sdelphij} 381141261Sdelphij 382141261Sdelphij/* 383141261Sdelphij * unix_connect() 384141261Sdelphij * Returns a socket connected to a local unix socket. Returns -1 on failure. 385141261Sdelphij */ 386141261Sdelphijint 387141261Sdelphijunix_connect(char *path) 388141261Sdelphij{ 389141261Sdelphij struct sockaddr_un sun; 390141261Sdelphij int s; 391141261Sdelphij 392141261Sdelphij if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 393141261Sdelphij return (-1); 394141261Sdelphij (void)fcntl(s, F_SETFD, 1); 395141261Sdelphij 396141261Sdelphij memset(&sun, 0, sizeof(struct sockaddr_un)); 397141261Sdelphij sun.sun_family = AF_UNIX; 398141261Sdelphij 399141261Sdelphij if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= 400141261Sdelphij sizeof(sun.sun_path)) { 401141261Sdelphij close(s); 402141261Sdelphij errno = ENAMETOOLONG; 403141261Sdelphij return (-1); 404141261Sdelphij } 405141261Sdelphij if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { 406141261Sdelphij close(s); 407141261Sdelphij return (-1); 408141261Sdelphij } 409141261Sdelphij return (s); 410141261Sdelphij 411141261Sdelphij} 412141261Sdelphij 413141261Sdelphij/* 414141261Sdelphij * unix_listen() 415141261Sdelphij * Create a unix domain socket, and listen on it. 416141261Sdelphij */ 417141261Sdelphijint 418141261Sdelphijunix_listen(char *path) 419141261Sdelphij{ 420141261Sdelphij struct sockaddr_un sun; 421141261Sdelphij int s; 422141261Sdelphij 423141261Sdelphij /* Create unix domain socket. */ 424141261Sdelphij if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 425141261Sdelphij return (-1); 426141261Sdelphij 427141261Sdelphij memset(&sun, 0, sizeof(struct sockaddr_un)); 428141261Sdelphij sun.sun_family = AF_UNIX; 429141261Sdelphij 430141261Sdelphij if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= 431141261Sdelphij sizeof(sun.sun_path)) { 432141261Sdelphij close(s); 433141261Sdelphij errno = ENAMETOOLONG; 434141261Sdelphij return (-1); 435141261Sdelphij } 436141261Sdelphij 437141261Sdelphij if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { 438141261Sdelphij close(s); 439141261Sdelphij return (-1); 440141261Sdelphij } 441141261Sdelphij 442141261Sdelphij if (listen(s, 5) < 0) { 443141261Sdelphij close(s); 444141261Sdelphij return (-1); 445141261Sdelphij } 446141261Sdelphij return (s); 447141261Sdelphij} 448141261Sdelphij 449141261Sdelphij/* 450141261Sdelphij * remote_connect() 451141261Sdelphij * Returns a socket connected to a remote host. Properly binds to a local 452141261Sdelphij * port or source address if needed. Returns -1 on failure. 453141261Sdelphij */ 454141261Sdelphijint 455141261Sdelphijremote_connect(char *host, char *port, struct addrinfo hints) 456141261Sdelphij{ 457141261Sdelphij struct addrinfo *res, *res0; 458141261Sdelphij int s, error, x = 1; 459141261Sdelphij 460141261Sdelphij if ((error = getaddrinfo(host, port, &hints, &res))) 461141261Sdelphij errx(1, "getaddrinfo: %s", gai_strerror(error)); 462141261Sdelphij 463141261Sdelphij res0 = res; 464141261Sdelphij do { 465141261Sdelphij if ((s = socket(res0->ai_family, res0->ai_socktype, 466141261Sdelphij res0->ai_protocol)) < 0) 467141261Sdelphij continue; 468141261Sdelphij 469141261Sdelphij /* Bind to a local port or source address if specified. */ 470141261Sdelphij if (sflag || pflag) { 471141261Sdelphij struct addrinfo ahints, *ares; 472141261Sdelphij 473141261Sdelphij if (!(sflag && pflag)) { 474141261Sdelphij if (!sflag) 475141261Sdelphij sflag = NULL; 476141261Sdelphij else 477141261Sdelphij pflag = NULL; 478141261Sdelphij } 479141261Sdelphij 480141261Sdelphij memset(&ahints, 0, sizeof(struct addrinfo)); 481141261Sdelphij ahints.ai_family = res0->ai_family; 482141261Sdelphij ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; 483141261Sdelphij ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; 484141261Sdelphij ahints.ai_flags = AI_PASSIVE; 485141261Sdelphij if ((error = getaddrinfo(sflag, pflag, &ahints, &ares))) 486141261Sdelphij errx(1, "getaddrinfo: %s", gai_strerror(error)); 487141261Sdelphij 488141261Sdelphij if (bind(s, (struct sockaddr *)ares->ai_addr, 489141261Sdelphij ares->ai_addrlen) < 0) 490141261Sdelphij errx(1, "bind failed: %s", strerror(errno)); 491141261Sdelphij freeaddrinfo(ares); 492141261Sdelphij } 493141261Sdelphij if (Sflag) { 494141261Sdelphij if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, 495141261Sdelphij &x, sizeof(x)) == -1) 496141261Sdelphij err(1, NULL); 497141261Sdelphij } 498141261Sdelphij if (Dflag) { 499141261Sdelphij if (setsockopt(s, SOL_SOCKET, SO_DEBUG, 500141261Sdelphij &x, sizeof(x)) == -1) 501141261Sdelphij err(1, NULL); 502141261Sdelphij } 503141261Sdelphij 504141261Sdelphij if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0) 505141261Sdelphij break; 506141261Sdelphij else if (vflag) 507141261Sdelphij warn("connect to %s port %s (%s) failed", host, port, 508141261Sdelphij uflag ? "udp" : "tcp"); 509141261Sdelphij 510141261Sdelphij close(s); 511141261Sdelphij s = -1; 512141261Sdelphij } while ((res0 = res0->ai_next) != NULL); 513141261Sdelphij 514141261Sdelphij freeaddrinfo(res); 515141261Sdelphij 516141261Sdelphij return (s); 517141261Sdelphij} 518141261Sdelphij 519141261Sdelphij/* 520141261Sdelphij * local_listen() 521141261Sdelphij * Returns a socket listening on a local port, binds to specified source 522141261Sdelphij * address. Returns -1 on failure. 523141261Sdelphij */ 524141261Sdelphijint 525141261Sdelphijlocal_listen(char *host, char *port, struct addrinfo hints) 526141261Sdelphij{ 527141261Sdelphij struct addrinfo *res, *res0; 528141261Sdelphij int s, ret, x = 1; 529141261Sdelphij int error; 530141261Sdelphij 531141261Sdelphij /* Allow nodename to be null. */ 532141261Sdelphij hints.ai_flags |= AI_PASSIVE; 533141261Sdelphij 534141261Sdelphij /* 535141261Sdelphij * In the case of binding to a wildcard address 536141261Sdelphij * default to binding to an ipv4 address. 537141261Sdelphij */ 538141261Sdelphij if (host == NULL && hints.ai_family == AF_UNSPEC) 539141261Sdelphij hints.ai_family = AF_INET; 540141261Sdelphij 541141261Sdelphij if ((error = getaddrinfo(host, port, &hints, &res))) 542141261Sdelphij errx(1, "getaddrinfo: %s", gai_strerror(error)); 543141261Sdelphij 544141261Sdelphij res0 = res; 545141261Sdelphij do { 546141261Sdelphij if ((s = socket(res0->ai_family, res0->ai_socktype, 547141261Sdelphij res0->ai_protocol)) == 0) 548141261Sdelphij continue; 549141261Sdelphij 550141261Sdelphij ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x)); 551141261Sdelphij if (ret == -1) 552141261Sdelphij err(1, NULL); 553141261Sdelphij if (Sflag) { 554141261Sdelphij ret = setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, 555141261Sdelphij &x, sizeof(x)); 556141261Sdelphij if (ret == -1) 557141261Sdelphij err(1, NULL); 558141261Sdelphij } 559141261Sdelphij if (Dflag) { 560141261Sdelphij if (setsockopt(s, SOL_SOCKET, SO_DEBUG, 561141261Sdelphij &x, sizeof(x)) == -1) 562141261Sdelphij err(1, NULL); 563141261Sdelphij } 564141261Sdelphij 565141261Sdelphij if (bind(s, (struct sockaddr *)res0->ai_addr, 566141261Sdelphij res0->ai_addrlen) == 0) 567141261Sdelphij break; 568141261Sdelphij 569141261Sdelphij close(s); 570141261Sdelphij s = -1; 571141261Sdelphij } while ((res0 = res0->ai_next) != NULL); 572141261Sdelphij 573141261Sdelphij if (!uflag && s != -1) { 574141261Sdelphij if (listen(s, 1) < 0) 575141261Sdelphij err(1, "listen"); 576141261Sdelphij } 577141261Sdelphij 578141261Sdelphij freeaddrinfo(res); 579141261Sdelphij 580141261Sdelphij return (s); 581141261Sdelphij} 582141261Sdelphij 583141261Sdelphij/* 584141261Sdelphij * readwrite() 585141261Sdelphij * Loop that polls on the network file descriptor and stdin. 586141261Sdelphij */ 587141261Sdelphijvoid 588141261Sdelphijreadwrite(int nfd) 589141261Sdelphij{ 590141261Sdelphij struct pollfd pfd[2]; 591141261Sdelphij unsigned char buf[BUFSIZ]; 592141261Sdelphij int wfd = fileno(stdin), n; 593141261Sdelphij int lfd = fileno(stdout); 594141261Sdelphij 595141261Sdelphij /* Setup Network FD */ 596141261Sdelphij pfd[0].fd = nfd; 597141261Sdelphij pfd[0].events = POLLIN; 598141261Sdelphij 599141261Sdelphij /* Set up STDIN FD. */ 600141261Sdelphij pfd[1].fd = wfd; 601141261Sdelphij pfd[1].events = POLLIN; 602141261Sdelphij 603141261Sdelphij while (pfd[0].fd != -1) { 604141261Sdelphij if (iflag) 605141261Sdelphij sleep(iflag); 606141261Sdelphij 607141261Sdelphij if ((n = poll(pfd, 2 - dflag, timeout)) < 0) { 608141261Sdelphij close(nfd); 609141261Sdelphij err(1, "Polling Error"); 610141261Sdelphij } 611141261Sdelphij 612141261Sdelphij if (n == 0) 613141261Sdelphij return; 614141261Sdelphij 615141261Sdelphij if (pfd[0].revents & POLLIN) { 616141261Sdelphij if ((n = read(nfd, buf, sizeof(buf))) < 0) 617141261Sdelphij return; 618141261Sdelphij else if (n == 0) { 619141261Sdelphij shutdown(nfd, SHUT_RD); 620141261Sdelphij pfd[0].fd = -1; 621141261Sdelphij pfd[0].events = 0; 622141261Sdelphij } else { 623141261Sdelphij if (tflag) 624141261Sdelphij atelnet(nfd, buf, n); 625141261Sdelphij if (atomicio((ssize_t (*)(int, void *, size_t))write, 626141261Sdelphij lfd, buf, n) != n) 627141261Sdelphij return; 628141261Sdelphij } 629141261Sdelphij } 630141261Sdelphij 631141261Sdelphij if (!dflag && pfd[1].revents & POLLIN) { 632141261Sdelphij if ((n = read(wfd, buf, sizeof(buf))) < 0) 633141261Sdelphij return; 634141261Sdelphij else if (n == 0) { 635141261Sdelphij shutdown(nfd, SHUT_WR); 636141261Sdelphij pfd[1].fd = -1; 637141261Sdelphij pfd[1].events = 0; 638141261Sdelphij } else { 639141261Sdelphij if (atomicio((ssize_t (*)(int, void *, size_t))write, 640141261Sdelphij nfd, buf, n) != n) 641141261Sdelphij return; 642141261Sdelphij } 643141261Sdelphij } 644141261Sdelphij } 645141261Sdelphij} 646141261Sdelphij 647141261Sdelphij/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */ 648141261Sdelphijvoid 649141261Sdelphijatelnet(int nfd, unsigned char *buf, unsigned int size) 650141261Sdelphij{ 651141261Sdelphij unsigned char *p, *end; 652141261Sdelphij unsigned char obuf[4]; 653141261Sdelphij 654141261Sdelphij end = buf + size; 655141261Sdelphij obuf[0] = '\0'; 656141261Sdelphij 657141261Sdelphij for (p = buf; p < end; p++) { 658141261Sdelphij if (*p != IAC) 659141261Sdelphij break; 660141261Sdelphij 661141261Sdelphij obuf[0] = IAC; 662141261Sdelphij p++; 663141261Sdelphij if ((*p == WILL) || (*p == WONT)) 664141261Sdelphij obuf[1] = DONT; 665141261Sdelphij if ((*p == DO) || (*p == DONT)) 666141261Sdelphij obuf[1] = WONT; 667141261Sdelphij if (obuf) { 668141261Sdelphij p++; 669141261Sdelphij obuf[2] = *p; 670141261Sdelphij obuf[3] = '\0'; 671141261Sdelphij if (atomicio((ssize_t (*)(int, void *, size_t))write, 672141261Sdelphij nfd, obuf, 3) != 3) 673141261Sdelphij warnx("Write Error!"); 674141261Sdelphij obuf[0] = '\0'; 675141261Sdelphij } 676141261Sdelphij } 677141261Sdelphij} 678141261Sdelphij 679141261Sdelphij/* 680141261Sdelphij * build_ports() 681141261Sdelphij * Build an array or ports in portlist[], listing each port 682141261Sdelphij * that we should try to connect to. 683141261Sdelphij */ 684141261Sdelphijvoid 685141261Sdelphijbuild_ports(char *p) 686141261Sdelphij{ 687141261Sdelphij char *n, *endp; 688141261Sdelphij int hi, lo, cp; 689141261Sdelphij int x = 0; 690141261Sdelphij 691141261Sdelphij if ((n = strchr(p, '-')) != NULL) { 692141261Sdelphij if (lflag) 693141261Sdelphij errx(1, "Cannot use -l with multiple ports!"); 694141261Sdelphij 695141261Sdelphij *n = '\0'; 696141261Sdelphij n++; 697141261Sdelphij 698141261Sdelphij /* Make sure the ports are in order: lowest->highest. */ 699141261Sdelphij hi = (int)strtoul(n, &endp, 10); 700141261Sdelphij if (hi <= 0 || hi > PORT_MAX || *endp != '\0') 701141261Sdelphij errx(1, "port range not valid"); 702141261Sdelphij lo = (int)strtoul(p, &endp, 10); 703141261Sdelphij if (lo <= 0 || lo > PORT_MAX || *endp != '\0') 704141261Sdelphij errx(1, "port range not valid"); 705141261Sdelphij 706141261Sdelphij if (lo > hi) { 707141261Sdelphij cp = hi; 708141261Sdelphij hi = lo; 709141261Sdelphij lo = cp; 710141261Sdelphij } 711141261Sdelphij 712141261Sdelphij /* Load ports sequentially. */ 713141261Sdelphij for (cp = lo; cp <= hi; cp++) { 714141261Sdelphij portlist[x] = calloc(1, PORT_MAX_LEN); 715141261Sdelphij if (portlist[x] == NULL) 716141261Sdelphij err(1, NULL); 717141261Sdelphij snprintf(portlist[x], PORT_MAX_LEN, "%d", cp); 718141261Sdelphij x++; 719141261Sdelphij } 720141261Sdelphij 721141261Sdelphij /* Randomly swap ports. */ 722141261Sdelphij if (rflag) { 723141261Sdelphij int y; 724141261Sdelphij char *c; 725141261Sdelphij 726141261Sdelphij for (x = 0; x <= (hi - lo); x++) { 727141261Sdelphij y = (arc4random() & 0xFFFF) % (hi - lo); 728141261Sdelphij c = portlist[x]; 729141261Sdelphij portlist[x] = portlist[y]; 730141261Sdelphij portlist[y] = c; 731141261Sdelphij } 732141261Sdelphij } 733141261Sdelphij } else { 734141261Sdelphij hi = (int)strtoul(p, &endp, 10); 735141261Sdelphij if (hi <= 0 || hi > PORT_MAX || *endp != '\0') 736141261Sdelphij errx(1, "port range not valid"); 737141261Sdelphij portlist[0] = calloc(1, PORT_MAX_LEN); 738141261Sdelphij if (portlist[0] == NULL) 739141261Sdelphij err(1, NULL); 740141261Sdelphij portlist[0] = p; 741141261Sdelphij } 742141261Sdelphij} 743141261Sdelphij 744141261Sdelphij/* 745141261Sdelphij * udptest() 746141261Sdelphij * Do a few writes to see if the UDP port is there. 747141261Sdelphij * XXX - Better way of doing this? Doesn't work for IPv6. 748141261Sdelphij * Also fails after around 100 ports checked. 749141261Sdelphij */ 750141261Sdelphijint 751141261Sdelphijudptest(int s) 752141261Sdelphij{ 753141261Sdelphij int i, ret; 754141261Sdelphij 755141261Sdelphij for (i = 0; i <= 3; i++) { 756141261Sdelphij if (write(s, "X", 1) == 1) 757141261Sdelphij ret = 1; 758141261Sdelphij else 759141261Sdelphij ret = -1; 760141261Sdelphij } 761141261Sdelphij return (ret); 762141261Sdelphij} 763141261Sdelphij 764141261Sdelphijvoid 765141261Sdelphijhelp(void) 766141261Sdelphij{ 767141261Sdelphij usage(0); 768141261Sdelphij fprintf(stderr, "\tCommand Summary:\n\ 769141261Sdelphij \t-4 Use IPv4\n\ 770141261Sdelphij \t-6 Use IPv6\n\ 771141261Sdelphij \t-D Enable the debug socket option\n\ 772141261Sdelphij \t-d Detach from stdin\n\ 773141261Sdelphij \t-h This help text\n\ 774141261Sdelphij \t-i secs\t Delay interval for lines sent, ports scanned\n\ 775141261Sdelphij \t-k Keep inbound sockets open for multiple connects\n\ 776141261Sdelphij \t-l Listen mode, for inbound connects\n\ 777141261Sdelphij \t-n Suppress name/port resolutions\n\ 778141261Sdelphij \t-p port\t Specify local port for remote connects\n\ 779141261Sdelphij \t-r Randomize remote ports\n\ 780141261Sdelphij \t-S Enable the TCP MD5 signature option\n\ 781141261Sdelphij \t-s addr\t Local source address\n\ 782141261Sdelphij \t-t Answer TELNET negotiation\n\ 783141261Sdelphij \t-U Use UNIX domain socket\n\ 784141261Sdelphij \t-u UDP mode\n\ 785141261Sdelphij \t-v Verbose\n\ 786141261Sdelphij \t-w secs\t Timeout for connects and final net reads\n\ 787141261Sdelphij \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\ 788141261Sdelphij \t-x addr[:port]\tSpecify proxy address and port\n\ 789141261Sdelphij \t-z Zero-I/O mode [used for scanning]\n\ 790141261Sdelphij Port numbers can be individual or ranges: lo-hi [inclusive]\n"); 791141261Sdelphij exit(1); 792141261Sdelphij} 793141261Sdelphij 794141261Sdelphijvoid 795141261Sdelphijusage(int ret) 796141261Sdelphij{ 797141261Sdelphij fprintf(stderr, "usage: nc [-46DdhklnrStUuvz] [-i interval] [-p source_port]\n"); 798141261Sdelphij fprintf(stderr, "\t [-s source_ip_address] [-w timeout] [-X proxy_version]\n"); 799141261Sdelphij fprintf(stderr, "\t [-x proxy_address[:port]] [hostname] [port[s]]\n"); 800141261Sdelphij if (ret) 801141261Sdelphij exit(1); 802141261Sdelphij} 803