diff options
author | Martin Willi <martin@revosec.ch> | 2013-07-01 14:47:11 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2013-07-18 16:00:29 +0200 |
commit | e11c02c8f1591fef64200137c24598fba9d488a9 (patch) | |
tree | 37888a2245fa4446222bf1862956dcbb2f72bab2 /src/libcharon/plugins/whitelist/whitelist_control.c | |
parent | 091d0afa2163a6aba79bf4802330f0099e857e38 (diff) | |
download | strongswan-e11c02c8f1591fef64200137c24598fba9d488a9.tar.bz2 strongswan-e11c02c8f1591fef64200137c24598fba9d488a9.tar.xz |
whitelist: use a stream service to accept client connections
Use SOCK_STREAM, as we don't have SOCK_SEQPACKET on TCP. To have network
transparency, the message now uses network byte order.
Diffstat (limited to 'src/libcharon/plugins/whitelist/whitelist_control.c')
-rw-r--r-- | src/libcharon/plugins/whitelist/whitelist_control.c | 132 |
1 files changed, 27 insertions, 105 deletions
diff --git a/src/libcharon/plugins/whitelist/whitelist_control.c b/src/libcharon/plugins/whitelist/whitelist_control.c index b90b62ac1..c3f7ac40e 100644 --- a/src/libcharon/plugins/whitelist/whitelist_control.c +++ b/src/libcharon/plugins/whitelist/whitelist_control.c @@ -23,8 +23,6 @@ #include <errno.h> #include <daemon.h> -#include <threading/thread.h> -#include <processing/jobs/callback_job.h> #include "whitelist_msg.h" @@ -46,65 +44,28 @@ struct private_whitelist_control_t { whitelist_listener_t *listener; /** - * Whitelist unix socket file descriptor + * Whitelist stream service */ - int socket; + stream_service_t *service; }; /** - * Open whitelist unix socket + * Dispatch a received message */ -static bool open_socket(private_whitelist_control_t *this) +static bool on_accept(private_whitelist_control_t *this, stream_t *stream) { - struct sockaddr_un addr; - mode_t old; - - addr.sun_family = AF_UNIX; - strcpy(addr.sun_path, WHITELIST_SOCKET); + identification_t *id, *current; + enumerator_t *enumerator; + whitelist_msg_t msg; - this->socket = socket(AF_UNIX, SOCK_SEQPACKET, 0); - if (this->socket == -1) + if (!stream->read_all(stream, &msg, sizeof(msg))) { - DBG1(DBG_CFG, "creating whitelist socket failed"); return FALSE; } - unlink(addr.sun_path); - old = umask(~(S_IRWXU | S_IRWXG)); - if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) < 0) - { - DBG1(DBG_CFG, "binding whitelist socket failed: %s", strerror(errno)); - close(this->socket); - return FALSE; - } - umask(old); - if (chown(addr.sun_path, lib->caps->get_uid(lib->caps), - lib->caps->get_gid(lib->caps)) != 0) - { - DBG1(DBG_CFG, "changing whitelist socket permissions failed: %s", - strerror(errno)); - } - if (listen(this->socket, 10) < 0) - { - DBG1(DBG_CFG, "listening on whitelist socket failed: %s", strerror(errno)); - close(this->socket); - unlink(addr.sun_path); - return FALSE; - } - return TRUE; -} -/** - * Dispatch a received message - */ -static void dispatch(private_whitelist_control_t *this, - int fd, whitelist_msg_t *msg) -{ - identification_t *id, *current; - enumerator_t *enumerator; - - msg->id[sizeof(msg->id)-1] = 0; - id = identification_create_from_string(msg->id); - switch (msg->type) + msg.id[sizeof(msg.id) - 1] = 0; + id = identification_create_from_string(msg.id); + switch (ntohl(msg.type)) { case WHITELIST_ADD: this->listener->add(this->listener, id); @@ -118,8 +79,8 @@ static void dispatch(private_whitelist_control_t *this, { if (current->matches(current, id)) { - snprintf(msg->id, sizeof(msg->id), "%Y", current); - if (send(fd, msg, sizeof(*msg), 0) != sizeof(*msg)) + snprintf(msg.id, sizeof(msg.id), "%Y", current); + if (!stream->write_all(stream, &msg, sizeof(msg))) { DBG1(DBG_CFG, "listing whitelist failed"); break; @@ -127,9 +88,9 @@ static void dispatch(private_whitelist_control_t *this, } } enumerator->destroy(enumerator); - msg->type = WHITELIST_END; - memset(msg->id, 0, sizeof(msg->id)); - send(fd, msg, sizeof(*msg), 0); + msg.type = htonl(WHITELIST_END); + memset(msg.id, 0, sizeof(msg.id)); + stream->write_all(stream, &msg, sizeof(msg)); break; case WHITELIST_FLUSH: this->listener->flush(this->listener, id); @@ -145,58 +106,14 @@ static void dispatch(private_whitelist_control_t *this, break; } id->destroy(id); -} - -/** - * Accept whitelist control connections, dispatch - */ -static job_requeue_t receive(private_whitelist_control_t *this) -{ - struct sockaddr_un addr; - int fd, len = sizeof(addr); - whitelist_msg_t msg; - bool oldstate; - - oldstate = thread_cancelability(TRUE); - fd = accept(this->socket, (struct sockaddr*)&addr, &len); - thread_cancelability(oldstate); - - if (fd != -1) - { - while (TRUE) - { - oldstate = thread_cancelability(TRUE); - len = recv(fd, &msg, sizeof(msg), 0); - thread_cancelability(oldstate); - if (len == sizeof(msg)) - { - dispatch(this, fd, &msg); - } - else - { - if (len != 0) - { - DBG1(DBG_CFG, "receiving whitelist msg failed: %s", - strerror(errno)); - } - break; - } - } - close(fd); - } - else - { - DBG1(DBG_CFG, "accepting whitelist connection failed: %s", - strerror(errno)); - } - return JOB_REQUEUE_FAIR; + return FALSE; } METHOD(whitelist_control_t, destroy, void, private_whitelist_control_t *this) { - close(this->socket); + this->service->destroy(this->service); free(this); } @@ -206,6 +123,7 @@ METHOD(whitelist_control_t, destroy, void, whitelist_control_t *whitelist_control_create(whitelist_listener_t *listener) { private_whitelist_control_t *this; + char *uri; INIT(this, .public = { @@ -214,15 +132,19 @@ whitelist_control_t *whitelist_control_create(whitelist_listener_t *listener) .listener = listener, ); - if (!open_socket(this)) + uri = lib->settings->get_str(lib->settings, + "%s.plugins.whitelist.socket", "unix://" WHITELIST_SOCKET, + charon->name); + this->service = lib->streams->create_service(lib->streams, uri, 10); + if (!this->service) { + DBG1(DBG_CFG, "creating whitelist socket failed"); free(this); return NULL; } - lib->processor->queue_job(lib->processor, - (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive, this, - NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); + this->service->on_accept(this->service, (stream_service_cb_t)on_accept, + this, JOB_PRIO_CRITICAL, 0); return &this->public; } |