diff --git a/src/acl.c b/src/acl.c index bfaec27b..4ef5d788 100644 --- a/src/acl.c +++ b/src/acl.c @@ -3,6 +3,36 @@ static struct ip_set set; +static void parse_addr_cidr(const char *str, char **host, int *cidr) +{ + int ret = -1, n = 0; + char *pch; + pch = strchr(str, '/'); + while (pch != NULL) + { + n++; + ret = pch - str; + pch = strchr(pch + 1, '/'); + } + if (n > 1) + { + if (strcmp(str+ret, "]") != 0) + { + ret = -1; + } + } + if (ret == -1) + { + *host = strdup(str); + *cidr = -1; + } + else + { + *host = ss_strndup(str, ret); + *cidr = atoi(strdup(str + ret + 1)); + } +} + int init_acl(const char *path) { ipset_init_library(); @@ -16,13 +46,18 @@ int init_acl(const char *path) { if (fgets(line, 256, f)) { - char host[256]; + char *host = NULL; int cidr; - sscanf(line, "%s/%d", host, &cidr); + parse_addr_cidr(line, &host, &cidr); struct cork_ipv4 addr; int err = cork_ipv4_init(&addr, host); if (err) continue; - ipset_ipv4_add_network(&set, &addr, cidr); + if (cidr >= 0) + ipset_ipv4_add_network(&set, &addr, cidr); + else + ipset_ipv4_add(&set, &addr); + + if (host != NULL) free(host); } } @@ -36,7 +71,7 @@ void free_acl(void) ipset_done(&set); } -int is_bypass(const char* host) +int acl_is_bypass(const char* host) { struct cork_ipv4 addr; int err = cork_ipv4_init(&addr, host); diff --git a/src/acl.h b/src/acl.h index 4c570c42..2acb6678 100644 --- a/src/acl.h +++ b/src/acl.h @@ -3,6 +3,6 @@ int init_acl(const char *path); void free_acl(void); -int is_bypass(const char* host); +int acl_is_bypass(const char* host); #endif // _ACL_H diff --git a/src/local.c b/src/local.c index ab822b9e..f550315b 100644 --- a/src/local.c +++ b/src/local.c @@ -404,29 +404,30 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) LOGD("connect to %s:%s", host, port); } - if (remote == NULL) + if (acl_is_bypass(host)) { - if (is_bypass(host)) - { - remote = connect_to_remote(server->listener, host, port); - remote->direct = 1; - } - else - { - remote = connect_to_remote(server->listener, NULL, NULL); - } - - if (remote == NULL) + remote = connect_to_remote(server->listener, host, port); + remote->direct = 1; + if (verbose) { - LOGE("invalid password or cipher"); - close_and_free_remote(EV_A_ remote); - close_and_free_server(EV_A_ server); - return; + LOGD("bypass %s:%s", host, port); } + } + else + { + remote = connect_to_remote(server->listener, NULL, NULL); + } - server->remote = remote; - remote->server = server; + if (remote == NULL) + { + LOGE("invalid password or cipher"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; } + + server->remote = remote; + remote->server = server; } // Fake reply @@ -929,8 +930,9 @@ int main (int argc, char **argv) int option_index = 0; static struct option long_options[] = { - {"fast-open", no_argument, 0, 0 }, - {0, 0, 0, 0 } + {"fast-open", no_argument, 0, 0 }, + {"acl", required_argument, 0, 0 }, + {0, 0, 0, 0 } }; opterr = 0; @@ -950,6 +952,11 @@ int main (int argc, char **argv) LOGE("tcp fast open is not supported by this environment"); #endif } + else if (option_index == 1) + { + acl = 1; + init_acl(optarg); + } break; case 's': remote_addr[remote_num].host = optarg;