示例#1
0
static SOCKADDR_LIST *dynamic_remote_addr(CLI *c) {
#ifdef SO_ORIGINAL_DST
    socklen_t addrlen=sizeof(SOCKADDR_UNION);
#endif /* SO_ORIGINAL_DST */

    /* check if the address was already set by a dynamic protocol
     * implemented protocols: CONNECT
     * protocols to be implemented: SOCKS4 */
    if(c->connect_addr.num)
        return &c->connect_addr;

#ifdef SO_ORIGINAL_DST
    if(c->opt->option.transparent_dst) {
        c->connect_addr.num=1;
        c->connect_addr.addr=str_alloc(sizeof(SOCKADDR_UNION));
        if(getsockopt(c->local_rfd.fd, SOL_IP, SO_ORIGINAL_DST,
                c->connect_addr.addr, &addrlen)) {
            sockerror("setsockopt SO_ORIGINAL_DST");
            longjmp(c->err, 1);
        }
        return &c->connect_addr;
    }
#endif /* SO_ORIGINAL_DST */

    if(c->opt->option.delayed_lookup) {
        if(!name2addrlist(&c->connect_addr,
                c->opt->connect_name, DEFAULT_LOOPBACK)) {
            s_log(LOG_ERR, "No host resolved");
            longjmp(c->err, 1);
        }
        return &c->connect_addr;
    }

    return &c->opt->connect_addr; /* use pre-resolved (static) addresses */
}
示例#2
0
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;
}
示例#3
0
int name2addr(SOCKADDR_UNION *addr, char *name, char *default_host) {
    SOCKADDR_LIST addr_list;
    int retval;

    addr_list.num=0;
    addr_list.addr=NULL;
    retval=name2addrlist(&addr_list, name, default_host);
    if(retval>0)
        memcpy(addr, &addr_list.addr[0], sizeof *addr);
    if(addr_list.addr)
        str_free(addr_list.addr);
    return retval;
}
示例#4
0
unsigned name2addr(SOCKADDR_UNION *addr, char *name, int passive) {
    SOCKADDR_LIST *addr_list;
    unsigned retval;

    addr_list=str_alloc(sizeof(SOCKADDR_LIST));
    addrlist_clear(addr_list, passive);
    retval=name2addrlist(addr_list, name);
    if(retval)
        addrlist2addr(addr, addr_list);
    str_free(addr_list->addr);
    str_free(addr_list);
    return retval;
}
示例#5
0
文件: client.c 项目: l7s/stunnel
static int connect_remote(CLI *c) { /* connect remote host */
    SOCKADDR_UNION addr;
    SOCKADDR_LIST resolved_list, *address_list;
    int fd, ind_try, ind_cur;

    /* setup address_list */
    if(c->opt->option.delayed_lookup) {
        resolved_list.num=0;
        if(!name2addrlist(&resolved_list,
                c->opt->remote_address, DEFAULT_LOOPBACK)) {
            s_log(LOG_ERR, "No host resolved");
            longjmp(c->err, 1);
        }
        address_list=&resolved_list;
    } else /* use pre-resolved addresses */
        address_list=&c->opt->remote_addr;

    /* try to connect each host from the list */
    for(ind_try=0; ind_try<address_list->num; ind_try++) {
        if(c->opt->failover==FAILOVER_RR) {
            ind_cur=address_list->cur;
            /* the race condition here can be safely ignored */
            address_list->cur=(ind_cur+1)%address_list->num;
        } else { /* FAILOVER_PRIO */
            ind_cur=ind_try; /* ignore address_list->cur */
        }
        memcpy(&addr, address_list->addr+ind_cur, sizeof addr);

        c->fd=s_socket(addr.sa.sa_family, SOCK_STREAM, 0, 1, "remote socket");
        if(c->fd<0)
            longjmp(c->err, 1);

        if(c->bind_addr.num) /* explicit local bind or transparent proxy */
            local_bind(c);

        if(connect_blocking(c, &addr, addr_len(addr))) {
            closesocket(c->fd);
            c->fd=-1;
            continue; /* next IP */
        }
        print_bound_address(c);
        fd=c->fd;
        c->fd=-1;
        return fd; /* success! */
    }
    longjmp(c->err, 1);
    return -1; /* some C compilers require a return value */
}
示例#6
0
static SOCKADDR_LIST *dynamic_remote_addr(CLI * c)
{
	if (c->connect_addr.num)
		return &c->connect_addr;

	if (c->opt->option.delayed_lookup) {
		if (!name2addrlist(&c->connect_addr,
				   c->opt->connect_name, DEFAULT_LOOPBACK)) {
			s_log(LOG_ERR, "No host resolved");
			longjmp(c->err, 1);
		}
		return &c->connect_addr;
	}

	return &c->opt->connect_addr;	
}
示例#7
0
unsigned addrlist_resolve(SOCKADDR_LIST *addr_list) {
    unsigned num=0, rnd;
    NAME_LIST *host;

    addrlist_reset(addr_list);
    for(host=addr_list->names; host; host=host->next)
        num+=name2addrlist(addr_list, host->name);
    switch(num) {
    case 0:
    case 1:
        addr_list->rr_val=0;
        break;
    default:
        /* randomize the initial value of round-robin counter */
        /* ignore the error value and the distribution bias */
        RAND_bytes((unsigned char *)&rnd, sizeof rnd);
        addr_list->rr_val=rnd%num;
    }
    return num;
}