Browse Source

fixed a bug in get_sockaddr_r()

pull/2430/head
PantherJohn 6 years ago
parent
commit
c20de089cf
7 changed files with 64 additions and 90 deletions
  1. 3
      src/acl.c
  2. 4
      src/common.h
  3. 8
      src/jconf.c
  4. 121
      src/netutils.c
  5. 11
      src/relay.c
  6. 4
      src/udprelay.c
  7. 3
      src/utils.c

3
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;

4
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

8
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;
}

121
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

11
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);
}
}

4
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

3
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

Loading…
Cancel
Save