main: allow multiple clients in control channel (occtl)

This commit is contained in:
Nikos Mavrogiannopoulos
2015-11-13 14:04:32 +01:00
committed by Nikos Mavrogiannopoulos
parent 0e604b8a9f
commit 12bc8955bd
7 changed files with 69 additions and 43 deletions

View File

@@ -28,12 +28,14 @@
#include <sys/un.h> #include <sys/un.h>
#include <main.h> #include <main.h>
#include <vpn.h> #include <vpn.h>
#include <cloexec.h>
#include <ip-lease.h> #include <ip-lease.h>
#include <errno.h> #include <errno.h>
#include <system.h> #include <system.h>
#include <main-ctl.h> #include <main-ctl.h>
#include <main-ban.h> #include <main-ban.h>
#include <ccan/container_of/container_of.h>
#include <ctl.pb-c.h> #include <ctl.pb-c.h>
#include <str.h> #include <str.h>
@@ -691,43 +693,28 @@ static void method_disconnect_user_id(method_ctx *ctx, int cfd,
return; return;
} }
static void ctl_handle_commands(main_server_st * s) struct ctl_watcher_st {
int fd;
struct ev_io ctl_cmd_io;
};
static void ctl_cmd_wacher_cb(EV_P_ ev_io *w, int revents)
{ {
int cfd = -1, e, ret; main_server_st *s = ev_userdata(loop);
unsigned i; int ret, e;
struct sockaddr_un sa;
socklen_t sa_len;
uint16_t length; uint16_t length;
uint8_t buffer[256]; uint8_t buffer[256];
unsigned buffer_size; unsigned buffer_size;
method_ctx ctx; method_ctx ctx;
void *pool = talloc_new(s); struct ctl_watcher_st *wst = container_of(w, struct ctl_watcher_st, ctl_cmd_io);
unsigned i;
if (pool == NULL) {
mslog(s, NULL, LOG_ERR, "memory allocation error");
return;
}
ctx.s = s; ctx.s = s;
ctx.pool = pool; ctx.pool = wst;
sa_len = sizeof(sa);
cfd = accept(s->ctl_fd, (struct sockaddr *)&sa, &sa_len);
if (cfd == -1) {
e = errno;
mslog(s, NULL, LOG_ERR,
"error accepting control connection: %s", strerror(e));
goto cleanup;
}
ret = check_upeer_id("ctl", s->perm_config->debug, cfd, 0, 0, NULL, NULL);
if (ret < 0) {
mslog(s, NULL, LOG_ERR, "ctl: unauthorized connection");
goto cleanup;
}
/* read request */ /* read request */
ret = recv(cfd, buffer, sizeof(buffer), 0); ret = recv(wst->fd, buffer, sizeof(buffer), 0);
if (ret < 3) { if (ret < 3) {
if (ret == -1) { if (ret == -1) {
e = errno; e = errno;
@@ -737,7 +724,7 @@ static void ctl_handle_commands(main_server_st * s)
mslog(s, NULL, LOG_ERR, "received ctl data: %d bytes", mslog(s, NULL, LOG_ERR, "received ctl data: %d bytes",
ret); ret);
} }
goto cleanup; goto fail;
} }
memcpy(&length, &buffer[1], 2); memcpy(&length, &buffer[1], 2);
buffer_size = ret - 3; buffer_size = ret - 3;
@@ -746,7 +733,7 @@ static void ctl_handle_commands(main_server_st * s)
mslog(s, NULL, LOG_ERR, mslog(s, NULL, LOG_ERR,
"received data length doesn't match received data (%d/%d)", "received data length doesn't match received data (%d/%d)",
buffer_size, (int)length); buffer_size, (int)length);
goto cleanup; goto fail;
} }
for (i = 0;; i++) { for (i = 0;; i++) {
@@ -756,12 +743,54 @@ static void ctl_handle_commands(main_server_st * s)
(unsigned)buffer[0]); (unsigned)buffer[0]);
break; break;
} else if (methods[i].cmd == buffer[0]) { } else if (methods[i].cmd == buffer[0]) {
methods[i].func(&ctx, cfd, buffer + 3, buffer_size); methods[i].func(&ctx, wst->fd, buffer + 3, buffer_size);
break; break;
} }
} }
cleanup:
talloc_free(pool); return;
fail:
close(wst->fd);
ev_io_stop(EV_A_ w);
talloc_free(wst);
return;
}
static void ctl_handle_commands(main_server_st * s)
{
int cfd = -1, e, ret;
struct sockaddr_un sa;
socklen_t sa_len;
struct ctl_watcher_st *wst;
sa_len = sizeof(sa);
cfd = accept(s->ctl_fd, (struct sockaddr *)&sa, &sa_len);
if (cfd == -1) {
e = errno;
mslog(s, NULL, LOG_ERR,
"error accepting control connection: %s", strerror(e));
goto fail;
}
ret = check_upeer_id("ctl", s->perm_config->debug, cfd, 0, 0, NULL, NULL);
if (ret < 0) {
mslog(s, NULL, LOG_ERR, "ctl: unauthorized connection");
goto fail;
}
set_cloexec_flag(cfd, 1);
wst = talloc(s, struct ctl_watcher_st);
if (wst == NULL)
goto fail;
wst->fd = cfd;
ev_io_init(&wst->ctl_cmd_io, ctl_cmd_wacher_cb, wst->fd, EV_READ);
ev_io_start(loop, &wst->ctl_cmd_io);
return;
fail:
if (cfd != -1) if (cfd != -1)
close(cfd); close(cfd);
} }

View File

@@ -310,7 +310,7 @@ static int handle_cookie_auth_res(main_server_st *s, struct proc_st *proc,
return ret; return ret;
} }
int handle_commands(main_server_st * s, struct proc_st *proc) int handle_worker_commands(main_server_st * s, struct proc_st *proc)
{ {
struct iovec iov[3]; struct iovec iov[3];
uint8_t cmd; uint8_t cmd;

View File

@@ -902,7 +902,7 @@ static void cmd_watcher_cb (EV_P_ ev_io *w, int revents)
int ret; int ret;
/* Check for any pending commands */ /* Check for any pending commands */
ret = handle_commands(s, ctmp); ret = handle_worker_commands(s, ctmp);
if (ret < 0) { if (ret < 0) {
remove_proc(s, ctmp, (ret!=ERR_WORKER_TERMINATED)?RPROC_KILL:0); remove_proc(s, ctmp, (ret!=ERR_WORKER_TERMINATED)?RPROC_KILL:0);
} }

View File

@@ -223,11 +223,8 @@ typedef struct main_server_st {
/* This one is on worker pool */ /* This one is on worker pool */
struct worker_st *ws; struct worker_st *ws;
#ifdef HAVE_DBUS
void * ctl_ctx;
#else
int ctl_fd; int ctl_fd;
#endif
int sec_mod_fd; /* messages are sent and received async */ int sec_mod_fd; /* messages are sent and received async */
int sec_mod_fd_sync; /* messages are send in a sync order (ping-pong). Only main sends. */ int sec_mod_fd_sync; /* messages are send in a sync order (ping-pong). Only main sends. */
void *main_pool; /* talloc main pool */ void *main_pool; /* talloc main pool */
@@ -235,7 +232,7 @@ typedef struct main_server_st {
void clear_lists(main_server_st *s); void clear_lists(main_server_st *s);
int handle_commands(main_server_st *s, struct proc_st* cur); int handle_worker_commands(main_server_st *s, struct proc_st* cur);
int handle_sec_mod_commands(main_server_st *s); int handle_sec_mod_commands(main_server_st *s);
int user_connected(main_server_st *s, struct proc_st* cur); int user_connected(main_server_st *s, struct proc_st* cur);

View File

@@ -49,7 +49,7 @@
#endif #endif
int handle_worker_commands(struct worker_st *ws) int handle_commands_from_main(struct worker_st *ws)
{ {
struct iovec iov[3]; struct iovec iov[3];
uint8_t cmd; uint8_t cmd;

View File

@@ -1974,7 +1974,7 @@ static int connect_handler(worker_st * ws)
/* read commands from command fd */ /* read commands from command fd */
if (FD_ISSET(ws->cmd_fd, &rfds)) { if (FD_ISSET(ws->cmd_fd, &rfds)) {
ret = handle_worker_commands(ws); ret = handle_commands_from_main(ws);
if (ret == ERR_NO_CMD_FD) { if (ret == ERR_NO_CMD_FD) {
terminate_reason = REASON_ERROR; terminate_reason = REASON_ERROR;
goto terminate; goto terminate;

View File

@@ -328,7 +328,7 @@ int complete_vpn_info(worker_st * ws,
struct vpn_st* vinfo); struct vpn_st* vinfo);
int send_tun_mtu(worker_st *ws, unsigned int mtu); int send_tun_mtu(worker_st *ws, unsigned int mtu);
int handle_worker_commands(struct worker_st *ws); int handle_commands_from_main(struct worker_st *ws);
int disable_system_calls(struct worker_st *ws); int disable_system_calls(struct worker_st *ws);
void ocsigaltstack(struct worker_st *ws); void ocsigaltstack(struct worker_st *ws);