From c20de089cffc3947fd2b2c0d427ad184143571f2 Mon Sep 17 00:00:00 2001 From: PantherJohn Date: Mon, 1 Jul 2019 13:28:10 +0800 Subject: [PATCH] fixed a bug in get_sockaddr_r() --- src/acl.c | 3 +- src/common.h | 4 +- src/jconf.c | 8 ++-- src/netutils.c | 121 ++++++++++++++++++------------------------------- src/relay.c | 11 ++--- src/udprelay.c | 4 +- src/utils.c | 3 ++ 7 files changed, 64 insertions(+), 90 deletions(-) diff --git a/src/acl.c b/src/acl.c index 807c213d..215805ac 100644 --- a/src/acl.c +++ b/src/acl.c @@ -161,8 +161,9 @@ init_acl(jconf_t *conf) char *tag = NULL; while ((tag = strtok(NULL, sep))) { for (int i = 0; i < conf->remote_num; i++) { + char *tag_ = trim_whitespace(tag); char *rtag = trim_whitespace(conf->remotes[i]->tag); - if (rtag != NULL && strcmp(trim_whitespace(tag), rtag) == 0) { + if (rtag != NULL && strcmp(tag_, rtag) == 0) { remote_idxs = ss_realloc(remote_idxs, (remote_num + 1) * sizeof(*remote_idxs)); remote_idxs[remote_num++] = i; diff --git a/src/common.h b/src/common.h index 04e1debb..ad8bd664 100644 --- a/src/common.h +++ b/src/common.h @@ -93,8 +93,8 @@ typedef struct listen_ctx { ev_timer stat_watcher; #endif struct cork_dllist_item entries; -#endif struct ev_loop *loop; +#endif struct sockaddr_storage *addr; } listen_ctx_t; @@ -103,7 +103,7 @@ int protect_socket(int fd); int send_traffic_stat(uint64_t tx, uint64_t rx); #endif -void init_udprelay(listen_ctx_t *listener); +void init_udprelay(EV_P_ listen_ctx_t *listener); void free_udprelay(struct ev_loop *loop); #endif // _COMMON_H diff --git a/src/jconf.c b/src/jconf.c index 80e49f38..2b6caa68 100644 --- a/src/jconf.c +++ b/src/jconf.c @@ -467,7 +467,7 @@ parse_argopts(jconf_t *conf, int argc, char **argv) { GETOPT_VAL_PASSWORD, jconf_type_string, required_argument, &conf->password }, { GETOPT_VAL_HELP, jconf_type_help, no_argument, NULL }, - { '?', jconf_type_unknown, no_argument, NULL }, + { '?', jconf_type_unknown, -1, NULL }, { 0, 0, no_argument, NULL } }; @@ -484,10 +484,11 @@ parse_argopts(jconf_t *conf, int argc, char **argv) opterr = 0; - int c; + int c, curind; int conf_parsed = 0; again: + curind = optind; while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { @@ -548,7 +549,8 @@ again: default: case jconf_type_unknown: { // The option character is not recognized. - LOGE("Unrecognized option: %s", optarg); + LOGE("Unrecognized option: %s", + optopt ? (char []) { optopt } : argv[curind]); opterr = 1; } break; } diff --git a/src/netutils.c b/src/netutils.c index 31c73575..f7fe8961 100644 --- a/src/netutils.c +++ b/src/netutils.c @@ -376,94 +376,63 @@ get_sockaddr_r(const char *node, { if (storage == NULL) return -1; - struct cork_ip ip; - uint16_t _port = elvis(port, service ? htons(atoi(service)) : 0); - if (cork_ip_init(&ip, node) != -1) { - switch (ip.version) { - case 4: { - struct sockaddr_in *addr - = (struct sockaddr_in *)storage; - addr->sin_family = AF_INET; - memcpy(&addr->sin_addr, &ip.ip.v4, sizeof(ip.ip.v4)); - addr->sin_port = _port; - } break; - case 6: { - struct sockaddr_in6 *addr - = (struct sockaddr_in6 *)storage; - addr->sin6_family = AF_INET; - memcpy(&addr->sin6_addr, &ip.ip.v6, sizeof(ip.ip.v6)); - addr->sin6_port = _port; - } break; - default: - return -1; - } - return 0; - } else if (resolv) { + #ifdef __ANDROID__ - extern int vpn; - assert(!vpn); // DNS packet protection isn't supported yet + extern int vpn; + assert(!vpn); // DNS packet protection isn't supported yet #endif - struct addrinfo hints = { - .ai_family = AF_UNSPEC, /* Return IPv4 and IPv6 choices */ - .ai_flags = AI_PASSIVE | AI_ADDRCONFIG /* For wildcard IP address */ - }; - struct addrinfo *result, *rp; + struct addrinfo hints = { + .ai_family = AF_UNSPEC, /* Return IPv4 and IPv6 choices */ + .ai_flags = AI_PASSIVE | AI_ADDRCONFIG /* For wildcard IP address */ + }; - int err = getaddrinfo(node, service, &hints, &result); + if (!resolv) + hints.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV; - if (err != 0) { - LOGE("getaddrinfo: %s", gai_strerror(err)); - return -1; - } + struct addrinfo *result, *rp; + + int err = getaddrinfo(node, service, &hints, &result); + + if (err != 0) { + LOGE("getaddrinfo: %s", gai_strerror(err)); + return -1; + } - int prefer_af = ipv6first ? AF_INET6 : AF_INET; + int prefer_af = ipv6first ? AF_INET6 : AF_INET; again: - for (rp = result; rp != NULL; rp = rp->ai_next) { - if (prefer_af ? rp->ai_family == prefer_af : true) { - storage->ss_family = rp->ai_family; - switch (rp->ai_family) { - case AF_INET: { - struct sockaddr_in *dst = (struct sockaddr_in *)storage; - struct sockaddr_in *src = (struct sockaddr_in *)rp->ai_addr; - dst->sin_addr = src->sin_addr; - dst->sin_port = elvis(src->sin_port, _port); - } break; - case AF_INET6: { - struct sockaddr_in6 *dst = (struct sockaddr_in6 *)storage; - struct sockaddr_in6 *src = (struct sockaddr_in6 *)rp->ai_addr; - dst->sin6_addr = src->sin6_addr; - dst->sin6_port = elvis(src->sin6_port, _port); - } break; - } - break; + for (rp = result; rp != NULL; rp = rp->ai_next) { + if (prefer_af ? rp->ai_family == prefer_af : true) { + storage->ss_family = rp->ai_family; + switch (rp->ai_family) { + case AF_INET: { + struct sockaddr_in *dst = (struct sockaddr_in *)storage; + struct sockaddr_in *src = (struct sockaddr_in *)rp->ai_addr; + dst->sin_addr = src->sin_addr; + dst->sin_port = elvis(src->sin_port, port); + } break; + case AF_INET6: { + struct sockaddr_in6 *dst = (struct sockaddr_in6 *)storage; + struct sockaddr_in6 *src = (struct sockaddr_in6 *)rp->ai_addr; + dst->sin6_addr = src->sin6_addr; + dst->sin6_port = elvis(src->sin6_port, port); + } break; } + break; } + } - if (prefer_af && rp == NULL) { - prefer_af = 0; - goto again; - } - - if (rp == NULL) { - LOGE("failed to resolve remote addr"); - return -1; - } + if (prefer_af && rp == NULL) { + prefer_af = 0; + goto again; + } - freeaddrinfo(result); - return 0; - } else { - switch (storage->ss_family) { - default: - case AF_INET: - ((struct sockaddr_in *)storage)->sin_port = _port; - break; - case AF_INET6: - ((struct sockaddr_in6 *)storage)->sin6_port = _port; - break; - } + if (rp == NULL) { + LOGE("failed to resolve remote addr"); + return -1; } - return -1; + freeaddrinfo(result); + return 0; } int diff --git a/src/relay.c b/src/relay.c index 0897aa4d..de22ed6f 100644 --- a/src/relay.c +++ b/src/relay.c @@ -748,7 +748,6 @@ start_relay(jconf_t *conf, .remote_num = conf->remote_num, .remotes = ss_calloc(conf->remote_num, sizeof(remote_cnf_t *)), .timeout = atoi(conf->timeout), - .loop = loop }; #ifdef MODULE_TUNNEL @@ -883,7 +882,7 @@ start_relay(jconf_t *conf, if (conf->fast_open) set_fastopen_passive(socket); ev_io_init(&listen_ctx_current.io, accept_cb, listen_ctx_current.fd, EV_READ); - ev_io_start(EV_A_ &listen_ctx_current.io); + ev_io_start(EV_A_ & listen_ctx_current.io); } } @@ -892,7 +891,7 @@ start_relay(jconf_t *conf, listen_ctx_t listen_ctx_dgram = listen_ctx_current; int socket_u = bind_and_listen(storage, IPPROTO_UDP, &listen_ctx_dgram); if ((listen_ctx_dgram.fd = socket_u) != -1) { - init_udprelay(&listen_ctx_dgram); + init_udprelay(EV_A_ & listen_ctx_dgram); } } @@ -913,7 +912,7 @@ start_relay(jconf_t *conf, } while (*(dscp++) != NULL); #elif MODULE_REMOTE - resolv_init(loop, conf->nameserver, conf->ipv6_first); + resolv_init(EV_A_ conf->nameserver, conf->ipv6_first); if (conf->nameserver != NULL) LOGI("using nameserver: %s", conf->nameserver); port_service_init(); @@ -1023,7 +1022,7 @@ start_relay(jconf_t *conf, if (conf->fast_open) set_fastopen_passive(socket); ev_io_init(&listen_ctx.io, accept_cb, listen_ctx.fd, EV_READ); - ev_io_start(loop, &listen_ctx.io); + ev_io_start(EV_A_ & listen_ctx.io); cork_dllist_add(&listeners, &listen_ctx.entries); } } @@ -1033,7 +1032,7 @@ start_relay(jconf_t *conf, listen_ctx_t listen_ctx_dgram = listen_ctx; int socket_u = bind_and_listen(storage, IPPROTO_UDP, &listen_ctx_dgram); if ((listen_ctx_dgram.fd = socket_u) != -1) { - init_udprelay(&listen_ctx_dgram); + init_udprelay(EV_A_ & listen_ctx_dgram); } } diff --git a/src/udprelay.c b/src/udprelay.c index 32fcfbf1..bef2adbc 100644 --- a/src/udprelay.c +++ b/src/udprelay.c @@ -764,7 +764,7 @@ CLEAN_UP: } void -init_udprelay(listen_ctx_t *listener) +init_udprelay(EV_P_ listen_ctx_t *listener) { if (listener->mtu > 0) { packet_size = listener->mtu - DGRAM_PKT_HDR_SIZE; @@ -772,7 +772,7 @@ init_udprelay(listen_ctx_t *listener) } server_t *server = new_server(listener->fd, listener); - ev_io_start(listener->loop, &server->io); + ev_io_start(EV_A_ & server->io); } void diff --git a/src/utils.c b/src/utils.c index 178cb2e7..a6b836ab 100644 --- a/src/utils.c +++ b/src/utils.c @@ -270,6 +270,9 @@ ss_is_ipv6addr(const char *addr) char * trim_whitespace(char *str) { + if (str == NULL) + return str; + char *end; // Trim leading space