aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-06-26 17:08:14 +0200
committerMartin Willi <martin@revosec.ch>2013-07-18 16:00:28 +0200
commitb785cfe05beaa35be96d57a4f1dcc748b91e50b6 (patch)
tree2e9df1389c2143fc3d37aa3a43c82c25528560dd
parentc1fd8c22ce26b0204d979352e292815d6361c8b4 (diff)
downloadstrongswan-b785cfe05beaa35be96d57a4f1dcc748b91e50b6.tar.bz2
strongswan-b785cfe05beaa35be96d57a4f1dcc748b91e50b6.tar.xz
stream: add support for UNIX streams
-rw-r--r--src/libstrongswan/networking/streams/stream.c49
-rw-r--r--src/libstrongswan/networking/streams/stream.h24
-rw-r--r--src/libstrongswan/networking/streams/stream_manager.c4
3 files changed, 77 insertions, 0 deletions
diff --git a/src/libstrongswan/networking/streams/stream.c b/src/libstrongswan/networking/streams/stream.c
index d3b67761e..3c782cce0 100644
--- a/src/libstrongswan/networking/streams/stream.c
+++ b/src/libstrongswan/networking/streams/stream.c
@@ -16,6 +16,8 @@
#include <library.h>
#include <errno.h>
#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
typedef struct private_stream_t private_stream_t;
@@ -266,3 +268,50 @@ stream_t *stream_create_from_fd(int fd)
return &this->public;
}
+
+/**
+ * See header
+ */
+int stream_parse_uri_unix(char *uri, struct sockaddr_un *addr)
+{
+ if (!strpfx(uri, "unix://"))
+ {
+ return -1;
+ }
+ uri += strlen("unix://");
+
+ memset(addr, 0, sizeof(*addr));
+ addr->sun_family = AF_UNIX;
+ strncpy(addr->sun_path, uri, sizeof(addr->sun_path));
+
+ return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path);
+}
+
+/**
+ * See header
+ */
+stream_t *stream_create_unix(char *uri)
+{
+ struct sockaddr_un addr;
+ int len, fd;
+
+ 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 < 0)
+ {
+ DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
+ return NULL;
+ }
+ if (connect(fd, (struct sockaddr*)&addr, len) < 0)
+ {
+ DBG1(DBG_NET, "connecting to '%s' failed: %s", uri, strerror(errno));
+ close(fd);
+ return NULL;
+ }
+ return stream_create_from_fd(fd);
+}
diff --git a/src/libstrongswan/networking/streams/stream.h b/src/libstrongswan/networking/streams/stream.h
index 4e0a67a07..842ad8e67 100644
--- a/src/libstrongswan/networking/streams/stream.h
+++ b/src/libstrongswan/networking/streams/stream.h
@@ -25,6 +25,8 @@ typedef struct stream_t stream_t;
#include <library.h>
+#include <sys/un.h>
+
/**
* Constructor function prototype for stream_t.
*
@@ -122,6 +124,28 @@ struct stream_t {
};
/**
+ * Create a stream for UNIX sockets.
+ *
+ * UNIX URIs start with unix://, followed by the socket path. For absolute
+ * paths, an URI looks something like:
+ *
+ * unix:///path/to/socket
+ *
+ * @param uri UNIX socket specific URI, must start with "unix://"
+ * @return stream instance, NULL on failure
+ */
+stream_t *stream_create_unix(char *uri);
+
+/**
+ * Helper function to parse a unix:// URI to a sockaddr
+ *
+ * @param uri URI
+ * @param addr sockaddr
+ * @return length of sockaddr, -1 on error
+ */
+int stream_parse_uri_unix(char *uri, struct sockaddr_un *addr);
+
+/**
* Create a stream from a file descriptor.
*
* The file descriptor MUST be a socket for non-blocking operation.
diff --git a/src/libstrongswan/networking/streams/stream_manager.c b/src/libstrongswan/networking/streams/stream_manager.c
index d28cb70e2..38aaf9af9 100644
--- a/src/libstrongswan/networking/streams/stream_manager.c
+++ b/src/libstrongswan/networking/streams/stream_manager.c
@@ -247,6 +247,8 @@ METHOD(stream_manager_t, remove_service, void,
METHOD(stream_manager_t, destroy, void,
private_stream_manager_t *this)
{
+ remove_stream(this, stream_create_unix);
+
this->streams->destroy(this->streams);
this->services->destroy(this->services);
this->running->destroy(this->running);
@@ -278,5 +280,7 @@ stream_manager_t *stream_manager_create()
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
+ add_stream(this, "unix://", stream_create_unix);
+
return &this->public;
}