NOEXPORT void socks5_client_address(CLI *c) {
    SOCKADDR_UNION addr;
    SOCKS5_UNION socks;

    if(original_dst(c->local_rfd.fd, &addr))
        throw_exception(c, 2); /* don't reset */
    memset(&socks, 0, sizeof socks);
    socks.req.ver=5; /* SOCKS5 */
    socks.req.cmd=0x01; /* CONNECT */
    switch(addr.sa.sa_family) {
    case AF_INET:
        socks.req.atyp=0x01; /* IP v4 address */
        memcpy(&socks.v4.addr, &addr.in.sin_addr, 4);
        memcpy(&socks.v4.port, &addr.in.sin_port, 2);
        s_log(LOG_INFO, "Sending SOCKS5 IPv4 address");
        s_ssl_write(c, &socks, sizeof socks.v4);
        break;
#ifdef USE_IPv6
    case AF_INET6:
        socks.req.atyp=0x04; /* IP v6 address */
        memcpy(&socks.v6.addr, &addr.in6.sin6_addr, 16);
        memcpy(&socks.v6.port, &addr.in6.sin6_port, 2);
        s_log(LOG_INFO, "Sending SOCKS5 IPv6 address");
        s_ssl_write(c, &socks, sizeof socks.v6);
        break;
#endif
    default:
        s_log(LOG_ERR, "Unsupported address type 0x%02x", addr.sa.sa_family);
        throw_exception(c, 2); /* don't reset */
    }

    s_ssl_read(c, &socks, sizeof socks.resp);
    if(socks.resp.atyp==0x04) /* IP V6 address */
        s_ssl_read(c, &socks.v6.addr, 16+2);
    else
        s_ssl_read(c, &socks.v4.addr, 4+2);
    if(socks.resp.ver!=5) {
        s_log(LOG_ERR, "Invalid SOCKS5 message version 0x%02x", socks.req.ver);
        throw_exception(c, 2); /* don't reset */
    }
    switch(socks.resp.rep) {
        case 0x00:
            s_log(LOG_INFO,
                "SOCKS5 request succeeded");
            return; /* SUCCESS */
        case 0x01:
            s_log(LOG_ERR,
                "SOCKS5 request failed: General SOCKS server failure");
            break;
        case 0x02:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Connection not allowed by ruleset");
            break;
        case 0x03:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Network unreachable");
            break;
        case 0x04:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Host unreachable");
            break;
        case 0x05:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Connection refused");
            break;
        case 0x06:
            s_log(LOG_ERR,
                "SOCKS5 request failed: TTL expired");
            break;
        case 0x07:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Command not supported");
            break;
        case 0x08:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Address type not supported");
            break;
        default:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Unknown error 0x%02x", socks.resp.rep);
    }
    throw_exception(c, 2); /* don't reset */
}
NOEXPORT void socks5_client_address(CLI *c) {
    SOCKADDR_UNION addr;
    SOCKS5_UNION socks;

    if(original_dst(c->local_rfd.fd, &addr))
        throw_exception(c, 2);  
    memset(&socks, 0, sizeof socks);
    socks.req.ver=5;  
    socks.req.cmd=0x01;  
    switch(addr.sa.sa_family) {
    case AF_INET:
        socks.req.atyp=0x01;  
        memcpy(&socks.v4.addr, &addr.in.sin_addr, 4);
        memcpy(&socks.v4.port, &addr.in.sin_port, 2);
        s_log(LOG_INFO, "Sending SOCKS5 IPv4 address");
        s_ssl_write(c, &socks, sizeof socks.v4);
        break;
#ifdef USE_IPv6
    case AF_INET6:
        socks.req.atyp=0x04;  
        memcpy(&socks.v6.addr, &addr.in6.sin6_addr, 16);
        memcpy(&socks.v6.port, &addr.in6.sin6_port, 2);
        s_log(LOG_INFO, "Sending SOCKS5 IPv6 address");
        s_ssl_write(c, &socks, sizeof socks.v6);
        break;
#endif
    default:
        s_log(LOG_ERR, "Unsupported address type 0x%02x", addr.sa.sa_family);
        throw_exception(c, 2);  
    }

    s_ssl_read(c, &socks, sizeof socks.resp);
    if(socks.resp.atyp==0x04)  
        s_ssl_read(c, &socks.v6.addr, 16+2);
    else
        s_ssl_read(c, &socks.v4.addr, 4+2);
    if(socks.resp.ver!=5) {
        s_log(LOG_ERR, "Invalid SOCKS5 message version 0x%02x", socks.req.ver);
        throw_exception(c, 2);  
    }
    switch(socks.resp.rep) {
        case 0x00:
            s_log(LOG_INFO,
                "SOCKS5 request succeeded");
            return;  
        case 0x01:
            s_log(LOG_ERR,
                "SOCKS5 request failed: General SOCKS server failure");
            break;
        case 0x02:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Connection not allowed by ruleset");
            break;
        case 0x03:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Network unreachable");
            break;
        case 0x04:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Host unreachable");
            break;
        case 0x05:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Connection refused");
            break;
        case 0x06:
            s_log(LOG_ERR,
                "SOCKS5 request failed: TTL expired");
            break;
        case 0x07:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Command not supported");
            break;
        case 0x08:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Address type not supported");
            break;
        default:
            s_log(LOG_ERR,
                "SOCKS5 request failed: Unknown error 0x%02x", socks.resp.rep);
    }
    throw_exception(c, 2);  
}