aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/plugins/whitelist/whitelist_control.c
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-07-01 14:47:11 +0200
committerMartin Willi <martin@revosec.ch>2013-07-18 16:00:29 +0200
commite11c02c8f1591fef64200137c24598fba9d488a9 (patch)
tree37888a2245fa4446222bf1862956dcbb2f72bab2 /src/libcharon/plugins/whitelist/whitelist_control.c
parent091d0afa2163a6aba79bf4802330f0099e857e38 (diff)
downloadstrongswan-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.c132
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;
}