03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/* $OpenBSD: netcat.c,v 1.89 2007/02/20 14:11:17 jmc Exp $ */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk *
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * Redistribution and use in source and binary forms, with or without
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * modification, are permitted provided that the following conditions
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * are met:
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk *
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * 1. Redistributions of source code must retain the above copyright
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * notice, this list of conditions and the following disclaimer.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * 2. Redistributions in binary form must reproduce the above copyright
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * notice, this list of conditions and the following disclaimer in the
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * documentation and/or other materials provided with the distribution.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * 3. The name of the author may not be used to endorse or promote products
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * derived from this software without specific prior written permission.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk *
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * Re-written nc(1) for OpenBSD. Original implementation by
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * *Hobbit* <hobbit@avian.org>.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk/*
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk * Use is subject to license terms.
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk */
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke/*
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke * Portions Copyright 2008 Erik Trauschke
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <sys/types.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <sys/socket.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <sys/time.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <sys/un.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <netinet/in.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <netinet/in_systm.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <netinet/tcp.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <netinet/ip.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <arpa/telnet.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <err.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <errno.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <netdb.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <poll.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <stdarg.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <stdio.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <stdlib.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <string.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <unistd.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <fcntl.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <limits.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include <signal.h>
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include "atomicio.h"
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#include "strtonum.h"
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#ifndef SUN_LEN
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#define SUN_LEN(su) \
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (sizeof (*(su)) - sizeof ((su)->sun_path) + strlen((su)->sun_path))
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#endif
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#define PORT_MIN 1
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#define PORT_MAX 65535
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk#define PORT_MAX_LEN 6
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke#define PLIST_SZ 32 /* initial capacity of the portlist */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/* Command Line Options */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint dflag; /* detached, no stdin */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkunsigned int iflag; /* Interval Flag */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint kflag; /* More than one connect */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint lflag; /* Bind to local port */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint nflag; /* Don't do name lookup */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkchar *Pflag; /* Proxy username */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkchar *pflag; /* Localport flag */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint rflag; /* Random ports flag */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkchar *sflag; /* Source Address */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint tflag; /* Telnet Emulation */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint uflag; /* UDP - Default to TCP */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint vflag; /* Verbosity */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint xflag; /* Socks proxy */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint Xflag; /* indicator of Socks version set */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint zflag; /* Port Scan Flag */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint Dflag; /* sodebug */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint Tflag = -1; /* IP Type of Service */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint timeout = -1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint family = AF_UNSPEC;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke/*
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke * portlist structure
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke * Used to store a list of ports given by the user and maintaining
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke * information about the number of ports stored.
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschkestruct {
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke uint16_t *list; /* list containing the ports */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke uint_t listsize; /* capacity of the list (number of entries) */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke uint_t numports; /* number of ports in the list */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke} ports;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkvoid atelnet(int, unsigned char *, unsigned int);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkvoid build_ports(char *);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkvoid help(void);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint local_listen(char *, char *, struct addrinfo);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkvoid readwrite(int);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint remote_connect(const char *, const char *, struct addrinfo);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint socks_connect(const char *, const char *,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk const char *, const char *, struct addrinfo, int, const char *);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint udptest(int);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint unix_connect(char *);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint unix_listen(char *);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkvoid set_common_sockopts(int);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint parse_iptos(char *);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkvoid usage(int);
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vkchar *print_addr(char *, size_t, struct sockaddr *, int, int);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkmain(int argc, char *argv[])
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int ch, s, ret, socksv;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk char *host, *uport, *proxy;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk struct addrinfo hints;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk struct servent *sv;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk socklen_t len;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk struct sockaddr_storage cliaddr;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk const char *errstr, *proxyhost = "", *proxyport = NULL;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk struct addrinfo proxyhints;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke char port[PORT_MAX_LEN];
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ret = 1;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke s = -1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk socksv = 5;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk host = NULL;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk uport = NULL;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk sv = NULL;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk while ((ch = getopt(argc, argv,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk "46Ddhi:klnP:p:rs:T:tUuvw:X:x:z")) != -1) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk switch (ch) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case '4':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk family = AF_INET;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case '6':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk family = AF_INET6;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'U':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk family = AF_UNIX;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'X':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk Xflag = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (strcasecmp(optarg, "connect") == 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk socksv = -1; /* HTTP proxy CONNECT */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk else if (strcmp(optarg, "4") == 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk socksv = 4; /* SOCKS v.4 */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk else if (strcmp(optarg, "5") == 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk socksv = 5; /* SOCKS v.5 */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk else
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "unsupported proxy protocol");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'd':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk dflag = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'h':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk help();
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'i':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (errstr)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "interval %s: %s", errstr, optarg);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'k':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk kflag = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'l':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk lflag = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'n':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk nflag = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'P':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk Pflag = optarg;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'p':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk pflag = optarg;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'r':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk rflag = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 's':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk sflag = optarg;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 't':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk tflag = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'u':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk uflag = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'v':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk vflag = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'w':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (errstr)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "timeout %s: %s", errstr, optarg);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk timeout *= 1000;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'x':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk xflag = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((proxy = strdup(optarg)) == NULL)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk err(1, NULL);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'z':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk zflag = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'D':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk Dflag = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk case 'T':
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk Tflag = parse_iptos(optarg);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk default:
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk usage(1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk argc -= optind;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk argv += optind;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /* Cruft to make sure options are clean, and used properly. */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (argv[0] && !argv[1] && family == AF_UNIX) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (uflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "cannot use -u and -U");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk host = argv[0];
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk uport = NULL;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk } else if (argv[0] && !argv[1]) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (!lflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk usage(1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk uport = argv[0];
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk host = NULL;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk } else if (argv[0] && argv[1]) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (family == AF_UNIX)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk usage(1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk host = argv[0];
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk uport = argv[1];
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk } else {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (!(lflag && pflag))
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk usage(1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
63c99f9316851ebfab1e6d91ff1807739e55bd5bvk if (argc > 2)
63c99f9316851ebfab1e6d91ff1807739e55bd5bvk usage(1);
63c99f9316851ebfab1e6d91ff1807739e55bd5bvk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (lflag && sflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "cannot use -s and -l");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (lflag && rflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "cannot use -r and -l");
63c99f9316851ebfab1e6d91ff1807739e55bd5bvk if (lflag && (timeout >= 0))
63c99f9316851ebfab1e6d91ff1807739e55bd5bvk warnx("-w has no effect with -l");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (lflag && pflag) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (uport)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk usage(1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk uport = pflag;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (lflag && zflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "cannot use -z and -l");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (!lflag && kflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "must use -l with -k");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (lflag && (Pflag || xflag || Xflag))
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "cannot use -l with -P, -X or -x");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /* Initialize addrinfo structure. */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (family != AF_UNIX) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) memset(&hints, 0, sizeof (struct addrinfo));
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk hints.ai_family = family;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (nflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk hints.ai_flags |= AI_NUMERICHOST;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (xflag) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (uflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "no proxy support for UDP mode");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (lflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "no proxy support for listen");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (family == AF_UNIX)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "no proxy support for unix sockets");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (family == AF_INET6)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "no proxy support for IPv6");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (sflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "no proxy support for local source address");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((proxyhost = strtok(proxy, ":")) == NULL)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "missing port specification");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk proxyport = strtok(NULL, ":");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) memset(&proxyhints, 0, sizeof (struct addrinfo));
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk proxyhints.ai_family = family;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk proxyhints.ai_socktype = SOCK_STREAM;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk proxyhints.ai_protocol = IPPROTO_TCP;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (nflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk proxyhints.ai_flags |= AI_NUMERICHOST;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (lflag) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int connfd;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ret = 0;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (family == AF_UNIX) {
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (host == NULL)
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke usage(1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk s = unix_listen(host);
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /* Allow only one connection at a time, but stay alive. */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk for (;;) {
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (family != AF_UNIX) {
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke /* check if uport is valid */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (strtonum(uport, PORT_MIN, PORT_MAX,
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke &errstr) == 0)
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke errx(1, "port number %s: %s",
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke uport, errstr);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk s = local_listen(host, uport, hints);
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (s < 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk err(1, NULL);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * For UDP, we will use recvfrom() initially
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * to wait for a caller, then use the regular
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * functions to talk to the caller.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (uflag) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int rv, plen;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk char buf[8192];
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk struct sockaddr_storage z;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk len = sizeof (z);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk plen = 1024;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk rv = recvfrom(s, buf, plen, MSG_PEEK,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (struct sockaddr *)&z, &len);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (rv < 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk err(1, "recvfrom");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk rv = connect(s, (struct sockaddr *)&z, len);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (rv < 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk err(1, "connect");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk connfd = s;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk } else {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk len = sizeof (cliaddr);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk connfd = accept(s, (struct sockaddr *)&cliaddr,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk &len);
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk if ((connfd != -1) && vflag) {
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk char ntop[NI_MAXHOST + NI_MAXSERV];
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk (void) fprintf(stderr,
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk "Received connection from %s\n",
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk print_addr(ntop, sizeof (ntop),
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk (struct sockaddr *)&cliaddr, len,
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk nflag ? NI_NUMERICHOST : 0));
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk readwrite(connfd);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(connfd);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (family != AF_UNIX)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (!kflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk } else if (family == AF_UNIX) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ret = 0;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((s = unix_connect(host)) > 0 && !zflag) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk readwrite(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk } else
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ret = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk exit(ret);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk } else { /* AF_INET or AF_INET6 */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke int i;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke /* Construct the portlist. */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk build_ports(uport);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /* Cycle through portlist, connecting to each port. */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke for (i = 0; i < ports.numports; i++) {
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke (void) snprintf(port, sizeof (port), "%u",
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke ports.list[i]);
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (s != -1)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (xflag)
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke s = socks_connect(host, port,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk proxyhost, proxyport, proxyhints, socksv,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk Pflag);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk else
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke s = remote_connect(host, port, hints);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (s < 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk continue;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ret = 0;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (vflag || zflag) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /* For UDP, make sure we are connected. */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (uflag) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (udptest(s) == -1) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ret = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk continue;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /* Don't look up port if -n. */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (nflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk sv = NULL;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk else {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk sv = getservbyport(
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke ntohs(ports.list[i]),
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk uflag ? "udp" : "tcp");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk (void) fprintf(stderr, "Connection to %s %s "
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk "port [%s/%s] succeeded!\n",
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke host, port, uflag ? "udp" : "tcp",
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk sv ? sv->s_name : "*");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (!zflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk readwrite(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke free(ports.list);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (s != -1)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (ret);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk/*
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk * print IP address and (optionally) a port
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk */
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vkchar *
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vkprint_addr(char *ntop, size_t ntlen, struct sockaddr *addr, int len, int flags)
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk{
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk char port[NI_MAXSERV];
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk int e;
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk /* print port always as number */
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk if ((e = getnameinfo(addr, len, ntop, ntlen,
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk port, sizeof (port), flags|NI_NUMERICSERV)) != 0) {
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk return ((char *)gai_strerror(e));
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk }
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk (void) snprintf(ntop, ntlen, "%s port %s", ntop, port);
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk return (ntop);
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk}
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * unix_connect()
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * Returns a socket connected to a local unix socket. Returns -1 on failure.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkunix_connect(char *path)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk struct sockaddr_un sunaddr;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int s;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (-1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) memset(&sunaddr, 0, sizeof (struct sockaddr_un));
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk sunaddr.sun_family = AF_UNIX;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (strlcpy(sunaddr.sun_path, path, sizeof (sunaddr.sun_path)) >=
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk sizeof (sunaddr.sun_path)) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errno = ENAMETOOLONG;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (-1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (connect(s, (struct sockaddr *)&sunaddr, SUN_LEN(&sunaddr)) < 0) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (-1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * unix_listen()
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * Create a unix domain socket, and listen on it.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkunix_listen(char *path)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk struct sockaddr_un sunaddr;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int s;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /* Create unix domain socket. */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (-1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) memset(&sunaddr, 0, sizeof (struct sockaddr_un));
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk sunaddr.sun_family = AF_UNIX;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (strlcpy(sunaddr.sun_path, path, sizeof (sunaddr.sun_path)) >=
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk sizeof (sunaddr.sun_path)) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errno = ENAMETOOLONG;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (-1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (bind(s, (struct sockaddr *)&sunaddr, SUN_LEN(&sunaddr)) < 0) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (-1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (listen(s, 5) < 0) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (-1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * remote_connect()
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * Returns a socket connected to a remote host. Properly binds to a local
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * port or source address if needed. Returns -1 on failure.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkremote_connect(const char *host, const char *port, struct addrinfo hints)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk struct addrinfo *res, *res0;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int s, error;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((error = getaddrinfo(host, port, &hints, &res)))
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "getaddrinfo: %s", gai_strerror(error));
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk res0 = res;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk do {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((s = socket(res0->ai_family, res0->ai_socktype,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk res0->ai_protocol)) < 0) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk warn("failed to create socket");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk continue;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /* Bind to a local port or source address if specified. */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (sflag || pflag) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk struct addrinfo ahints, *ares;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) memset(&ahints, 0, sizeof (struct addrinfo));
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ahints.ai_family = res0->ai_family;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ahints.ai_flags = AI_PASSIVE;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "getaddrinfo: %s", gai_strerror(error));
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (bind(s, (struct sockaddr *)ares->ai_addr,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ares->ai_addrlen) < 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "bind failed: %s", strerror(errno));
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk freeaddrinfo(ares);
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk if (vflag && !lflag) {
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk if (sflag != NULL)
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk (void) fprintf(stderr,
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk "Using source address: %s\n",
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk sflag);
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk if (pflag != NULL)
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk (void) fprintf(stderr,
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk "Using source port: %s\n", pflag);
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk set_common_sockopts(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk else if (vflag) {
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk char ntop[NI_MAXHOST + NI_MAXSERV];
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk warn("connect to %s [host %s] (%s) failed",
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk print_addr(ntop, sizeof (ntop),
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk res0->ai_addr, res0->ai_addrlen, NI_NUMERICHOST),
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk host, uflag ? "udp" : "tcp");
f8c3982ab1838a24e4b671d13329f52bbbebc2a7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk s = -1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk } while ((res0 = res0->ai_next) != NULL);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk freeaddrinfo(res);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * local_listen()
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * Returns a socket listening on a local port, binds to specified source
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * address. Returns -1 on failure.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vklocal_listen(char *host, char *port, struct addrinfo hints)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk struct addrinfo *res, *res0;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int s, ret, x = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int error;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /* Allow nodename to be null. */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk hints.ai_flags |= AI_PASSIVE;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((error = getaddrinfo(host, port, &hints, &res)))
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "getaddrinfo: %s", gai_strerror(error));
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk res0 = res;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk do {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((s = socket(res0->ai_family, res0->ai_socktype,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk res0->ai_protocol)) < 0) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk warn("failed to create socket");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk continue;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x));
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (ret == -1)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk err(1, NULL);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk set_common_sockopts(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (bind(s, (struct sockaddr *)res0->ai_addr,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk res0->ai_addrlen) == 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk s = -1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk } while ((res0 = res0->ai_next) != NULL);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (!uflag && s != -1) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (listen(s, 1) < 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk err(1, "listen");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk freeaddrinfo(res);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (s);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * readwrite()
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * Loop that polls on the network file descriptor and stdin.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkvoid
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkreadwrite(int nfd)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk struct pollfd pfd[2];
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk unsigned char buf[8192];
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int n, wfd = fileno(stdin);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int lfd = fileno(stdout);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int plen;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk plen = 1024;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /* Setup Network FD */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk pfd[0].fd = nfd;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk pfd[0].events = POLLIN;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /* Set up STDIN FD. */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk pfd[1].fd = wfd;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk pfd[1].events = POLLIN;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk while (pfd[0].fd != -1) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (iflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) sleep(iflag);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) close(nfd);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk err(1, "Polling Error");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (n == 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (pfd[0].revents & (POLLIN|POLLHUP)) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((n = read(nfd, buf, plen)) < 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk else if (n == 0) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) shutdown(nfd, SHUT_RD);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk pfd[0].fd = -1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk pfd[0].events = 0;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk } else {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (tflag)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk atelnet(nfd, buf, n);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (atomicio(vwrite, lfd, buf, n) != n)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * handle the case of disconnected pipe: after pipe
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * is closed (indicated by POLLHUP) there may still
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * be some data lingering (POLLIN). After we read
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * the data, only POLLHUP remains, read() returns 0
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * and we are finished.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (!dflag && (pfd[1].revents & (POLLIN|POLLHUP))) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((n = read(wfd, buf, plen)) < 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk else if (n == 0) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) shutdown(nfd, SHUT_WR);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk pfd[1].fd = -1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk pfd[1].events = 0;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk } else {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (atomicio(vwrite, nfd, buf, n) != n)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkvoid
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkatelnet(int nfd, unsigned char *buf, unsigned int size)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk unsigned char *p, *end;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk unsigned char obuf[4];
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk end = buf + size;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk obuf[0] = '\0';
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk for (p = buf; p < end; p++) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (*p != IAC)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk break;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk obuf[0] = IAC;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk obuf[1] = 0;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk p++;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk /* refuse all options */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((*p == WILL) || (*p == WONT))
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk obuf[1] = DONT;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if ((*p == DO) || (*p == DONT))
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk obuf[1] = WONT;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (obuf[1]) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk p++;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk obuf[2] = *p;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk obuf[3] = '\0';
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (atomicio(vwrite, nfd, obuf, 3) != 3)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk warn("Write Error!");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk obuf[0] = '\0';
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * build_ports()
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke * Build an array of ports in ports.list[], listing each port
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * that we should try to connect to.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkvoid
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkbuild_ports(char *p)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk const char *errstr;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke const char *token;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk char *n;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke int lo, hi, cp;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke int i;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke /* Set up initial portlist. */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke ports.list = malloc(PLIST_SZ * sizeof (uint16_t));
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (ports.list == NULL)
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke err(1, NULL);
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke ports.listsize = PLIST_SZ;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke ports.numports = 0;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke /* Cycle through list of given ports sep. by "," */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke while ((token = strsep(&p, ",")) != NULL) {
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (*token == '\0')
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke errx(1, "Invalid port/portlist format: "
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke "zero length port");
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke /* check if it is a range */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if ((n = strchr(token, '-')) != NULL)
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke *n++ = '\0';
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke lo = strtonum(token, PORT_MIN, PORT_MAX, &errstr);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (errstr)
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke errx(1, "port number %s: %s", errstr, token);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (n == NULL) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk hi = lo;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke } else {
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke hi = strtonum(n, PORT_MIN, PORT_MAX, &errstr);
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (errstr)
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke errx(1, "port number %s: %s", errstr, n);
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (lo > hi) {
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke cp = hi;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke hi = lo;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke lo = cp;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke /*
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke * Grow the portlist if needed.
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke * We double the size and add size of current range
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke * to make sure we don't have to resize that often.
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (hi - lo + ports.numports + 1 >= ports.listsize) {
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke ports.listsize = ports.listsize * 2 + hi - lo;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke ports.list = realloc(ports.list,
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke ports.listsize * sizeof (uint16_t));
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (ports.list == NULL)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk err(1, NULL);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke /* Load ports sequentially. */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke for (i = lo; i <= hi; i++)
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke ports.list[ports.numports++] = i;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke /* Randomly swap ports. */
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (rflag) {
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke int y;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke uint16_t u;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke if (ports.numports < 2) {
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke warnx("can not swap %d port randomly",
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke ports.numports);
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke return;
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke }
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke srandom(time(NULL));
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke for (i = 0; i < ports.numports; i++) {
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke y = random() % (ports.numports - 1);
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke u = ports.list[i];
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke ports.list[i] = ports.list[y];
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke ports.list[y] = u;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk/*
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * udptest()
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * Do a few writes to see if the UDP port is there.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * XXX - Better way of doing this? Doesn't work for IPv6.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk * Also fails after around 100 ports checked.
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk */
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkudptest(int s)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int i, ret;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk for (i = 0; i <= 3; i++) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (write(s, "X", 1) == 1)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ret = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk else
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk ret = -1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (ret);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkvoid
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkset_common_sockopts(int s)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int x = 1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (Dflag) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (setsockopt(s, SOL_SOCKET, SO_DEBUG, &x, sizeof (x)) == -1)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk err(1, NULL);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (Tflag != -1) {
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (setsockopt(s, IPPROTO_IP, IP_TOS, &Tflag,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk sizeof (Tflag)) == -1)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk err(1, "set IP ToS");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk }
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkint
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkparse_iptos(char *s)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk int tos = -1;
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (strcmp(s, "lowdelay") == 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (IPTOS_LOWDELAY);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (strcmp(s, "throughput") == 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (IPTOS_THROUGHPUT);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (strcmp(s, "reliability") == 0)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (IPTOS_RELIABILITY);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (sscanf(s, "0x%x", (unsigned int *) &tos) != 1 ||
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk tos < 0 || tos > 0xff)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk errx(1, "invalid IP Type of Service");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk return (tos);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkvoid
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkhelp(void)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk usage(0);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) fprintf(stderr, "\tCommand Summary:\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-4 Use IPv4\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-6 Use IPv6\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-D Enable the debug socket option\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-d Detach from stdin\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-h This help text\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-i secs\t Delay interval for lines sent, ports scanned\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-k Keep inbound sockets open for multiple connects\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-l Listen mode, for inbound connects\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-n Suppress name/port resolutions\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-P proxyuser\tUsername for proxy authentication\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-p port\t Specify local port or listen port\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-r Randomize remote ports\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-s addr\t Local source address\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-T ToS\t Set IP Type of Service\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-t Answer TELNET negotiation\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-U Use UNIX domain socket\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-u UDP mode\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-v Verbose\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-w secs\t Timeout for connects and final net reads\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-x addr[:port]\tSpecify proxy address and port\n\
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk \t-z Zero-I/O mode [used for scanning]\n\
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke Port numbers can be individuals, ranges (lo-hi; inclusive) and\n\
2eef1f2b3c0d57d3f401f917b9f38f01456fd554Erik Trauschke combinations of both separated by comma (e.g. 10,22-25,80)\n");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk exit(1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkvoid
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vkusage(int ret)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk{
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) fprintf(stderr,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk "usage: nc [-46DdhklnrtUuvz] [-i interval] [-P proxy_username]"
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk " [-p port]\n");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) fprintf(stderr,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk "\t [-s source_ip_address] [-T ToS] [-w timeout]"
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk " [-X proxy_protocol]\n");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk (void) fprintf(stderr,
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk "\t [-x proxy_address[:port]] [hostname]"
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk " [port[s]]\n");
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk if (ret)
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk exit(1);
03100a6332bd4edc7a53091fcf7c9a7131bcdaa7vk}