static void init_remote(CLI *c) { /* where to bind connecting socket */ if(c->opt->option.local) /* outgoing interface */ c->bind_addr=&c->opt->source_addr; #ifndef USE_WIN32 else if(c->opt->option.transparent_src) c->bind_addr=&c->peer_addr; #endif else c->bind_addr=NULL; /* don't bind */ /* setup c->remote_fd, now */ if(c->opt->option.remote) { /* try remote first for exec+connect targets */ c->remote_fd.fd=connect_remote(c); } else if(c->opt->option.program) { /* exec+connect uses local fd */ c->remote_fd.fd=connect_local(c); } else { s_log(LOG_ERR, "INTERNAL ERROR: No target for remote socket"); longjmp(c->err, 1); } c->remote_fd.is_socket=1; /* always! */ s_log(LOG_DEBUG, "Remote socket (FD=%d) initialized", c->remote_fd.fd); if(set_socket_options(c->remote_fd.fd, 2)) s_log(LOG_WARNING, "Failed to set remote socket options"); }
static int newtcpforwarded(struct Channel * channel) { char *origaddr = NULL; unsigned int origport; m_list_elem * iter = NULL; struct TCPFwdEntry *fwd; char portstring[NI_MAXSERV]; int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; origaddr = buf_getstring(ses.payload, NULL); origport = buf_getint(ses.payload); /* Find which port corresponds. First try and match address as well as port, in case they want to forward different ports separately ... */ for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { fwd = (struct TCPFwdEntry*)iter->item; if (origport == fwd->listenport && strcmp(origaddr, fwd->listenaddr) == 0) { break; } } if (!iter) { /* ... otherwise try to generically match the only forwarded port without address (also handles ::1 vs 127.0.0.1 vs localhost case). rfc4254 is vague about the definition of "address that was connected" */ for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { fwd = (struct TCPFwdEntry*)iter->item; if (origport == fwd->listenport) { break; } } } if (iter == NULL) { /* We didn't request forwarding on that port */ cleantext(origaddr); dropbear_log(LOG_INFO, "Server sent unrequested forward from \"%s:%d\"", origaddr, origport); goto out; } snprintf(portstring, sizeof(portstring), "%d", fwd->connectport); channel->conn_pending = connect_remote(AF_UNSPEC, fwd->connectaddr, portstring, channel_connect_done, channel); channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE; err = SSH_OPEN_IN_PROGRESS; out: m_free(origaddr); TRACE(("leave newtcpdirect: err %d", err)) return err; }
int cli_main(int argc, char ** argv) { #else int main(int argc, char ** argv) { #endif int sock_in, sock_out; struct dropbear_progress_connection *progress = NULL; _dropbear_exit = cli_dropbear_exit; _dropbear_log = cli_dropbear_log; disallow_core(); seedrandom(); crypto_init(); cli_getopts(argc, argv); #ifndef DISABLE_SYSLOG if (opts.usingsyslog) { startsyslog("dbclient"); } #endif TRACE(("user='******' host='%s' port='%s' bind_address='%s' bind_port='%s'", cli_opts.username, cli_opts.remotehost, cli_opts.remoteport, cli_opts.bind_address, cli_opts.bind_port)) if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { dropbear_exit("signal() error"); } pid_t proxy_cmd_pid = 0; #if DROPBEAR_CLI_PROXYCMD if (cli_opts.proxycmd) { cli_proxy_cmd(&sock_in, &sock_out, &proxy_cmd_pid); m_free(cli_opts.proxycmd); if (signal(SIGINT, kill_proxy_sighandler) == SIG_ERR || signal(SIGTERM, kill_proxy_sighandler) == SIG_ERR || signal(SIGHUP, kill_proxy_sighandler) == SIG_ERR) { dropbear_exit("signal() error"); } } else #endif { progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport, cli_connected, &ses, cli_opts.bind_address, cli_opts.bind_port); sock_in = sock_out = -1; } cli_session(sock_in, sock_out, progress, proxy_cmd_pid); /* not reached */ return -1; }
static int newtcpforwarded(struct Channel * channel) { char *origaddr = NULL; unsigned int origport; m_list_elem * iter = NULL; struct TCPFwdEntry *fwd; char portstring[NI_MAXSERV]; int sock; int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; origaddr = buf_getstring(ses.payload, NULL); origport = buf_getint(ses.payload); /* Find which port corresponds */ for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { fwd = (struct TCPFwdEntry*)iter->item; if (origport == fwd->listenport && (strcmp(origaddr, fwd->listenaddr) == 0)) { break; } } if (iter == NULL) { /* We didn't request forwarding on that port */ cleantext(origaddr); dropbear_log(LOG_INFO, "Server sent unrequested forward from \"%s:%d\"", origaddr, origport); goto out; } snprintf(portstring, sizeof(portstring), "%d", fwd->connectport); sock = connect_remote(AF_UNSPEC, fwd->connectaddr, portstring, 1, NULL); if (sock < 0) { TRACE(("leave newtcpdirect: sock failed")) err = SSH_OPEN_CONNECT_FAILED; goto out; } ses.maxfd = MAX(ses.maxfd, sock); /* We don't set readfd, that will get set after the connection's * progress succeeds */ channel->writefd = sock; channel->initconn = 1; err = SSH_OPEN_IN_PROGRESS; out: m_free(origaddr); TRACE(("leave newtcpdirect: err %d", err)) return err; }
int cli_main(int argc, char ** argv) { #else int main(int argc, char ** argv) { #endif int sock_in, sock_out; char* error = NULL; char* hostandport; int len; _dropbear_exit = cli_dropbear_exit; _dropbear_log = cli_dropbear_log; disallow_core(); cli_getopts(argc, argv); TRACE(("user='******' host='%s' port='%s'", cli_opts.username, cli_opts.remotehost, cli_opts.remoteport)) if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { dropbear_exit("signal() error"); } #ifdef ENABLE_CLI_PROXYCMD if (cli_opts.proxycmd) { cli_proxy_cmd(&sock_in, &sock_out); } else #endif { int sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport, 0, &error); sock_in = sock_out = sock; } if (sock_in < 0) { dropbear_exit("%s", error); } /* Set up the host:port log */ len = strlen(cli_opts.remotehost); len += 10; /* 16 bit port and leeway*/ hostandport = (char*)m_malloc(len); snprintf(hostandport, len, "%s:%s", cli_opts.remotehost, cli_opts.remoteport); cli_session(sock_in, sock_out, hostandport); /* not reached */ return -1; }
int cli_main(int argc, char ** argv) { #else int main(int argc, char ** argv) { #endif int sock_in, sock_out; char* error = NULL; _dropbear_exit = cli_dropbear_exit; _dropbear_log = cli_dropbear_log; disallow_core(); seedrandom(); crypto_init(); cli_getopts(argc, argv); TRACE(("user='******' host='%s' port='%s'", cli_opts.username, cli_opts.remotehost, cli_opts.remoteport)) if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { dropbear_exit("signal() error"); } #ifdef ENABLE_CLI_PROXYCMD if (cli_opts.proxycmd) { cli_proxy_cmd(&sock_in, &sock_out); m_free(cli_opts.proxycmd); } else #endif { int sock = connect_remote(cli_opts.ipfamily, cli_opts.remotehost, cli_opts.remoteport, 0, &error); sock_in = sock_out = sock; if (cli_opts.wantpty) { set_sock_priority(sock, DROPBEAR_PRIO_LOWDELAY); } } if (sock_in < 0) { dropbear_exit("%s", error); } cli_session(sock_in, sock_out); /* not reached */ return -1; }
int cli_main(int argc, char ** argv) { #else int main(int argc, char ** argv) { #endif int sock_in, sock_out; struct dropbear_progress_connection *progress = NULL; _dropbear_exit = cli_dropbear_exit; _dropbear_log = cli_dropbear_log; disallow_core(); seedrandom(); crypto_init(); cli_getopts(argc, argv); TRACE(("user='******' host='%s' port='%s'", cli_opts.username, cli_opts.remotehost, cli_opts.remoteport)) if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { dropbear_exit("signal() error"); } #ifdef ENABLE_CLI_PROXYCMD if (cli_opts.proxycmd) { cli_proxy_cmd(&sock_in, &sock_out); m_free(cli_opts.proxycmd); } else #endif { progress = connect_remote(cli_opts.ipfamily, cli_opts.remotehost, cli_opts.remoteport, cli_connected, &ses); sock_in = sock_out = -1; } cli_session(sock_in, sock_out, progress); /* not reached */ return -1; }
static void init_remote(CLI * c) { if (c->opt->option.local) c->bind_addr = &c->opt->source_addr; else c->bind_addr = NULL; if (c->opt->option.remote) { c->remote_fd.fd = connect_remote(c); } else { s_log(LOG_ERR, "INTERNAL ERROR: No target for remote socket"); longjmp(c->err, 1); } c->remote_fd.is_socket = 1; s_log(LOG_DEBUG, "Remote socket (FD=%d) initialized", c->remote_fd.fd); if (set_socket_options(c->remote_fd.fd, 2)) s_log(LOG_WARNING, "Failed to set remote socket options"); }
static int init_local(CLI *c) { SOCKADDR_UNION addr; socklen_t addrlen; addrlen=sizeof(SOCKADDR_UNION); if(getpeername(c->local_rfd.fd, &addr.sa, &addrlen)<0) { strcpy(c->accepting_address, "NOT A SOCKET"); c->local_rfd.is_socket=0; c->local_wfd.is_socket=0; /* TODO: It's not always true */ #ifdef USE_WIN32 if(get_last_socket_error()!=ENOTSOCK) { #else if(c->opt->option.transparent || get_last_socket_error()!=ENOTSOCK) { #endif sockerror("getpeerbyname"); return -1; } /* Ignore ENOTSOCK error so 'local' doesn't have to be a socket */ } else { /* success */ /* copy addr to c->peer_addr */ memcpy(&c->peer_addr.addr[0], &addr, sizeof(SOCKADDR_UNION)); c->peer_addr.num=1; s_ntop(c->accepting_address, &c->peer_addr.addr[0]); c->local_rfd.is_socket=1; c->local_wfd.is_socket=1; /* TODO: It's not always true */ /* It's a socket: lets setup options */ if(set_socket_options(c->local_rfd.fd, 1)<0) return -1; if(auth_libwrap(c)<0) return -1; if(auth_user(c)<0) { s_log(LOG_WARNING, "Connection from %s REFUSED by IDENT", c->accepting_address); return -1; } s_log(LOG_NOTICE, "%s connected from %s", c->opt->servname, c->accepting_address); } return 0; /* OK */ } static int init_remote(CLI *c) { int fd; /* create connection to host/service */ if(c->opt->source_addr.num) memcpy(&c->bind_addr, &c->opt->source_addr, sizeof(SOCKADDR_LIST)); #ifndef USE_WIN32 else if(c->opt->option.transparent) memcpy(&c->bind_addr, &c->peer_addr, sizeof(SOCKADDR_LIST)); #endif else { c->bind_addr.num=0; /* don't bind connecting socket */ } /* Setup c->remote_fd, now */ if(c->opt->option.remote) { fd=connect_remote(c); } else /* NOT in remote mode */ fd=connect_local(c); if(fd<0) { s_log(LOG_ERR, "Failed to initialize remote connection"); return -1; } #ifndef USE_WIN32 if(fd>=max_fds) { s_log(LOG_ERR, "Remote file descriptor out of range (%d>=%d)", fd, max_fds); closesocket(fd); return -1; } #endif s_log(LOG_DEBUG, "Remote FD=%d initialized", fd); c->remote_fd.fd=fd; c->remote_fd.is_socket=1; /* Always! */ if(set_socket_options(fd, 2)<0) return -1; return 0; /* OK */ }
//Acquires information, initiates a connect and initialises a new connection //object. Return NULL if anything fails, pointer to object otherwise tproxy_conn_t* add_tcp_connection(int efd, struct tailhead *conn_list, int local_fd, uint16_t listen_port) { struct sockaddr_storage orig_dst; tproxy_conn_t *conn; int remote_fd; struct epoll_event ev; if(get_org_dstaddr(local_fd, &orig_dst)){ fprintf(stderr, "Could not get local address\n"); close(local_fd); return NULL; } if (check_local_ip((struct sockaddr*)&orig_dst)==1 && saport((struct sockaddr*)&orig_dst)==listen_port) { fprintf(stderr, "Dropping connection to local address to the same port to avoid loop\n"); close(local_fd); return NULL; } if((remote_fd = connect_remote(&orig_dst)) == 0){ fprintf(stderr, "Failed to connect\n"); close(remote_fd); close(local_fd); return NULL; } //Create connection object and fill in information if((conn = (tproxy_conn_t*) malloc(sizeof(tproxy_conn_t))) == NULL){ fprintf(stderr, "Could not allocate memory for connection\n"); close(remote_fd); close(local_fd); return NULL; } memset(conn, 0, sizeof(tproxy_conn_t)); conn->state = CONN_AVAILABLE; conn->remote_fd = remote_fd; conn->local_fd = local_fd; if(pipe(conn->splice_pipe) != 0){ fprintf(stderr, "Could not create the required pipe\n"); free_conn(conn); return NULL; } //remote_fd is connecting. Non-blocking connects are signaled as done by //socket being marked as ready for writing memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN | EPOLLOUT; ev.data.ptr = (void*) conn; if(epoll_ctl(efd, EPOLL_CTL_ADD, remote_fd, &ev) == -1){ perror("epoll_ctl (remote_fd)"); free_conn(conn); return NULL; } //Local socket can be closed while waiting for connection attempt. I need //to detect this when waiting for connect() to complete. However, I dont //want to get EPOLLIN-events, as I dont want to receive any data before //remote connection is established ev.events = EPOLLRDHUP; if(epoll_ctl(efd, EPOLL_CTL_ADD, local_fd, &ev) == -1){ perror("epoll_ctl (local_fd)"); free_conn(conn); return NULL; } else { TAILQ_INSERT_HEAD(conn_list, conn, conn_ptrs); return conn; } }
int cli_main(int argc, char ** argv) { #else int main(int argc, char ** argv) { #endif #if 0 int sock_in, sock_out; char* error = NULL; #endif _dropbear_exit = cli_dropbear_exit; _dropbear_log = cli_dropbear_log; disallow_core(); cli_getopts(argc, argv); #if 0 TRACE(("user='******' host='%s' port='%s'", cli_opts.username, cli_opts.remotehost, cli_opts.remoteport)) #endif TRACE(("user='******' remotehost='%s'", cli_opts.username, cli_opts.remote_name_str)); if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { dropbear_exit("signal() error"); } #if 0 #ifdef ENABLE_CLI_PROXYCMD if (cli_opts.proxycmd) { cli_proxy_cmd(&sock_in, &sock_out); m_free(cli_opts.proxycmd); } else #endif { int sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport, 0, &error); sock_in = sock_out = sock; } if (sock_in < 0) { dropbear_exit("%s", error); } cli_session(sock_in, sock_out); #endif srand(time(NULL)); cli_opts.ssh_ccn = ccn_create(); cli_opts.ccn_cached_keystore = ccn_init_keystore(); if( cli_opts.ssh_ccn == NULL || ccn_connect(cli_opts.ssh_ccn,NULL) == -1 ) dropbear_exit("Failed to connect to ccnd"); ccn_publish_host_key(); ccn_publish_client_mountpoint(); ccn_ssh_connect(cli_opts.remote_name_str); // Wait for server response ccn_run(cli_opts.ssh_ccn,-1); /* not reached */ return -1; }
static void init_local(CLI *c) { SOCKADDR_UNION addr; socklen_t addrlen; addrlen=sizeof addr; if(getpeername(c->local_rfd.fd, &addr.sa, &addrlen)<0) { strcpy(c->accepted_address, "NOT A SOCKET"); c->local_rfd.is_socket=0; c->local_wfd.is_socket=0; /* TODO: It's not always true */ #ifdef USE_WIN32 if(get_last_socket_error()!=ENOTSOCK) { #else if(c->opt->option.transparent_src || get_last_socket_error()!=ENOTSOCK) { #endif sockerror("getpeerbyname"); longjmp(c->err, 1); } /* ignore ENOTSOCK error so 'local' doesn't have to be a socket */ } else { /* success */ /* copy addr to c->peer_addr */ memcpy(&c->peer_addr.addr[0], &addr, sizeof addr); c->peer_addr.num=1; s_ntop(c->accepted_address, &c->peer_addr.addr[0]); c->local_rfd.is_socket=1; c->local_wfd.is_socket=1; /* TODO: It's not always true */ /* it's a socket: lets setup options */ if(set_socket_options(c->local_rfd.fd, 1)<0) longjmp(c->err, 1); #ifdef USE_LIBWRAP libwrap_auth(c); #endif /* USE_LIBWRAP */ auth_user(c); s_log(LOG_NOTICE, "Service %s accepted connection from %s", c->opt->servname, c->accepted_address); } } static void init_remote(CLI *c) { /* create connection to host/service */ if(c->opt->source_addr.num) memcpy(&c->bind_addr, &c->opt->source_addr, sizeof(SOCKADDR_LIST)); #ifndef USE_WIN32 else if(c->opt->option.transparent_src) memcpy(&c->bind_addr, &c->peer_addr, sizeof(SOCKADDR_LIST)); #endif else { c->bind_addr.num=0; /* don't bind connecting socket */ } /* setup c->remote_fd, now */ if(c->opt->option.remote) c->remote_fd.fd=connect_remote(c); #ifdef SO_ORIGINAL_DST else if(c->opt->option.transparent_dst) c->remote_fd.fd=connect_transparent(c); #endif /* SO_ORIGINAL_DST */ else /* NOT in remote mode */ c->remote_fd.fd=connect_local(c); c->remote_fd.is_socket=1; /* always! */ s_log(LOG_DEBUG, "Remote FD=%d initialized", c->remote_fd.fd); if(set_socket_options(c->remote_fd.fd, 2)<0) longjmp(c->err, 1); } static void init_ssl(CLI *c) { int i, err; SSL_SESSION *old_session; if(!(c->ssl=SSL_new(c->opt->ctx))) { sslerror("SSL_new"); longjmp(c->err, 1); } SSL_set_ex_data(c->ssl, cli_index, c); /* for callbacks */ SSL_set_session_id_context(c->ssl, (unsigned char *)sid_ctx, strlen(sid_ctx)); if(c->opt->option.client) { #ifndef OPENSSL_NO_TLSEXT if(c->opt->host_name) { s_log(LOG_DEBUG, "SNI: host name: %s", c->opt->host_name); if(!SSL_set_tlsext_host_name(c->ssl, c->opt->host_name)) { sslerror("SSL_set_tlsext_host_name"); longjmp(c->err, 1); } } #endif if(c->opt->session) { enter_critical_section(CRIT_SESSION); SSL_set_session(c->ssl, c->opt->session); leave_critical_section(CRIT_SESSION); } SSL_set_fd(c->ssl, c->remote_fd.fd); SSL_set_connect_state(c->ssl); } else { if(c->local_rfd.fd==c->local_wfd.fd) SSL_set_fd(c->ssl, c->local_rfd.fd); else { /* does it make sence to have SSL on STDIN/STDOUT? */ SSL_set_rfd(c->ssl, c->local_rfd.fd); SSL_set_wfd(c->ssl, c->local_wfd.fd); } SSL_set_accept_state(c->ssl); } /* setup some values for transfer() function */ if(c->opt->option.client) { c->sock_rfd=&(c->local_rfd); c->sock_wfd=&(c->local_wfd); c->ssl_rfd=c->ssl_wfd=&(c->remote_fd); } else { c->sock_rfd=c->sock_wfd=&(c->remote_fd); c->ssl_rfd=&(c->local_rfd); c->ssl_wfd=&(c->local_wfd); } while(1) { #if OPENSSL_VERSION_NUMBER<0x1000002f /* this critical section is a crude workaround for CVE-2010-3864 * * see http://www.securityfocus.com/bid/44884 for details * * NOTE: this critical section also covers callbacks (e.g. OCSP) */ enter_critical_section(CRIT_SSL); #endif /* OpenSSL version < 1.0.0b */ if(c->opt->option.client) i=SSL_connect(c->ssl); else i=SSL_accept(c->ssl); #if OPENSSL_VERSION_NUMBER<0x1000002f leave_critical_section(CRIT_SSL); #endif /* OpenSSL version < 1.0.0b */ err=SSL_get_error(c->ssl, i); if(err==SSL_ERROR_NONE) break; /* ok -> done */ if(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE) { s_poll_init(&c->fds); s_poll_add(&c->fds, c->ssl_rfd->fd, err==SSL_ERROR_WANT_READ, err==SSL_ERROR_WANT_WRITE); switch(s_poll_wait(&c->fds, c->opt->timeout_busy, 0)) { case -1: sockerror("init_ssl: s_poll_wait"); longjmp(c->err, 1); case 0: s_log(LOG_INFO, "init_ssl: s_poll_wait:" " TIMEOUTbusy exceeded: sending reset"); longjmp(c->err, 1); case 1: break; /* OK */ default: s_log(LOG_ERR, "init_ssl: s_poll_wait: unknown result"); longjmp(c->err, 1); } continue; /* ok -> retry */ } if(err==SSL_ERROR_SYSCALL) { switch(get_last_socket_error()) { case EINTR: case EAGAIN: continue; } } if(c->opt->option.client) sslerror("SSL_connect"); else sslerror("SSL_accept"); longjmp(c->err, 1); } if(SSL_session_reused(c->ssl)) { s_log(LOG_INFO, "SSL %s: previous session reused", c->opt->option.client ? "connected" : "accepted"); } else { /* a new session was negotiated */ if(c->opt->option.client) { s_log(LOG_INFO, "SSL connected: new session negotiated"); enter_critical_section(CRIT_SESSION); old_session=c->opt->session; c->opt->session=SSL_get1_session(c->ssl); /* store it */ if(old_session) SSL_SESSION_free(old_session); /* release the old one */ leave_critical_section(CRIT_SESSION); } else s_log(LOG_INFO, "SSL accepted: new session negotiated"); print_cipher(c); } }
static int init_local(CLI *c) { int addrlen; addrlen=sizeof(c->addr); if(getpeername(c->local_rfd.fd, (struct sockaddr *)&c->addr, &addrlen)<0) { strcpy(c->accepting_address, "NOT A SOCKET"); c->local_rfd.is_socket=0; c->local_wfd.is_socket=0; /* TODO: It's not always true */ #ifdef USE_WIN32 if(get_last_socket_error()!=ENOTSOCK) { #else if(c->opt->option.transparent || get_last_socket_error()!=ENOTSOCK) { #endif sockerror("getpeerbyname"); return -1; } /* Ignore ENOTSOCK error so 'local' doesn't have to be a socket */ } else { safe_ntoa(c->accepting_address, c->addr.sin_addr); c->local_rfd.is_socket=1; c->local_wfd.is_socket=1; /* TODO: It's not always true */ /* It's a socket: lets setup options */ if(set_socket_options(c->local_rfd.fd, 1)<0) return -1; if(auth_libwrap(c)<0) return -1; if(auth_user(c)<0) { log(LOG_WARNING, "Connection from %s:%d REFUSED by IDENT", c->accepting_address, ntohs(c->addr.sin_port)); return -1; } log(LOG_NOTICE, "%s connected from %s:%d", c->opt->servname, c->accepting_address, ntohs(c->addr.sin_port)); } return 0; /* OK */ } static int init_remote(CLI *c) { int fd; /* create connection to host/service */ if(c->opt->local_ip) c->bind_ip=*c->opt->local_ip; #ifndef USE_WIN32 else if(c->opt->option.transparent) c->bind_ip=c->addr.sin_addr.s_addr; #endif else c->bind_ip=0; /* Setup c->remote_fd, now */ if(c->opt->option.remote) { c->resolved_addresses=NULL; fd=connect_remote(c); if(c->resolved_addresses) /* allocated */ free(c->resolved_addresses); } else /* NOT in remote mode */ fd=connect_local(c); if(fd<0) { log(LOG_ERR, "Failed to initialize remote connection"); return -1; } #ifndef USE_WIN32 if(fd>=max_fds) { log(LOG_ERR, "Remote file descriptor out of range (%d>=%d)", fd, max_fds); closesocket(fd); return -1; } #endif log(LOG_DEBUG, "Remote FD=%d initialized", fd); c->remote_fd.fd=fd; c->remote_fd.is_socket=1; /* Always! */ if(set_socket_options(fd, 2)<0) return -1; return 0; /* OK */ }