static int connect_remote(CLI *c) { /* connect to remote host */ SOCKADDR_UNION bind_addr, addr; SOCKADDR_LIST resolved_list, *address_list; int error; int s; /* destination socket */ u16 i; /* setup address_list */ if(c->opt->option.delayed_lookup) { resolved_list.num=0; if(!name2addrlist(&resolved_list, c->opt->remote_address, DEFAULT_LOOPBACK)) return -1; /* no host resolved */ address_list=&resolved_list; } else /* use pre-resolved addresses */ address_list=&c->opt->remote_addr; /* try to connect each host from the list */ for(i=0; i<address_list->num; i++) { memcpy(&addr, address_list->addr + address_list->cur, sizeof(SOCKADDR_UNION)); address_list->cur=(address_list->cur+1)%address_list->num; /* race condition is possible, but harmless in this case */ if((s=socket(addr.sa.sa_family, SOCK_STREAM, 0))<0) { sockerror("remote socket"); return -1; } if(alloc_fd(s)) return -1; if(c->bind_addr.num) { /* explicit local bind or transparent proxy */ memcpy(&bind_addr, &c->bind_addr.addr[0], sizeof(SOCKADDR_UNION)); if(bind(s, &bind_addr.sa, addr_len(bind_addr))<0) { sockerror("bind transparent"); closesocket(s); return -1; } } /* try to connect for the 1st time */ s_ntop(c->connecting_address, &addr); s_log(LOG_DEBUG, "%s connecting %s", c->opt->servname, c->connecting_address); if(!connect(s, &addr.sa, addr_len(addr))) return s; /* no error -> success (should not be possible) */ error=get_last_socket_error(); if(error!=EINPROGRESS && error!=EWOULDBLOCK) { s_log(LOG_ERR, "remote connect (%s): %s (%d)", c->connecting_address, my_strerror(error), error); closesocket(s); continue; /* next IP */ } if(!connect_wait(c, s, c->opt->timeout_connect)) return s; /* success! */ closesocket(s); /* error -> next IP */ } return -1; }
static int auth_user(CLI *c) { struct servent *s_ent; /* structure for getservbyname */ SOCKADDR_UNION ident; /* IDENT socket name */ int fd; /* IDENT socket descriptor */ char name[STRLEN]; int retval; int error; if(!c->opt->username) return 0; /* -u option not specified */ if((fd=socket(c->peer_addr.addr[0].sa.sa_family, SOCK_STREAM, 0))<0) { sockerror("socket (auth_user)"); return -1; } if(alloc_fd(fd)) return -1; memcpy(&ident, &c->peer_addr.addr[0], sizeof(SOCKADDR_UNION)); s_ent=getservbyname("auth", "tcp"); if(s_ent) { ident.in.sin_port=s_ent->s_port; } else { s_log(LOG_WARNING, "Unknown service 'auth': using default 113"); ident.in.sin_port=htons(113); } if(connect(fd, &ident.sa, addr_len(ident))) { error=get_last_socket_error(); if(error!=EINPROGRESS && error!=EWOULDBLOCK) { sockerror("ident connect (auth_user)"); closesocket(fd); return -1; } if(connect_wait(c, fd, c->opt->timeout_connect)) { /* error */ closesocket(fd); return -1; } } s_log(LOG_DEBUG, "IDENT server connected"); if(fdprintf(c, fd, "%u , %u", ntohs(c->peer_addr.addr[0].in.sin_port), ntohs(c->opt->local_addr.addr[0].in.sin_port))<0) { sockerror("fdprintf (auth_user)"); closesocket(fd); return -1; } if(fdscanf(c, fd, "%*[^:]: USERID :%*[^:]:%s", name)!=1) { s_log(LOG_ERR, "Incorrect data from IDENT server"); closesocket(fd); return -1; } closesocket(fd); retval=strcmp(name, c->opt->username) ? -1 : 0; safestring(name); s_log(LOG_INFO, "IDENT resolved remote user to %s", name); return retval; }
void connect_target(msyncdata *md) { struct timeval tv; md->s = connect_socket(md->target); if(md->s == -1){ fprintf(stderr, "can't connect %s\n", md->target); exit(1); } tv.tv_sec = 5; tv.tv_usec = 0; setsockopt(md->s, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv)); if(connect_wait(md)){ close(md->s); exit(1); } }