Example #1
0
NOEXPORT void proxy_server(CLI *c) {
    SOCKADDR_UNION addr;
    socklen_t addrlen;
    char src_host[IP_LEN], dst_host[IP_LEN];
    char src_port[PORT_LEN], dst_port[PORT_LEN], *proto;
    int err;

    addrlen=sizeof addr;
    if(getpeername(c->local_rfd.fd, &addr.sa, &addrlen)) {
        sockerror("getpeername");
        longjmp(c->err, 1);
    }
    err=getnameinfo(&addr.sa, addr_len(&addr), src_host, IP_LEN,
        src_port, PORT_LEN, NI_NUMERICHOST|NI_NUMERICSERV);
    if(err) {
        s_log(LOG_ERR, "getnameinfo: %s", s_gai_strerror(err));
        longjmp(c->err, 1);
    }

    addrlen=sizeof addr;
    if(getsockname(c->local_rfd.fd, &addr.sa, &addrlen)) {
        sockerror("getsockname");
        longjmp(c->err, 1);
    }
    err=getnameinfo(&addr.sa, addr_len(&addr), dst_host, IP_LEN,
        dst_port, PORT_LEN, NI_NUMERICHOST|NI_NUMERICSERV);
    if(err) {
        s_log(LOG_ERR, "getnameinfo: %s", s_gai_strerror(err));
        longjmp(c->err, 1);
    }

    switch(addr.sa.sa_family) {
    case AF_INET:
        proto="TCP4";
        break;
#ifdef USE_IPv6
    case AF_INET6:
        proto="TCP6";
        break;
#endif
    default: /* AF_UNIX */
        proto="UNKNOWN";
    }
    fd_printf(c, c->remote_fd.fd, "PROXY %s %s %s %s %s",
        proto, src_host, dst_host, src_port, dst_port);
}
Example #2
0
int hostport2addrlist(SOCKADDR_LIST *addr_list,
        char *hostname, char *portname) {
    struct addrinfo hints, *res=NULL, *cur;
    int err;

    addr_list->cur=0; /* initialize round-robin counter */

    memset(&hints, 0, sizeof hints);
#if defined(USE_IPv6) || defined(USE_WIN32)
    hints.ai_family=PF_UNSPEC;
#else
    hints.ai_family=PF_INET;
#endif
    hints.ai_socktype=SOCK_STREAM;
    hints.ai_protocol=IPPROTO_TCP;
    do {
        err=getaddrinfo(hostname, portname, &hints, &res);
        if(err && res)
            freeaddrinfo(res);
        if(err==EAI_AGAIN) {
            s_log(LOG_DEBUG, "getaddrinfo: EAI_AGAIN received: retrying");
            sleep(1);
        }
    } while(err==EAI_AGAIN);
    switch(err) {
    case 0:
        break; /* success */
    case EAI_SERVICE:
        s_log(LOG_ERR, "Unknown TCP service '%s'", portname);
        return 0; /* error */
    default:
        s_log(LOG_ERR, "Error resolving '%s': %s",
            hostname, s_gai_strerror(err));
        return 0; /* error */
    }

    /* copy the list of addresses */
    for(cur=res; cur && addr_list->num<MAX_HOSTS;
            cur=cur->ai_next, addr_list->num++) {
        if(cur->ai_addrlen>sizeof(SOCKADDR_UNION)) {
            s_log(LOG_ERR, "INTERNAL ERROR: ai_addrlen value too big");
            freeaddrinfo(res);
            return 0; /* no results */
        }
        memcpy(&addr_list->addr[addr_list->num],
            cur->ai_addr, cur->ai_addrlen);
    }
    freeaddrinfo(res);
    return addr_list->num; /* ok - return the number of addresses */
}
Example #3
0
char *s_ntop(SOCKADDR_UNION *addr, socklen_t addrlen) {
    int err;
    char *host, *port, *retval;

    if(addrlen==sizeof(u_short)) /* see UNIX(7) manual for details */
        return str_dup("unnamed socket");
    host=str_alloc(256);
    port=str_alloc(256); /* needs to be long enough for AF_UNIX path */
    err=getnameinfo(&addr->sa, addrlen,
        host, 256, port, 256, NI_NUMERICHOST|NI_NUMERICSERV);
    if(err) {
        s_log(LOG_ERR, "getnameinfo: %s", s_gai_strerror(err));
        retval=str_dup("unresolvable address");
    } else
        retval=str_printf("%s:%s", host, port);
    str_free(host);
    str_free(port);
    return retval;
}
Example #4
0
int hostport2addrlist(SOCKADDR_LIST *addr_list,
        char *hostname, char *portname) {
    struct addrinfo hints, *res=NULL, *cur;
    int err;

    addr_list->cur=0; /* initialize round-robin counter */

    memset(&hints, 0, sizeof(hints));
#if defined(USE_IPv6) || defined(USE_WIN32)
    hints.ai_family=PF_UNSPEC;
#else
    hints.ai_family=PF_INET;
#endif
    hints.ai_socktype=SOCK_STREAM;
    hints.ai_protocol=IPPROTO_TCP;

    err=getaddrinfo(hostname, portname, &hints, &res);
    if(err) {
        if(err == EAI_SERVICE)
	    s_log(LOG_ERR, "Unknown TCP service '%s'", portname);
	else
	    s_log(LOG_ERR, "Error resolving '%s': %s",
		hostname, s_gai_strerror(err));
        if(res)
            freeaddrinfo(res);
        return 0; /* Error */
    }
    /* copy the list of addresses */
    cur=res;
    while(cur && addr_list->num<MAX_HOSTS) {
        if(cur->ai_addrlen>sizeof(SOCKADDR_UNION)) {
            s_log(LOG_ERR, "INTERNAL ERROR: ai_addrlen value too big");
            freeaddrinfo(res);
            return 0; /* no results */
        }
        memcpy(&addr_list->addr[addr_list->num],
            cur->ai_addr, cur->ai_addrlen);
        cur=cur->ai_next;
        addr_list->num++;
    }
    freeaddrinfo(res);
    return addr_list->num; /* ok - return the number of addresses */
}
Example #5
0
unsigned hostport2addrlist(SOCKADDR_LIST *addr_list,
        char *host_name, char *port_name) {
    struct addrinfo hints, *res=NULL, *cur;
    int err, retry=0;

    memset(&hints, 0, sizeof hints);
#if defined(USE_IPv6) || defined(USE_WIN32)
    hints.ai_family=AF_UNSPEC;
#else
    hints.ai_family=AF_INET;
#endif
    hints.ai_socktype=SOCK_STREAM;
    hints.ai_protocol=IPPROTO_TCP;
    hints.ai_flags=0;
    if(addr_list->passive) {
        hints.ai_family=AF_INET; /* first try IPv4 for passive requests */
        hints.ai_flags|=AI_PASSIVE;
    }
    for(;;) {
        err=getaddrinfo(host_name, port_name, &hints, &res);
        if(!err)
            break;
        if(res)
            freeaddrinfo(res);
        if(err==EAI_AGAIN && ++retry<=3) {
            s_log(LOG_DEBUG, "getaddrinfo: EAI_AGAIN received: retrying");
            sleep(1);
            continue;
        }
#if defined(USE_IPv6) || defined(USE_WIN32)
        if(hints.ai_family==AF_INET) {
            hints.ai_family=AF_UNSPEC;
            continue; /* retry for non-IPv4 addresses */
        }
#endif
        break;
    }
    if(err==EAI_SERVICE) {
        s_log(LOG_ERR, "Unknown TCP service \"%s\"", port_name);
        return 0; /* error */
    }
    if(err) {
        s_log(LOG_ERR, "Error resolving \"%s\": %s",
            host_name ? host_name :
                (addr_list->passive ? DEFAULT_ANY : DEFAULT_LOOPBACK),
            s_gai_strerror(err));
        return 0; /* error */
    }

    /* copy the list of addresses */
    for(cur=res; cur; cur=cur->ai_next) {
        if(cur->ai_addrlen>(int)sizeof(SOCKADDR_UNION)) {
            s_log(LOG_ERR, "INTERNAL ERROR: ai_addrlen value too big");
            freeaddrinfo(res);
            return 0; /* no results */
        }
        addr_list->addr=str_realloc(addr_list->addr,
            (addr_list->num+1)*sizeof(SOCKADDR_UNION));
        memcpy(&addr_list->addr[addr_list->num], cur->ai_addr,
            (size_t)cur->ai_addrlen);
        ++(addr_list->num);
    }
    freeaddrinfo(res);
    return addr_list->num; /* ok - return the number of addresses */
}