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); }
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; }
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); }
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); }
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); }
/* * 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; }
/* * 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; }
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 */ }
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; }
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; }
/* * 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; }
/* * 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; }
/* * 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; }
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); }
/* * 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; }
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; }