add ip addr support

This commit is contained in:
Max Lv
2015-08-12 12:27:59 +08:00
parent 7f9e158f85
commit 4c508e1ed4
4 changed files with 225 additions and 55 deletions
+121 -24
View File
@@ -47,6 +47,7 @@
#include <pthread.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <pwd.h>
#endif
#include <libcork/core.h>
@@ -71,6 +72,7 @@
int verbose = 0;
char *executable = "ss-server";
char working_dir[128];
static struct cork_hash_table *server_table;
@@ -91,9 +93,9 @@ static char *construct_command_line(struct manager_ctx *manager, struct server *
memset(cmd, 0, BUF_SIZE);
snprintf(cmd, BUF_SIZE,
"%s -p %s -m %s -k %s --manager-address %s -f %s_%s.pid", executable,
"%s -p %s -m %s -k %s --manager-address %s -f %s/.shadowsocks_%s.pid", executable,
server->port, manager->method, server->password, manager->manager_address,
manager->manager_address, server->port);
working_dir, server->port);
if (manager->acl != NULL) {
int len = strlen(cmd);
snprintf(cmd + len, BUF_SIZE - len, " --acl %s", manager->acl);
@@ -261,7 +263,7 @@ static void stop_server(char *prefix, char *port)
{
char path[128];
int pid;
snprintf(path, 128, "%s_%s.pid", prefix, port);
snprintf(path, 128, "%s/.shadowsocks_%s.pid", prefix, port);
FILE *f = fopen(path, "r");
if (f == NULL) {
if (verbose) {
@@ -334,7 +336,7 @@ static void manager_recv_cb(EV_P_ ev_io *w, int revents)
goto ERROR_MSG;
}
remove_server(manager->manager_address, server->port);
remove_server(working_dir, server->port);
add_server(manager, server);
char msg[3] = "ok";
@@ -353,7 +355,7 @@ static void manager_recv_cb(EV_P_ ev_io *w, int revents)
goto ERROR_MSG;
}
remove_server(manager->manager_address, server->port);
remove_server(working_dir, server->port);
free(server);
char msg[3] = "ok";
@@ -432,6 +434,84 @@ static void signal_cb(EV_P_ ev_signal *w, int revents)
}
}
int create_server_socket(const char *host, const char *port)
{
struct addrinfo hints;
struct addrinfo *result, *rp, *ipv4v6bindall;
int s, server_sock;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
hints.ai_socktype = SOCK_DGRAM; /* We want a UDP socket */
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */
hints.ai_protocol = IPPROTO_UDP;
s = getaddrinfo(host, port, &hints, &result);
if (s != 0) {
LOGE("getaddrinfo: %s", gai_strerror(s));
return -1;
}
rp = result;
/*
On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with
AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to
return a list of addresses to listen on, but it is impossible to listen on
0.0.0.0 and :: at the same time, if :: implies dualstack mode.
*/
if (!host) {
ipv4v6bindall = result;
/* Loop over all address infos found until a IPV6 address is found. */
while (ipv4v6bindall) {
if (ipv4v6bindall->ai_family == AF_INET6) {
rp = ipv4v6bindall; /* Take first IPV6 address available */
break;
}
ipv4v6bindall = ipv4v6bindall->ai_next; /* Get next address info, if any */
}
}
for (/*rp = result*/; rp != NULL; rp = rp->ai_next) {
server_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (server_sock == -1) {
continue;
}
if (rp->ai_family == AF_INET6) {
int ipv6only = host ? 1 : 0;
setsockopt(server_sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only));
}
int opt = 1;
setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
set_nosigpipe(server_sock);
#endif
s = bind(server_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0) {
/* We managed to bind successfully! */
break;
} else {
ERROR("bind");
}
close(server_sock);
}
if (rp == NULL) {
LOGE("cannot bind");
return -1;
}
freeaddrinfo(result);
return server_sock;
}
int main(int argc, char **argv)
{
@@ -634,6 +714,16 @@ int main(int argc, char **argv)
run_as(user);
}
struct passwd *pw = getpwuid(getuid());
const char *homedir = pw->pw_dir;
snprintf(working_dir, 128, "%s/.shadowsocks", homedir);
int err = mkdir(working_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (err != 0 && errno != EEXIST) {
ERROR("mkdir");
FATAL("unable to create working directory");
}
server_table = cork_string_hash_table_new(MAX_PORT_NUM, 0);
if (conf != NULL) {
@@ -645,30 +735,37 @@ int main(int argc, char **argv)
}
}
struct sockaddr_un svaddr;
int sfd;
ss_addr_t ip_addr = { .host = NULL, .port = NULL };
parse_addr(manager_address, &ip_addr);
sfd = socket(AF_UNIX, SOCK_DGRAM, 0); /* Create server socket */
if (sfd == -1) {
FATAL("socket");
}
if (ip_addr.host == NULL || ip_addr.port == NULL) {
struct sockaddr_un svaddr;
sfd = socket(AF_UNIX, SOCK_DGRAM, 0); /* Create server socket */
if (sfd == -1) {
FATAL("socket");
}
setnonblocking(sfd);
setnonblocking(sfd);
/* Construct well-known address and bind server socket to it */
if (remove(manager_address) == -1 && errno != ENOENT) {
ERROR("bind");
exit(EXIT_FAILURE);
}
if (remove(manager_address) == -1 && errno != ENOENT) {
ERROR("bind");
exit(EXIT_FAILURE);
}
memset(&svaddr, 0, sizeof(struct sockaddr_un));
svaddr.sun_family = AF_UNIX;
strncpy(svaddr.sun_path, manager_address, sizeof(svaddr.sun_path) - 1);
memset(&svaddr, 0, sizeof(struct sockaddr_un));
svaddr.sun_family = AF_UNIX;
strncpy(svaddr.sun_path, manager_address, sizeof(svaddr.sun_path) - 1);
if (bind(sfd, (struct sockaddr *) &svaddr, sizeof(struct sockaddr_un)) == -1) {
ERROR("bind");
exit(EXIT_FAILURE);
if (bind(sfd, (struct sockaddr *) &svaddr, sizeof(struct sockaddr_un)) == -1) {
ERROR("bind");
exit(EXIT_FAILURE);
}
} else {
sfd = create_server_socket(ip_addr.host, ip_addr.port);
if (sfd == -1) {
FATAL("socket");
}
}
manager.fd = sfd;
@@ -690,7 +787,7 @@ int main(int argc, char **argv)
while((entry = cork_hash_table_iterator_next(&server_iter)) != NULL) {
struct server *server = (struct server*)entry->value;
stop_server(manager_address, server->port);
stop_server(working_dir, server->port);
}
#ifdef __MINGW32__
+60 -28
View File
@@ -60,6 +60,7 @@
#define SET_INTERFACE
#endif
#include "netutils.h"
#include "utils.h"
#include "acl.h"
#include "server.h"
@@ -127,7 +128,7 @@ static struct cork_dllist connections;
static void stat_update_cb(EV_P_ ev_timer *watcher, int revents)
{
struct sockaddr_un svaddr, claddr;
int sfd;
int sfd = -1;
size_t msgLen;
char resp[BUF_SIZE];
@@ -135,38 +136,69 @@ static void stat_update_cb(EV_P_ ev_timer *watcher, int revents)
LOGI("update traffic stat: tx: %"PRIu64" rx: %"PRIu64"", tx, rx);
}
sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sfd == -1) {
ERROR("stat_socket");
return;
}
memset(&claddr, 0, sizeof(struct sockaddr_un));
claddr.sun_family = AF_UNIX;
snprintf(claddr.sun_path, sizeof(claddr.sun_path), "/tmp/shadowsocks.%s", server_port);
unlink(claddr.sun_path);
if (bind(sfd, (struct sockaddr *) &claddr, sizeof(struct sockaddr_un)) == -1) {
ERROR("stat_bind");
close(sfd);
return;
}
memset(&svaddr, 0, sizeof(struct sockaddr_un));
svaddr.sun_family = AF_UNIX;
strncpy(svaddr.sun_path, manager_address, sizeof(svaddr.sun_path) - 1);
snprintf(resp, BUF_SIZE, "stat: {\"%s\":%"PRIu64"}", server_port, tx + rx);
msgLen = strlen(resp) + 1;
if (sendto(sfd, resp, strlen(resp) + 1, 0, (struct sockaddr *) &svaddr,
sizeof(struct sockaddr_un)) != msgLen) {
ERROR("stat_sendto");
return;
ss_addr_t ip_addr = { .host = NULL, .port = NULL };
parse_addr(manager_address, &ip_addr);
if (ip_addr.host == NULL || ip_addr.port == NULL) {
sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sfd == -1) {
ERROR("stat_socket");
return;
}
memset(&claddr, 0, sizeof(struct sockaddr_un));
claddr.sun_family = AF_UNIX;
snprintf(claddr.sun_path, sizeof(claddr.sun_path), "/tmp/shadowsocks.%s", server_port);
unlink(claddr.sun_path);
if (bind(sfd, (struct sockaddr *) &claddr, sizeof(struct sockaddr_un)) == -1) {
ERROR("stat_bind");
close(sfd);
return;
}
memset(&svaddr, 0, sizeof(struct sockaddr_un));
svaddr.sun_family = AF_UNIX;
strncpy(svaddr.sun_path, manager_address, sizeof(svaddr.sun_path) - 1);
if (sendto(sfd, resp, strlen(resp) + 1, 0, (struct sockaddr *) &svaddr,
sizeof(struct sockaddr_un)) != msgLen) {
ERROR("stat_sendto");
close(sfd);
return;
}
unlink(claddr.sun_path);
} else {
struct sockaddr_storage storage;
memset(&storage, 0, sizeof(struct sockaddr_storage));
if (get_sockaddr(ip_addr.host, ip_addr.port, &storage, 0) == -1) {
ERROR("failed to parse the manager addr");
return;
}
sfd = socket(storage.ss_family, SOCK_DGRAM, 0);
if (sfd == -1) {
ERROR("stat_socket");
return;
}
size_t addr_len = get_sockaddr_len((struct sockaddr *)&storage);
if (sendto(sfd, resp, strlen(resp) + 1, 0, (struct sockaddr *)&storage,
addr_len) != msgLen) {
ERROR("stat_sendto");
close(sfd);
return;
}
}
close(sfd);
unlink(claddr.sun_path);
}
static void free_connections(struct ev_loop *loop)