From 5cd294879b2f05800596280e37aaa8e956c0978c Mon Sep 17 00:00:00 2001 From: Max Lv Date: Sat, 12 Nov 2016 11:01:05 +0800 Subject: [PATCH] Add -6 option for #942 --- src/acl.c | 3 ++- src/cache.c | 2 +- src/local.c | 25 +++++++++++++++++-------- src/manager.c | 4 ++-- src/netutils.c | 8 +++++--- src/netutils.h | 4 +++- src/redir.c | 16 ++++++++++++---- src/server.c | 9 +++++---- src/tls.c | 4 ++-- src/tunnel.c | 18 +++++++++++++----- 10 files changed, 62 insertions(+), 31 deletions(-) diff --git a/src/acl.c b/src/acl.c index 46a613cf..76d76170 100644 --- a/src/acl.c +++ b/src/acl.c @@ -134,7 +134,8 @@ init_firewall() fp = popen(cli, "r"); if (fp == NULL) return -1; - if (pclose(fp) == 0) mode = IPTABLES_MODE; + if (pclose(fp) == 0) + mode = IPTABLES_MODE; } sprintf(chain_name, "SHADOWSOCKS_LIBEV_%d", getpid()); diff --git a/src/cache.c b/src/cache.c index 0b1268e8..127792d9 100644 --- a/src/cache.c +++ b/src/cache.c @@ -283,7 +283,7 @@ cache_insert(struct cache *cache, char *key, size_t key_len, void *data) entry->key = ss_malloc(key_len); memcpy(entry->key, key, key_len); entry->data = data; - entry->ts = ev_time(); + entry->ts = ev_time(); HASH_ADD_KEYPTR(hh, cache->entries, entry->key, key_len, entry); if (HASH_COUNT(cache->entries) >= cache->max_entries) { diff --git a/src/local.c b/src/local.c index 4054a10f..8066d47f 100644 --- a/src/local.c +++ b/src/local.c @@ -91,8 +91,9 @@ ev_tstamp last = 0; char *prefix; #endif -static int acl = 0; -static int mode = TCP_ONLY; +static int acl = 0; +static int mode = TCP_ONLY; +static int ipv6first = 0; static int fast_open = 0; #ifdef HAVE_SETRLIMIT @@ -634,9 +635,9 @@ server_recv_cb(EV_P_ ev_io *w, int revents) int err; memset(&storage, 0, sizeof(struct sockaddr_storage)); if (atyp == 1 || atyp == 4) { - err = get_sockaddr(ip, port, &storage, 0); + err = get_sockaddr(ip, port, &storage, 0, ipv6first); } else { - err = get_sockaddr(host, port, &storage, 1); + err = get_sockaddr(host, port, &storage, 1, ipv6first); } if (err != -1) { remote = create_remote(server->listener, (struct sockaddr *)&storage); @@ -737,6 +738,7 @@ stat_update_cb() last = now; } } + #endif static void @@ -1154,10 +1156,10 @@ main(int argc, char **argv) USE_TTY(); #ifdef ANDROID - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:n:P:huUvVA", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:n:P:huUvVA6", long_options, &option_index)) != -1) { #else - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:n:huUvA", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:n:huUvA6", long_options, &option_index)) != -1) { #endif switch (c) { @@ -1235,6 +1237,9 @@ main(int argc, char **argv) case 'A': auth = 1; break; + case '6': + ipv6first = 1; + break; #ifdef ANDROID case 'V': vpn = 1; @@ -1352,6 +1357,10 @@ main(int argc, char **argv) #endif } + if (ipv6first) { + LOGI("resolving hostname to IPv6 address first"); + } + if (auth) { LOGI("onetime authentication enabled"); } @@ -1380,7 +1389,7 @@ main(int argc, char **argv) remote_addr[i].port; struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage)); memset(storage, 0, sizeof(struct sockaddr_storage)); - if (get_sockaddr(host, port, storage, 1) == -1) { + if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) { FATAL("failed to resolve the provided hostname"); } listen_ctx.remote_addr[i] = (struct sockaddr *)storage; @@ -1536,7 +1545,7 @@ start_ss_local_server(profile_t profile) struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage)); memset(storage, 0, sizeof(struct sockaddr_storage)); - if (get_sockaddr(remote_host, remote_port_str, storage, 1) == -1) { + if (get_sockaddr(remote_host, remote_port_str, storage, 1, ipv6first) == -1) { return -1; } diff --git a/src/manager.c b/src/manager.c index d237ea5a..7ef7459c 100644 --- a/src/manager.c +++ b/src/manager.c @@ -618,7 +618,7 @@ main(int argc, char **argv) int mtu = 0; #ifdef HAVE_SETRLIMIT -static int nofile = 0; + static int nofile = 0; #endif int server_num = 0; @@ -838,7 +838,7 @@ static int nofile = 0; manager.nameserver_num = nameserver_num; manager.mtu = mtu; #ifdef HAVE_SETRLIMIT - manager.nofile = nofile; + manager.nofile = nofile; #endif // initialize ev loop diff --git a/src/netutils.c b/src/netutils.c index ccdfaeba..1df1bac7 100644 --- a/src/netutils.c +++ b/src/netutils.c @@ -118,7 +118,9 @@ bind_to_address(int socket_fd, const char *host) } ssize_t -get_sockaddr(char *host, char *port, struct sockaddr_storage *storage, int block) +get_sockaddr(char *host, char *port, + struct sockaddr_storage *storage, int block, + int ipv6first) { struct cork_ip ip; if (cork_ip_init(&ip, host) != -1) { @@ -167,8 +169,9 @@ get_sockaddr(char *host, char *port, struct sockaddr_storage *storage, int block return -1; } + int prefer_af = ipv6first ? AF_INET6 : AF_INET; for (rp = result; rp != NULL; rp = rp->ai_next) - if (rp->ai_family == AF_INET) { + if (rp->ai_family == prefer_af) { memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in)); break; } @@ -299,4 +302,3 @@ validate_hostname(const char *hostname, const int hostname_len) return 1; } - diff --git a/src/netutils.h b/src/netutils.h index 756d0c1e..07255923 100644 --- a/src/netutils.h +++ b/src/netutils.h @@ -61,7 +61,9 @@ #define INET6_SIZE 16 size_t get_sockaddr_len(struct sockaddr *addr); -ssize_t get_sockaddr(char *host, char *port, struct sockaddr_storage *storage, int block); +ssize_t get_sockaddr(char *host, char *port, + struct sockaddr_storage *storage, int block, + int ipv6first); int set_reuseport(int socket); #ifdef SET_INTERFACE diff --git a/src/redir.c b/src/redir.c index 67047ffb..8daeb2f2 100644 --- a/src/redir.c +++ b/src/redir.c @@ -86,8 +86,9 @@ static void close_and_free_server(EV_P_ server_t *server); int verbose = 0; int keep_resolving = 1; -static int mode = TCP_ONLY; -static int auth = 0; +static int ipv6first = 0; +static int mode = TCP_ONLY; +static int auth = 0; #ifdef HAVE_SETRLIMIT static int nofile = 0; #endif @@ -781,7 +782,7 @@ main(int argc, char **argv) USE_TTY(); - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUvA", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUvA6", long_options, &option_index)) != -1) { switch (c) { case 0: @@ -850,6 +851,9 @@ main(int argc, char **argv) case 'A': auth = 1; break; + case '6': + ipv6first = 1; + break; case '?': // The option character is not recognized. LOGE("Unrecognized option: %s", optarg); @@ -946,6 +950,10 @@ main(int argc, char **argv) daemonize(pid_path); } + if (ipv6first) { + LOGI("resolving hostname to IPv6 address first"); + } + if (auth) { LOGI("onetime authentication enabled"); } @@ -970,7 +978,7 @@ main(int argc, char **argv) remote_addr[i].port; struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage)); memset(storage, 0, sizeof(struct sockaddr_storage)); - if (get_sockaddr(host, port, storage, 1) == -1) { + if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) { FATAL("failed to resolve the provided hostname"); } listen_ctx.remote_addr[i] = (struct sockaddr *)storage; diff --git a/src/server.c b/src/server.c index c5702c47..18dd4cce 100644 --- a/src/server.c +++ b/src/server.c @@ -183,7 +183,7 @@ stat_update_cb(EV_P_ ev_timer *watcher, int revents) } else { struct sockaddr_storage storage; memset(&storage, 0, sizeof(struct sockaddr_storage)); - if (get_sockaddr(ip_addr.host, ip_addr.port, &storage, 0) == -1) { + if (get_sockaddr(ip_addr.host, ip_addr.port, &storage, 0, ipv6first) == -1) { ERROR("failed to parse the manager addr"); return; } @@ -302,16 +302,16 @@ get_peer_name(int fd) return peer_name; } - #ifdef __linux__ static void set_linger(int fd) { struct linger so_linger; - so_linger.l_onoff = 1; + so_linger.l_onoff = 1; so_linger.l_linger = 0; setsockopt(fd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger); } + #endif static void @@ -708,7 +708,8 @@ server_recv_cb(EV_P_ ev_io *w, int revents) ss_free(server->header_buf); server->stage = 2; } else { - if (ret == -1) server->stage = -1; + if (ret == -1) + server->stage = -1; server->buf->len = 0; server->buf->idx = 0; return; diff --git a/src/tls.c b/src/tls.c index 5c584b25..5c422160 100644 --- a/src/tls.c +++ b/src/tls.c @@ -121,7 +121,7 @@ parse_tls_header(const char *data, size_t data_len, char **hostname) if (tls_version_major < 3) { if (verbose) LOGI("Received SSL %d.%d handshake which can not support SNI.", - tls_version_major, tls_version_minor); + tls_version_major, tls_version_minor); return -2; } @@ -251,7 +251,7 @@ parse_server_name_extension(const char *data, size_t data_len, default: if (verbose) LOGI("Unknown server name extension name type: %d", - data[pos]); + data[pos]); } pos += 3 + len; } diff --git a/src/tunnel.c b/src/tunnel.c index 1a7c52cb..4ddfe0b6 100644 --- a/src/tunnel.c +++ b/src/tunnel.c @@ -93,8 +93,9 @@ char *prefix; int verbose = 0; int keep_resolving = 1; -static int mode = TCP_ONLY; -static int auth = 0; +static int ipv6first = 0; +static int mode = TCP_ONLY; +static int auth = 0; #ifdef HAVE_SETRLIMIT static int nofile = 0; #endif @@ -750,10 +751,10 @@ main(int argc, char **argv) USE_TTY(); #ifdef ANDROID - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:n:P:huUvVA", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:n:P:huUvVA6", long_options, &option_index)) != -1) { #else - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:n:huUvA", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:n:huUvA6", long_options, &option_index)) != -1) { #endif switch (c) { @@ -829,6 +830,9 @@ main(int argc, char **argv) case 'A': auth = 1; break; + case '6': + ipv6first = 1; + break; #ifdef ANDROID case 'V': vpn = 1; @@ -939,6 +943,10 @@ main(int argc, char **argv) daemonize(pid_path); } + if (ipv6first) { + LOGI("resolving hostname to IPv6 address first"); + } + if (auth) { LOGI("onetime authentication enabled"); } @@ -975,7 +983,7 @@ main(int argc, char **argv) remote_addr[i].port; struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage)); memset(storage, 0, sizeof(struct sockaddr_storage)); - if (get_sockaddr(host, port, storage, 1) == -1) { + if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) { FATAL("failed to resolve the provided hostname"); } listen_ctx.remote_addr[i] = (struct sockaddr *)storage;