stream: add support for UNIX stream services
authorMartin Willi <martin@revosec.ch>
Wed, 26 Jun 2013 15:16:33 +0000 (17:16 +0200)
committerMartin Willi <martin@revosec.ch>
Thu, 18 Jul 2013 14:00:28 +0000 (16:00 +0200)
src/libstrongswan/networking/streams/stream_manager.c
src/libstrongswan/networking/streams/stream_service.c
src/libstrongswan/networking/streams/stream_service.h

index 38aaf9a..dbd221e 100644 (file)
@@ -248,6 +248,7 @@ METHOD(stream_manager_t, destroy, void,
        private_stream_manager_t *this)
 {
        remove_stream(this, stream_create_unix);
+       remove_service(this, stream_service_create_unix);
 
        this->streams->destroy(this->streams);
        this->services->destroy(this->services);
@@ -281,6 +282,7 @@ stream_manager_t *stream_manager_create()
        );
 
        add_stream(this, "unix://", stream_create_unix);
+       add_service(this, "unix://", stream_service_create_unix);
 
        return &this->public;
 }
index 489edae..609ff3c 100644 (file)
 #include <threading/thread.h>
 #include <processing/jobs/callback_job.h>
 
+#include <errno.h>
 #include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
 
 typedef struct private_stream_service_t private_stream_service_t;
 
@@ -154,3 +158,50 @@ stream_service_t *stream_service_create_from_fd(int fd)
 
        return &this->public;
 }
+
+/**
+ * See header
+ */
+stream_service_t *stream_service_create_unix(char *uri)
+{
+       struct sockaddr_un addr;
+       mode_t old;
+       int fd, len;
+
+       len = stream_parse_uri_unix(uri, &addr);
+       if (len == -1)
+       {
+               DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
+               return NULL;
+       }
+       fd = socket(AF_UNIX, SOCK_STREAM, 0);
+       if (fd == -1)
+       {
+               DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
+               return NULL;
+       }
+       unlink(addr.sun_path);
+
+       old = umask(~(S_IRWXU | S_IRWXG));
+       if (bind(fd, (struct sockaddr*)&addr, len) < 0)
+       {
+               DBG1(DBG_NET, "binding socket '%s' failed: %s", uri, strerror(errno));
+               close(fd);
+               return NULL;
+       }
+       umask(old);
+       if (chown(addr.sun_path, lib->caps->get_uid(lib->caps),
+                         lib->caps->get_gid(lib->caps)) != 0)
+       {
+               DBG1(DBG_NET, "changing socket permissions for '%s' failed: %s",
+                        uri, strerror(errno));
+       }
+       if (listen(fd, 5) < 0)
+       {
+               DBG1(DBG_NET, "listen on socket '%s' failed: %s", uri, strerror(errno));
+               unlink(addr.sun_path);
+               close(fd);
+               return NULL;
+       }
+       return stream_service_create_from_fd(fd);
+}
index f5da92e..f864a7a 100644 (file)
@@ -75,4 +75,12 @@ struct stream_service_t {
  */
 stream_service_t *stream_service_create_from_fd(int fd);
 
+/**
+ * Create a service instance for UNIX sockets.
+ *
+ * @param uri          UNIX socket specific URI, must start with "unix://"
+ * @return                     stream_service instance, NULL on failure
+ */
+stream_service_t *stream_service_create_unix(char *uri);
+
 #endif /** STREAM_SERVICE_H_ @}*/