コード例 #1
0
ファイル: strings.cpp プロジェクト: Anisha2202/sipp
TEST(GetHostAndPort, IPv4AndPort) {
    int port_result = -1;
    char host_result[255];
    get_host_and_port("127.0.0.1:999", host_result, &port_result);
    EXPECT_EQ(999, port_result);
    EXPECT_STREQ("127.0.0.1", host_result);
}
コード例 #2
0
ファイル: connect.c プロジェクト: LinTeX9527/git
static struct child_process *git_proxy_connect(int fd[2], char *host)
{
	const char *port = STR(DEFAULT_GIT_PORT);
	struct child_process *proxy;

	get_host_and_port(&host, &port);

	if (looks_like_command_line_option(host))
		die("strange hostname '%s' blocked", host);
	if (looks_like_command_line_option(port))
		die("strange port '%s' blocked", port);

	proxy = xmalloc(sizeof(*proxy));
	child_process_init(proxy);
	argv_array_push(&proxy->args, git_proxy_command);
	argv_array_push(&proxy->args, host);
	argv_array_push(&proxy->args, port);
	proxy->in = -1;
	proxy->out = -1;
	if (start_command(proxy))
		die("cannot start proxy %s", git_proxy_command);
	fd[0] = proxy->out; /* read from proxy stdout */
	fd[1] = proxy->in;  /* write to proxy stdin */
	return proxy;
}
コード例 #3
0
ファイル: strings.cpp プロジェクト: Anisha2202/sipp
TEST(GetHostAndPort, DNSAndPort) {
    int port_result = -1;
    char host_result[255];
    get_host_and_port("sipp.sf.net:999", host_result, &port_result);
    EXPECT_EQ(999, port_result);
    EXPECT_STREQ("sipp.sf.net", host_result);
}
コード例 #4
0
ファイル: strings.cpp プロジェクト: Anisha2202/sipp
TEST(GetHostAndPort, IPv6BracketsAndPort) {
    int port_result = -1;
    char host_result[255];
    get_host_and_port("[fe80::92a4:deff:fe74:7af5]:999", host_result, &port_result);
    EXPECT_EQ(999, port_result);
    EXPECT_STREQ("fe80::92a4:deff:fe74:7af5", host_result);
}
コード例 #5
0
ファイル: strings.cpp プロジェクト: Anisha2202/sipp
TEST(GetHostAndPort, IPv6) {
    int port_result = -1;
    char host_result[255];
    get_host_and_port("fe80::92a4:deff:fe74:7af5", host_result, &port_result);
    EXPECT_EQ(0, port_result);
    EXPECT_STREQ("fe80::92a4:deff:fe74:7af5", host_result);
}
コード例 #6
0
ファイル: connect.c プロジェクト: adityalnx/git
/*
 * Returns a connected socket() fd, or else die()s.
 */
static int git_tcp_connect_sock(char *host, int flags)
{
	int sockfd = -1, saved_errno = 0;
	const char *port = STR(DEFAULT_GIT_PORT);
	struct addrinfo hints, *ai0, *ai;
	int gai;
	int cnt = 0;

	get_host_and_port(&host, &port);
	if (!*port)
		port = "<none>";

	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "Looking up %s ... ", host);

	gai = getaddrinfo(host, port, &hints, &ai);
	if (gai)
		die("Unable to look up %s (port %s) (%s)", host, port, gai_strerror(gai));

	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);

	for (ai0 = ai; ai; ai = ai->ai_next) {
		sockfd = socket(ai->ai_family,
				ai->ai_socktype, ai->ai_protocol);
		if (sockfd < 0) {
			saved_errno = errno;
			continue;
		}
		if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
			saved_errno = errno;
			fprintf(stderr, "%s[%d: %s]: errno=%s\n",
				host,
				cnt,
				ai_name(ai),
				strerror(saved_errno));
			close(sockfd);
			sockfd = -1;
			continue;
		}
		if (flags & CONNECT_VERBOSE)
			fprintf(stderr, "%s ", ai_name(ai));
		break;
	}

	freeaddrinfo(ai0);

	if (sockfd < 0)
		die("unable to connect a socket (%s)", strerror(saved_errno));

	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "done.\n");

	return sockfd;
}
コード例 #7
0
ファイル: connect.c プロジェクト: AbhishekJajoria/git
/*
 * Returns a connected socket() fd, or else die()s.
 */
static int git_tcp_connect_sock(char *host, int flags)
{
	struct strbuf error_message = STRBUF_INIT;
	int sockfd = -1;
	const char *port = STR(DEFAULT_GIT_PORT);
	struct addrinfo hints, *ai0, *ai;
	int gai;
	int cnt = 0;

	get_host_and_port(&host, &port);
	if (!*port)
		port = "<none>";

	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "Looking up %s ... ", host);

	gai = getaddrinfo(host, port, &hints, &ai);
	if (gai)
		die("Unable to look up %s (port %s) (%s)", host, port, gai_strerror(gai));

	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);

	for (ai0 = ai; ai; ai = ai->ai_next, cnt++) {
		sockfd = socket(ai->ai_family,
				ai->ai_socktype, ai->ai_protocol);
		if ((sockfd < 0) ||
		    (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0)) {
			strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n",
				    host, cnt, ai_name(ai), strerror(errno));
			if (0 <= sockfd)
				close(sockfd);
			sockfd = -1;
			continue;
		}
		if (flags & CONNECT_VERBOSE)
			fprintf(stderr, "%s ", ai_name(ai));
		break;
	}

	freeaddrinfo(ai0);

	if (sockfd < 0)
		die("unable to connect to %s:\n%s", host, error_message.buf);

	enable_keepalive(sockfd);

	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "done.\n");

	strbuf_release(&error_message);

	return sockfd;
}
コード例 #8
0
ファイル: connect.c プロジェクト: adityalnx/git
static void git_proxy_connect(int fd[2], char *host)
{
	const char *port = STR(DEFAULT_GIT_PORT);
	const char *argv[4];
	struct child_process proxy;

	get_host_and_port(&host, &port);

	argv[0] = git_proxy_command;
	argv[1] = host;
	argv[2] = port;
	argv[3] = NULL;
	memset(&proxy, 0, sizeof(proxy));
	proxy.argv = argv;
	proxy.in = -1;
	proxy.out = -1;
	if (start_command(&proxy))
		die("cannot start proxy %s", argv[0]);
	fd[0] = proxy.out; /* read from proxy stdout */
	fd[1] = proxy.in;  /* write to proxy stdin */
}
コード例 #9
0
ファイル: connect.c プロジェクト: AbhishekJajoria/git
static struct child_process *git_proxy_connect(int fd[2], char *host)
{
	const char *port = STR(DEFAULT_GIT_PORT);
	const char **argv;
	struct child_process *proxy;

	get_host_and_port(&host, &port);

	argv = xmalloc(sizeof(*argv) * 4);
	argv[0] = git_proxy_command;
	argv[1] = host;
	argv[2] = port;
	argv[3] = NULL;
	proxy = xcalloc(1, sizeof(*proxy));
	proxy->argv = argv;
	proxy->in = -1;
	proxy->out = -1;
	if (start_command(proxy))
		die("cannot start proxy %s", argv[0]);
	fd[0] = proxy->out; /* read from proxy stdout */
	fd[1] = proxy->in;  /* write to proxy stdin */
	return proxy;
}
コード例 #10
0
int main (int argc, char** argv) 
{
	char* hostname;
	char* display;
	char* name;
	short port;
	int sock;
	int reply;
	int rval;
	int protoversion;
	char fullauth = 0;
	Byte opcode = OP_CLOSE;

        if (argc < 2) {
	       puts("Usage: floppyd_installtest [-f] Connect-String\n"
		    "-f\tDo full X-Cookie-Authentication");
	       return -1;
	}

	name = argv[1];
	if (strcmp(name, "-f") == 0) {
		fullauth = 1;
		name = argv[2];
	}

	rval = get_host_and_port(name, &hostname, &display, &port);
	
	if (!rval) return -1;

	sock = connect_to_server(getipaddress(hostname), port);

	if (sock == -1) {
		fprintf(stderr,
			"Can't connect to floppyd server on %s, port %i!\n",
			hostname, port);
		return -1;
	}
	
	protoversion = FLOPPYD_PROTOCOL_VERSION;
	while(1) {
	    reply = authenticate_to_floppyd(fullauth, sock, display,
					    protoversion);
	    if(protoversion == FLOPPYD_PROTOCOL_VERSION_OLD)
		break;
	    if(reply == AUTH_WRONGVERSION) {
		/* fall back on old version */
		protoversion = FLOPPYD_PROTOCOL_VERSION_OLD;
		continue;
	    }
	    break;
	}

	if (reply != 0) {
		fprintf(stderr, 
			"Connection to floppyd failed:\n"
			"%s\n", AuthErrors[reply]);
		return -1;
	}
	
	free(hostname);
	free(display);

	write_dword(sock, 1);
	write(sock, &opcode, 1);

	close(sock);

	return 0;
}
コード例 #11
0
ファイル: connect.c プロジェクト: AbhishekJajoria/git
/*
 * Returns a connected socket() fd, or else die()s.
 */
static int git_tcp_connect_sock(char *host, int flags)
{
	struct strbuf error_message = STRBUF_INIT;
	int sockfd = -1;
	const char *port = STR(DEFAULT_GIT_PORT);
	char *ep;
	struct hostent *he;
	struct sockaddr_in sa;
	char **ap;
	unsigned int nport;
	int cnt;

	get_host_and_port(&host, &port);

	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "Looking up %s ... ", host);

	he = gethostbyname(host);
	if (!he)
		die("Unable to look up %s (%s)", host, hstrerror(h_errno));
	nport = strtoul(port, &ep, 10);
	if ( ep == port || *ep ) {
		/* Not numeric */
		struct servent *se = getservbyname(port,"tcp");
		if ( !se )
			die("Unknown port %s", port);
		nport = se->s_port;
	}

	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);

	for (cnt = 0, ap = he->h_addr_list; *ap; ap++, cnt++) {
		memset(&sa, 0, sizeof sa);
		sa.sin_family = he->h_addrtype;
		sa.sin_port = htons(nport);
		memcpy(&sa.sin_addr, *ap, he->h_length);

		sockfd = socket(he->h_addrtype, SOCK_STREAM, 0);
		if ((sockfd < 0) ||
		    connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
			strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n",
				host,
				cnt,
				inet_ntoa(*(struct in_addr *)&sa.sin_addr),
				strerror(errno));
			if (0 <= sockfd)
				close(sockfd);
			sockfd = -1;
			continue;
		}
		if (flags & CONNECT_VERBOSE)
			fprintf(stderr, "%s ",
				inet_ntoa(*(struct in_addr *)&sa.sin_addr));
		break;
	}

	if (sockfd < 0)
		die("unable to connect to %s:\n%s", host, error_message.buf);

	enable_keepalive(sockfd);

	if (flags & CONNECT_VERBOSE)
		fprintf(stderr, "done.\n");

	return sockfd;
}
コード例 #12
0
ファイル: connect.c プロジェクト: n0n4zw0rl6/git
/*
 * This returns a dummy child_process if the transport protocol does not
 * need fork(2), or a struct child_process object if it does.  Once done,
 * finish the connection with finish_connect() with the value returned from
 * this function (it is safe to call finish_connect() with NULL to support
 * the former case).
 *
 * If it returns, the connect is successful; it just dies on errors (this
 * will hopefully be changed in a libification effort, to return NULL when
 * the connection failed).
 */
struct child_process *git_connect(int fd[2], const char *url,
				  const char *prog, int flags)
{
	char *hostandport, *path;
	struct child_process *conn = &no_fork;
	enum protocol protocol;
	struct strbuf cmd = STRBUF_INIT;

	/* Without this we cannot rely on waitpid() to tell
	 * what happened to our children.
	 */
	signal(SIGCHLD, SIG_DFL);

	protocol = parse_connect_url(url, &hostandport, &path);
	if ((flags & CONNECT_DIAG_URL) && (protocol != PROTO_SSH)) {
		printf("Diag: url=%s\n", url ? url : "NULL");
		printf("Diag: protocol=%s\n", prot_name(protocol));
		printf("Diag: hostandport=%s\n", hostandport ? hostandport : "NULL");
		printf("Diag: path=%s\n", path ? path : "NULL");
		conn = NULL;
	} else if (protocol == PROTO_GIT) {
		/*
		 * Set up virtual host information based on where we will
		 * connect, unless the user has overridden us in
		 * the environment.
		 */
		char *target_host = getenv("GIT_OVERRIDE_VIRTUAL_HOST");
		if (target_host)
			target_host = xstrdup(target_host);
		else
			target_host = xstrdup(hostandport);

		transport_check_allowed("git");

		/* These underlying connection commands die() if they
		 * cannot connect.
		 */
		if (git_use_proxy(hostandport))
			conn = git_proxy_connect(fd, hostandport);
		else
			git_tcp_connect(fd, hostandport, flags);
		/*
		 * Separate original protocol components prog and path
		 * from extended host header with a NUL byte.
		 *
		 * Note: Do not add any other headers here!  Doing so
		 * will cause older git-daemon servers to crash.
		 */
		packet_write(fd[1],
			     "%s %s%chost=%s%c",
			     prog, path, 0,
			     target_host, 0);
		free(target_host);
	} else {
		conn = xmalloc(sizeof(*conn));
		child_process_init(conn);

		strbuf_addstr(&cmd, prog);
		strbuf_addch(&cmd, ' ');
		sq_quote_buf(&cmd, path);

		conn->in = conn->out = -1;
		if (protocol == PROTO_SSH) {
			const char *ssh;
			int putty, tortoiseplink = 0;
			char *ssh_host = hostandport;
			const char *port = NULL;
			transport_check_allowed("ssh");
			get_host_and_port(&ssh_host, &port);

			if (!port)
				port = get_port(ssh_host);

			if (flags & CONNECT_DIAG_URL) {
				printf("Diag: url=%s\n", url ? url : "NULL");
				printf("Diag: protocol=%s\n", prot_name(protocol));
				printf("Diag: userandhost=%s\n", ssh_host ? ssh_host : "NULL");
				printf("Diag: port=%s\n", port ? port : "NONE");
				printf("Diag: path=%s\n", path ? path : "NULL");

				free(hostandport);
				free(path);
				free(conn);
				return NULL;
			}

			ssh = getenv("GIT_SSH_COMMAND");
			if (ssh) {
				conn->use_shell = 1;
				putty = 0;
			} else {
				const char *base;
				char *ssh_dup;

				ssh = getenv("GIT_SSH");
				if (!ssh)
					ssh = "ssh";

				ssh_dup = xstrdup(ssh);
				base = basename(ssh_dup);

				tortoiseplink = !strcasecmp(base, "tortoiseplink") ||
					!strcasecmp(base, "tortoiseplink.exe");
				putty = !strcasecmp(base, "plink") ||
					!strcasecmp(base, "plink.exe") || tortoiseplink;

				free(ssh_dup);
			}

			argv_array_push(&conn->args, ssh);
			if (tortoiseplink)
				argv_array_push(&conn->args, "-batch");
			if (port) {
				/* P is for PuTTY, p is for OpenSSH */
				argv_array_push(&conn->args, putty ? "-P" : "-p");
				argv_array_push(&conn->args, port);
			}
			argv_array_push(&conn->args, ssh_host);
		} else {
			/* remove repo-local variables from the environment */
			conn->env = local_repo_env;
			conn->use_shell = 1;
			transport_check_allowed("file");
		}
		argv_array_push(&conn->args, cmd.buf);

		if (start_command(conn))
			die("unable to fork");

		fd[0] = conn->out; /* read from child's stdout */
		fd[1] = conn->in;  /* write to child's stdin */
		strbuf_release(&cmd);
	}
	free(hostandport);
	free(path);
	return conn;
}
コード例 #13
0
ファイル: connect.c プロジェクト: LinTeX9527/git
/*
 * This returns the dummy child_process `no_fork` if the transport protocol
 * does not need fork(2), or a struct child_process object if it does.  Once
 * done, finish the connection with finish_connect() with the value returned
 * from this function (it is safe to call finish_connect() with NULL to
 * support the former case).
 *
 * If it returns, the connect is successful; it just dies on errors (this
 * will hopefully be changed in a libification effort, to return NULL when
 * the connection failed).
 */
struct child_process *git_connect(int fd[2], const char *url,
				  const char *prog, int flags)
{
	char *hostandport, *path;
	struct child_process *conn;
	enum protocol protocol;

	/* Without this we cannot rely on waitpid() to tell
	 * what happened to our children.
	 */
	signal(SIGCHLD, SIG_DFL);

	protocol = parse_connect_url(url, &hostandport, &path);
	if ((flags & CONNECT_DIAG_URL) && (protocol != PROTO_SSH)) {
		printf("Diag: url=%s\n", url ? url : "NULL");
		printf("Diag: protocol=%s\n", prot_name(protocol));
		printf("Diag: hostandport=%s\n", hostandport ? hostandport : "NULL");
		printf("Diag: path=%s\n", path ? path : "NULL");
		conn = NULL;
	} else if (protocol == PROTO_GIT) {
		conn = git_connect_git(fd, hostandport, path, prog, flags);
	} else {
		struct strbuf cmd = STRBUF_INIT;
		const char *const *var;

		conn = xmalloc(sizeof(*conn));
		child_process_init(conn);

		if (looks_like_command_line_option(path))
			die("strange pathname '%s' blocked", path);

		strbuf_addstr(&cmd, prog);
		strbuf_addch(&cmd, ' ');
		sq_quote_buf(&cmd, path);

		/* remove repo-local variables from the environment */
		for (var = local_repo_env; *var; var++)
			argv_array_push(&conn->env_array, *var);

		conn->use_shell = 1;
		conn->in = conn->out = -1;
		if (protocol == PROTO_SSH) {
			char *ssh_host = hostandport;
			const char *port = NULL;
			transport_check_allowed("ssh");
			get_host_and_port(&ssh_host, &port);

			if (!port)
				port = get_port(ssh_host);

			if (flags & CONNECT_DIAG_URL) {
				printf("Diag: url=%s\n", url ? url : "NULL");
				printf("Diag: protocol=%s\n", prot_name(protocol));
				printf("Diag: userandhost=%s\n", ssh_host ? ssh_host : "NULL");
				printf("Diag: port=%s\n", port ? port : "NONE");
				printf("Diag: path=%s\n", path ? path : "NULL");

				free(hostandport);
				free(path);
				free(conn);
				strbuf_release(&cmd);
				return NULL;
			}
			fill_ssh_args(conn, ssh_host, port, flags);
		} else {
			transport_check_allowed("file");
			if (get_protocol_version_config() > 0) {
				argv_array_pushf(&conn->env_array, GIT_PROTOCOL_ENVIRONMENT "=version=%d",
						 get_protocol_version_config());
			}
		}
		argv_array_push(&conn->args, cmd.buf);

		if (start_command(conn))
			die("unable to fork");

		fd[0] = conn->out; /* read from child's stdout */
		fd[1] = conn->in;  /* write to child's stdin */
		strbuf_release(&cmd);
	}
	free(hostandport);
	free(path);
	return conn;
}
コード例 #14
0
ファイル: strings.cpp プロジェクト: Anisha2202/sipp
TEST(GetHostAndPort, IgnorePort) {
    char host_result[255];
    get_host_and_port("127.0.0.1", host_result, NULL);
    EXPECT_STREQ("127.0.0.1", host_result);
}
コード例 #15
0
ファイル: connect.c プロジェクト: chris-y/Git
/*
 * Returns a connected socket() fd, or else die()s.
 */
static int git_tcp_connect_sock(char *host, int flags)
{
    int sockfd = -1, saved_errno = 0;
    const char *port = STR(DEFAULT_GIT_PORT);
    char *ep;
    struct hostent *he;
    struct sockaddr_in sa;
    char **ap;
    unsigned int nport;
    int cnt;

    get_host_and_port(&host, &port);

    if (flags & CONNECT_VERBOSE)
        fprintf(stderr, "Looking up %s ... ", host);

#ifdef AMIGA
    /* FIXME: A clean way of doing this on startup/exit?
       How does AROS auto-open work? */
    /* On AROS it should be auto-opened. On AmigaOS it
       won't. However, we try to open it here in any
       case instead of using separate code for each,
       as it won't do any harm, and if we don't we'll
       crash if bsdsocket.library isn't present
     */
    if (!SocketBase) {
        SocketBase = OpenLibrary("bsdsocket.library",0);
        if (!SocketBase) {
            die("Unable to open bsdsocket.library");
        }
    }
#endif
    he = gethostbyname(host);
    if (!he)
        die("Unable to look up %s (%s)", host, hstrerror(h_errno));
    nport = strtoul(port, &ep, 10);
    if ( ep == port || *ep ) {
        /* Not numeric */
        struct servent *se = getservbyname(port,"tcp");
        if ( !se )
            die("Unknown port %s", port);
        nport = se->s_port;
    }
    if (flags & CONNECT_VERBOSE)
        fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);

    for (cnt = 0, ap = he->h_addr_list; *ap; ap++, cnt++) {
        sockfd = socket(he->h_addrtype, SOCK_STREAM, 0);
        if (sockfd < 0) {
            saved_errno = errno;
            continue;
        }

        memset(&sa, 0, sizeof sa);
        sa.sin_family = he->h_addrtype;
        sa.sin_port = htons(nport);
        memcpy(&sa.sin_addr, *ap, he->h_length);

        if (connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
            saved_errno = errno;
            fprintf(stderr, "%s[%d: %s]: errno=%s\n",
                    host,
                    cnt,
                    inet_ntoa(*(struct in_addr *)&sa.sin_addr),
                    strerror(saved_errno));
            close(sockfd);
            sockfd = -1;
            continue;
        }
        if (flags & CONNECT_VERBOSE)
            fprintf(stderr, "%s ",
                    inet_ntoa(*(struct in_addr *)&sa.sin_addr));
        break;
    }

    if (sockfd < 0)
        die("unable to connect a socket (%s)", strerror(saved_errno));

    if (flags & CONNECT_VERBOSE)
        fprintf(stderr, "done.\n");

    return sockfd;
}
コード例 #16
0
ファイル: client.c プロジェクト: askovpen/binkd
static int call0 (FTN_NODE *node, BINKD_CONFIG *config)
{
  int sockfd = INVALID_SOCKET;
  int sock_out;
  char szDestAddr[FTN_ADDR_SZ + 1];
  int i, rc, pid = -1;
  char host[BINKD_FQDNLEN + 5 + 1];       /* current host/port */
  char addrbuf[BINKD_FQDNLEN + 1];
  char servbuf[MAXSERVNAME + 1];
  char *hosts;
  char *port;
  char *dst_host = host;
  const char *save_err;
#ifdef HTTPS
  int use_proxy;
  char *proxy, *socks;
  struct addrinfo *aiProxyHead;
#endif
  struct addrinfo *ai, *aiNodeHead, *aiHead, hints;
  int aiErr;

  /* setup hints for getaddrinfo */
  memset((void *)&hints, 0, sizeof(hints));
  hints.ai_family = node->IP_afamily;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;

#ifdef WITH_PERL
  hosts = xstrdup(node->hosts);
#ifdef HTTPS
  proxy = xstrdup(config->proxy);
  socks = xstrdup(config->socks);
#endif
  if (!perl_on_call(node, config, &hosts
#ifdef HTTPS
                    , &proxy, &socks
#endif
                    )) {
    Log(1, "call aborted by Perl on_call()");
    return 0;
  }
#else
  hosts = node->hosts;
#ifdef HTTPS
  proxy = config->proxy;
  socks = config->socks;
#endif
#endif

  ftnaddress_to_str (szDestAddr, &node->fa);
  Log (2, "call to %s", szDestAddr);
  setproctitle ("call to %s", szDestAddr);

#ifdef HTTPS
  use_proxy = (node->NP_flag != NP_ON) && (!node->pipe || !node->pipe[0]) && (proxy[0] || socks[0]);
  if (use_proxy)
  {
    char *sp, *sport;
    strncpy(host, proxy[0] ? proxy : socks, sizeof(host));
    if ((sp=strchr(host, ':')) != NULL)
    {
      *sp++ = '\0';
      sport = sp;
      if ((sp=strchr(sp, '/')) != NULL)
	*sp++ = '\0';
    }
    else
    {
      if ((sp=strchr(host, '/')) != NULL)
	*sp++ = '\0';
      sport = proxy[0] ? "squid" : "socks"; /* default port */
    }
    /* resolve proxy host */
    if ( (aiErr = srv_getaddrinfo(host, sport, &hints, &aiProxyHead)) != 0)
    {
	Log(2, "Port %s not found, try default %d", sp, proxy[0] ? 3128 : 1080);
	aiErr = getaddrinfo(host, proxy[0] ? "3128" : "1080", &hints, &aiProxyHead);
    }
    if (aiErr != 0)
    {
      Log(1, "%s host %s not found", proxy[0] ? "Proxy" : "Socks", host);
#ifdef WITH_PERL
      xfree(hosts);
#ifdef HTTPS
      xfree(proxy);
      xfree(socks);
#endif
#endif
      return 0;
    }
  }
#endif

  for (i = 1; sockfd == INVALID_SOCKET
       && (rc = get_host_and_port
	   (i, host, &port, hosts, &node->fa, config)) != -1; ++i)
  {
    if (rc == 0)
    {
      Log (1, "%s: %i: error parsing host list", hosts, i);
      continue;
    }

    pid = -1;
    if (node->pipe && node->pipe[0])
    {
      char *cmdline = strdup(node->pipe);
      cmdline = ed(cmdline, "*H", host, NULL);
      cmdline = ed(cmdline, "*I", port, NULL);
      pid = run3(cmdline, &sock_out, &sockfd, NULL);
      free(cmdline);
      if (pid != -1)
      {
	Log (4, "connected");
	add_socket(sock_out);
	break;
      }
      if (!binkd_exit)
      {
	Log (1, "connection to %s failed");
	/* bad_try (&node->fa, "exec error", BAD_CALL, config); */
      }
      sockfd = INVALID_SOCKET;
      continue;
    }

#ifdef HTTPS
    if (use_proxy)
      aiHead = aiProxyHead;
    else /* don't resolve if proxy or socks specified */
#endif
    {
      aiErr = srv_getaddrinfo(host, port, &hints, &aiNodeHead);
     
      if (aiErr != 0)
      {
        bad_try(&node->fa, "Cannot getaddrinfo", BAD_CALL, config);
        continue;
      }
      aiHead = aiNodeHead;
    }

    /* Trying... */

    for (ai = aiHead; ai != NULL && sockfd == INVALID_SOCKET; ai = ai->ai_next)
    {
      if ((sockfd = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == INVALID_SOCKET)
      {
	Log (1, "socket: %s", TCPERR ());

	/* as long as there are more addresses, try those */
        if (ai != NULL) 
          continue;
        else
        {
#ifdef WITH_PERL
	  xfree(hosts);
#ifdef HTTPS
	  xfree(proxy);
	  xfree(socks);
#endif
#endif
	  freeaddrinfo(aiHead);
	  return 0;
	}
      }
      add_socket(sockfd);
      /* Was the socket created after close_sockets loop in exitfunc()? */
      if (binkd_exit)
      {
#ifdef WITH_PERL
	xfree(hosts);
#ifdef HTTPS
	xfree(proxy);
	xfree(socks);
#endif
#endif
	freeaddrinfo(aiHead);
	return 0;
      }
      rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, addrbuf, sizeof(addrbuf),
		       servbuf, sizeof(servbuf), NI_NUMERICHOST | NI_NUMERICSERV);
      if (rc != 0) {
	Log (2, "Error in getnameinfo(): %s (%d)", gai_strerror(rc), rc);
        snprintf(addrbuf, BINKD_FQDNLEN, "invalid");
	*servbuf = '\0';
      }

#ifdef HTTPS
      if (use_proxy)
      {
	char *sp = strchr(host, ':');
	if (sp) *sp = '\0';
	if (port == config->oport)
	  Log (4, "trying %s via %s %s:%s...", host,
	       proxy[0] ? "proxy" : "socks", addrbuf, servbuf);
	else
	  Log (4, "trying %s:%s via %s %s:%s...", host, port,
	       proxy[0] ? "proxy" : "socks", addrbuf, servbuf);
	sprintf(host+strlen(host), ":%s", port);
      }
      else
#endif
      {
	if (port == config->oport)
          Log (4, "trying %s [%s]...", host, addrbuf);
	else
          Log (4, "trying %s [%s]:%s...", host, addrbuf, servbuf);
      }
      /* find bind addr with matching address family */
      if (config->bindaddr[0])
      {
	struct addrinfo *src_ai, src_hints;
	
	memset((void *)&src_hints, 0, sizeof(src_hints));
	src_hints.ai_socktype = SOCK_STREAM;
	src_hints.ai_family = ai->ai_family;
	src_hints.ai_protocol = IPPROTO_TCP;
	if ((aiErr = getaddrinfo(config->bindaddr, NULL, &src_hints, &src_ai)) == 0)
        {
          if (bind(sockfd, src_ai->ai_addr, src_ai->ai_addrlen))
	    Log(4, "bind: %s", TCPERR());
	  freeaddrinfo(src_ai);
	}
        else
	  if (aiErr == EAI_FAMILY)
	    /* address family of target and bind address don't match */
	    continue;
	  else
	    /* otherwise just warn and don't bind() */
	    Log(2, "bind -- getaddrinfo: %s (%d)", gai_strerror(aiErr), aiErr);
      }
#ifdef HAVE_FORK
      if (config->connect_timeout)
      {
	signal(SIGALRM, alrm);
	alarm(config->connect_timeout);
      }
#endif
      if (connect (sockfd, ai->ai_addr, ai->ai_addrlen) == 0)
      {
#ifdef HAVE_FORK
	alarm(0);
#endif
	Log (4, "connected");
	sock_out = sockfd;
	dst_host = addrbuf;
	break;
      }

#ifdef HAVE_FORK
      if (errno == EINTR && config->connect_timeout)
	save_err = strerror (ETIMEDOUT);
      else
	save_err = TCPERR ();
      alarm(0);
#else
      save_err = TCPERR ();
#endif
      if (!binkd_exit)
      {
	Log (1, "connection to %s failed: %s", szDestAddr, save_err);
	bad_try (&node->fa, save_err, BAD_CALL, config);
      }
      del_socket(sockfd);
      soclose (sockfd);
      sockfd = INVALID_SOCKET;
    }
#ifdef HTTPS
    if (!use_proxy)
#endif
      freeaddrinfo(aiNodeHead);
#ifdef HTTPS
    if (sockfd != INVALID_SOCKET && use_proxy) {
      if (h_connect(sockfd, host, config, proxy, socks) != 0) {
        if (!binkd_exit)
          bad_try (&node->fa, TCPERR (), BAD_CALL, config);
        del_socket(sockfd);
        soclose (sockfd);
        sockfd = INVALID_SOCKET;
      }
      else if (port == config->oport) {
        char *pp;
        if( (pp = strchr(host, ':')) ){
          *pp = '\0';
        }
      }
    }
#endif
  }
#ifdef HTTPS
  if (use_proxy)
    freeaddrinfo(aiProxyHead);
#endif
#ifdef WITH_PERL
  xfree(hosts);
#ifdef HTTPS
  xfree(proxy);
  xfree(socks);
#endif
#endif

  if (sockfd == INVALID_SOCKET)
    return 0;

  protocol (sockfd, sock_out, node, NULL, dst_host, config);
  if (pid != -1)
  {
    del_socket(sock_out);
    close(sock_out);
#ifdef HAVE_WAITPID
    if (waitpid (pid, &rc, 0) == -1)
    {
      Log (1, "waitpid(%u) error: %s", pid, strerror(errno));
    }
    else
    {
      if (WIFSIGNALED(rc))
        Log (2, "process %u exited by signal %u", pid, WTERMSIG(rc));
      else
        Log (4, "rc(%u)=%u", pid, WEXITSTATUS(rc));
    }
#endif
    close(sockfd);
  }
  else
  {
    del_socket(sockfd);
    soclose (sockfd);
  }
  return 1;
}