summaryrefslogtreecommitdiff
path: root/src/libstrongswan/networking
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/networking')
-rw-r--r--src/libstrongswan/networking/host.h4
-rw-r--r--src/libstrongswan/networking/host_resolver.c2
-rw-r--r--src/libstrongswan/networking/streams/stream.c133
-rw-r--r--src/libstrongswan/networking/streams/stream.h51
-rw-r--r--src/libstrongswan/networking/streams/stream_manager.c19
-rw-r--r--src/libstrongswan/networking/streams/stream_service.c99
-rw-r--r--src/libstrongswan/networking/streams/stream_service.h19
-rw-r--r--src/libstrongswan/networking/streams/stream_service_tcp.c64
-rw-r--r--src/libstrongswan/networking/streams/stream_service_tcp.h33
-rw-r--r--src/libstrongswan/networking/streams/stream_service_unix.c75
-rw-r--r--src/libstrongswan/networking/streams/stream_service_unix.h42
-rw-r--r--src/libstrongswan/networking/streams/stream_tcp.c99
-rw-r--r--src/libstrongswan/networking/streams/stream_tcp.h52
-rw-r--r--src/libstrongswan/networking/streams/stream_unix.c69
-rw-r--r--src/libstrongswan/networking/streams/stream_unix.h48
-rw-r--r--src/libstrongswan/networking/tun_device.c124
16 files changed, 607 insertions, 326 deletions
diff --git a/src/libstrongswan/networking/host.h b/src/libstrongswan/networking/host.h
index 4fc6cf35c..9c9b5035f 100644
--- a/src/libstrongswan/networking/host.h
+++ b/src/libstrongswan/networking/host.h
@@ -30,10 +30,8 @@ typedef struct host_t host_t;
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
+#include <utils/utils.h>
#include <utils/chunk.h>
/**
diff --git a/src/libstrongswan/networking/host_resolver.c b/src/libstrongswan/networking/host_resolver.c
index 10af11a7f..a7524ac23 100644
--- a/src/libstrongswan/networking/host_resolver.c
+++ b/src/libstrongswan/networking/host_resolver.c
@@ -14,8 +14,6 @@
*/
#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
#include "host_resolver.h"
diff --git a/src/libstrongswan/networking/streams/stream.c b/src/libstrongswan/networking/streams/stream.c
index f6fec0b4a..e49c35a7c 100644
--- a/src/libstrongswan/networking/streams/stream.c
+++ b/src/libstrongswan/networking/streams/stream.c
@@ -16,7 +16,8 @@
#include <library.h>
#include <errno.h>
#include <unistd.h>
-#include <limits.h>
+
+#include "stream.h"
typedef struct private_stream_t private_stream_t;
@@ -65,7 +66,7 @@ METHOD(stream_t, read_, ssize_t,
if (block)
{
- ret = read(this->fd, buf, len);
+ ret = recv(this->fd, buf, len, 0);
}
else
{
@@ -116,7 +117,7 @@ METHOD(stream_t, write_, ssize_t,
{
if (block)
{
- ret = write(this->fd, buf, len);
+ ret = send(this->fd, buf, len, 0);
}
else
{
@@ -287,129 +288,3 @@ 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));
- addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
-
- 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);
-}
-
-/**
- * See header.
- */
-int stream_parse_uri_tcp(char *uri, struct sockaddr *addr)
-{
- char *pos, buf[128];
- host_t *host;
- u_long port;
- int len;
-
- if (!strpfx(uri, "tcp://"))
- {
- return -1;
- }
- uri += strlen("tcp://");
- pos = strrchr(uri, ':');
- if (!pos)
- {
- return -1;
- }
- if (*uri == '[' && pos > uri && *(pos - 1) == ']')
- {
- /* IPv6 URI */
- snprintf(buf, sizeof(buf), "%.*s", (int)(pos - uri - 2), uri + 1);
- }
- else
- {
- snprintf(buf, sizeof(buf), "%.*s", (int)(pos - uri), uri);
- }
- port = strtoul(pos + 1, &pos, 10);
- if (port == ULONG_MAX || *pos || port > 65535)
- {
- return -1;
- }
- host = host_create_from_dns(buf, AF_UNSPEC, port);
- if (!host)
- {
- return -1;
- }
- len = *host->get_sockaddr_len(host);
- memcpy(addr, host->get_sockaddr(host), len);
- host->destroy(host);
- return len;
-}
-
-/**
- * See header
- */
-stream_t *stream_create_tcp(char *uri)
-{
- union {
- struct sockaddr_in in;
- struct sockaddr_in6 in6;
- struct sockaddr sa;
- } addr;
- int fd, len;
-
- len = stream_parse_uri_tcp(uri, &addr.sa);
- if (len == -1)
- {
- DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
- return NULL;
- }
- fd = socket(addr.sa.sa_family, SOCK_STREAM, 0);
- if (fd < 0)
- {
- DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
- return NULL;
- }
- if (connect(fd, &addr.sa, len))
- {
- 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 3516d9186..747bf651c 100644
--- a/src/libstrongswan/networking/streams/stream.h
+++ b/src/libstrongswan/networking/streams/stream.h
@@ -25,9 +25,6 @@ typedef struct stream_t stream_t;
#include <library.h>
-#include <sys/un.h>
-#include <sys/socket.h>
-
/**
* Constructor function prototype for stream_t.
*
@@ -138,54 +135,6 @@ 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 for TCP sockets.
- *
- * TCP URIs start with tcp://, followed by a hostname (FQDN or IP), followed
- * by a colon separated port. A full TCP uri looks something like:
- *
- * tcp://srv.example.com:5555
- * tcp://0.0.0.0:1234
- * tcp://[fec2::1]:7654
- *
- * There is no default port, so a colon after tcp:// is mandatory.
- *
- * @param uri TCP socket specific URI, must start with "tcp://"
- * @return stream instance, NULL on failure
- */
-stream_t *stream_create_tcp(char *uri);
-
-/**
- * Helper function to parse a tcp:// URI to a sockaddr
- *
- * @param uri URI
- * @param addr sockaddr, large enough for URI
- * @return length of sockaddr, -1 on error
- */
-int stream_parse_uri_tcp(char *uri, struct sockaddr *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 2cbd6127e..8de243daa 100644
--- a/src/libstrongswan/networking/streams/stream_manager.c
+++ b/src/libstrongswan/networking/streams/stream_manager.c
@@ -15,6 +15,13 @@
#include "stream_manager.h"
+#include "stream_tcp.h"
+#include "stream_service_tcp.h"
+#ifndef WIN32
+# include "stream_unix.h"
+# include "stream_service_unix.h"
+#endif
+
#include <threading/rwlock.h>
typedef struct private_stream_manager_t private_stream_manager_t;
@@ -193,10 +200,12 @@ METHOD(stream_manager_t, remove_service, void,
METHOD(stream_manager_t, destroy, void,
private_stream_manager_t *this)
{
- remove_stream(this, stream_create_unix);
remove_stream(this, stream_create_tcp);
- remove_service(this, stream_service_create_unix);
remove_service(this, stream_service_create_tcp);
+#ifndef WIN32
+ remove_stream(this, stream_create_unix);
+ remove_service(this, stream_service_create_unix);
+#endif
this->streams->destroy(this->streams);
this->services->destroy(this->services);
@@ -226,10 +235,12 @@ stream_manager_t *stream_manager_create()
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
- add_stream(this, "unix://", stream_create_unix);
add_stream(this, "tcp://", stream_create_tcp);
- add_service(this, "unix://", stream_service_create_unix);
add_service(this, "tcp://", stream_service_create_tcp);
+#ifndef WIN32
+ add_stream(this, "unix://", stream_create_unix);
+ add_service(this, "unix://", stream_service_create_unix);
+#endif
return &this->public;
}
diff --git a/src/libstrongswan/networking/streams/stream_service.c b/src/libstrongswan/networking/streams/stream_service.c
index 4e0eebddb..7358c580e 100644
--- a/src/libstrongswan/networking/streams/stream_service.c
+++ b/src/libstrongswan/networking/streams/stream_service.c
@@ -19,10 +19,10 @@
#include <threading/condvar.h>
#include <processing/jobs/callback_job.h>
+#include "stream_service.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;
@@ -235,98 +235,3 @@ stream_service_t *stream_service_create_from_fd(int fd)
return &this->public;
}
-
-/**
- * See header
- */
-stream_service_t *stream_service_create_unix(char *uri, int backlog)
-{
- 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;
- }
- if (!lib->caps->check(lib->caps, CAP_CHOWN))
- { /* required to chown(2) service socket */
- DBG1(DBG_NET, "socket '%s' requires CAP_CHOWN capability", 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_IRWXO);
- 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, backlog) < 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);
-}
-
-/**
- * See header
- */
-stream_service_t *stream_service_create_tcp(char *uri, int backlog)
-{
- union {
- struct sockaddr_in in;
- struct sockaddr_in6 in6;
- struct sockaddr sa;
- } addr;
- int fd, len, on = 1;
-
- len = stream_parse_uri_tcp(uri, &addr.sa);
- if (len == -1)
- {
- DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
- return NULL;
- }
- fd = socket(addr.sa.sa_family, SOCK_STREAM, 0);
- if (fd < 0)
- {
- DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
- return NULL;
- }
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0)
- {
- DBG1(DBG_NET, "SO_REUSADDR on '%s' failed: %s", uri, strerror(errno));
- }
- if (bind(fd, &addr.sa, len) < 0)
- {
- DBG1(DBG_NET, "binding socket '%s' failed: %s", uri, strerror(errno));
- close(fd);
- return NULL;
- }
- if (listen(fd, backlog) < 0)
- {
- DBG1(DBG_NET, "listen on socket '%s' failed: %s", uri, strerror(errno));
- close(fd);
- return NULL;
- }
- return stream_service_create_from_fd(fd);
-}
diff --git a/src/libstrongswan/networking/streams/stream_service.h b/src/libstrongswan/networking/streams/stream_service.h
index c8faba323..de2aaf7a5 100644
--- a/src/libstrongswan/networking/streams/stream_service.h
+++ b/src/libstrongswan/networking/streams/stream_service.h
@@ -23,7 +23,6 @@
typedef struct stream_service_t stream_service_t;
-#include <library.h>
#include <processing/jobs/job.h>
#include <networking/streams/stream.h>
@@ -83,22 +82,4 @@ 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://"
- * @param backlog size of the backlog queue, as passed to listen()
- * @return stream_service instance, NULL on failure
- */
-stream_service_t *stream_service_create_unix(char *uri, int backlog);
-
-/**
- * Create a service instance for TCP sockets.
- *
- * @param uri TCP socket specific URI, must start with "tcp://"
- * @param backlog size of the backlog queue, as passed to listen()
- * @return stream_service instance, NULL on failure
- */
-stream_service_t *stream_service_create_tcp(char *uri, int backlog);
-
#endif /** STREAM_SERVICE_H_ @}*/
diff --git a/src/libstrongswan/networking/streams/stream_service_tcp.c b/src/libstrongswan/networking/streams/stream_service_tcp.c
new file mode 100644
index 000000000..4082834c8
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_service_tcp.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <library.h>
+#include <networking/streams/stream_tcp.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+/**
+ * See header
+ */
+stream_service_t *stream_service_create_tcp(char *uri, int backlog)
+{
+ union {
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr sa;
+ } addr;
+ int fd, len, on = 1;
+
+ len = stream_parse_uri_tcp(uri, &addr.sa);
+ if (len == -1)
+ {
+ DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
+ return NULL;
+ }
+ fd = socket(addr.sa.sa_family, SOCK_STREAM, 0);
+ if (fd < 0)
+ {
+ DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
+ return NULL;
+ }
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) != 0)
+ {
+ DBG1(DBG_NET, "SO_REUSADDR on '%s' failed: %s", uri, strerror(errno));
+ }
+ if (bind(fd, &addr.sa, len) < 0)
+ {
+ DBG1(DBG_NET, "binding socket '%s' failed: %s", uri, strerror(errno));
+ close(fd);
+ return NULL;
+ }
+ if (listen(fd, backlog) < 0)
+ {
+ DBG1(DBG_NET, "listen on socket '%s' failed: %s", uri, strerror(errno));
+ close(fd);
+ return NULL;
+ }
+ return stream_service_create_from_fd(fd);
+}
diff --git a/src/libstrongswan/networking/streams/stream_service_tcp.h b/src/libstrongswan/networking/streams/stream_service_tcp.h
new file mode 100644
index 000000000..f63f0074b
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_service_tcp.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup stream_service_tcp stream_service_tcp
+ * @{ @ingroup stream
+ */
+
+#ifndef STREAM_SERVICE_TCP_H_
+#define STREAM_SERVICE_TCP_H_
+
+/**
+ * Create a service instance for TCP sockets.
+ *
+ * @param uri TCP socket specific URI, must start with "tcp://"
+ * @param backlog size of the backlog queue, as passed to listen()
+ * @return stream_service instance, NULL on failure
+ */
+stream_service_t *stream_service_create_tcp(char *uri, int backlog);
+
+#endif /** STREAM_SERVICE_TCP_H_ @}*/
diff --git a/src/libstrongswan/networking/streams/stream_service_unix.c b/src/libstrongswan/networking/streams/stream_service_unix.c
new file mode 100644
index 000000000..1ed27c499
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_service_unix.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <library.h>
+#include <networking/streams/stream_unix.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+
+/**
+ * See header
+ */
+stream_service_t *stream_service_create_unix(char *uri, int backlog)
+{
+ 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;
+ }
+ if (!lib->caps->check(lib->caps, CAP_CHOWN))
+ { /* required to chown(2) service socket */
+ DBG1(DBG_NET, "socket '%s' requires CAP_CHOWN capability", 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_IRWXO);
+ 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, backlog) < 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);
+}
diff --git a/src/libstrongswan/networking/streams/stream_service_unix.h b/src/libstrongswan/networking/streams/stream_service_unix.h
new file mode 100644
index 000000000..14c09cbb5
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_service_unix.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup stream_service_unix stream_service_unix
+ * @{ @ingroup stream
+ */
+
+#ifndef STREAM_SERVICE_UNIX_H_
+#define STREAM_SERVICE_UNIX_H_
+
+/**
+ * Create a service instance for UNIX sockets.
+ *
+ * @param uri UNIX socket specific URI, must start with "unix://"
+ * @param backlog size of the backlog queue, as passed to listen()
+ * @return stream_service instance, NULL on failure
+ */
+stream_service_t *stream_service_create_unix(char *uri, int backlog);
+
+/**
+ * Create a service instance for TCP sockets.
+ *
+ * @param uri TCP socket specific URI, must start with "tcp://"
+ * @param backlog size of the backlog queue, as passed to listen()
+ * @return stream_service instance, NULL on failure
+ */
+stream_service_t *stream_service_create_tcp(char *uri, int backlog);
+
+#endif /** STREAM_SERVICE_UNIX_H_ @}*/
diff --git a/src/libstrongswan/networking/streams/stream_tcp.c b/src/libstrongswan/networking/streams/stream_tcp.c
new file mode 100644
index 000000000..5459145a0
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_tcp.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <library.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "stream_tcp.h"
+
+/**
+ * See header.
+ */
+int stream_parse_uri_tcp(char *uri, struct sockaddr *addr)
+{
+ char *pos, buf[128];
+ host_t *host;
+ u_long port;
+ int len;
+
+ if (!strpfx(uri, "tcp://"))
+ {
+ return -1;
+ }
+ uri += strlen("tcp://");
+ pos = strrchr(uri, ':');
+ if (!pos)
+ {
+ return -1;
+ }
+ if (*uri == '[' && pos > uri && *(pos - 1) == ']')
+ {
+ /* IPv6 URI */
+ snprintf(buf, sizeof(buf), "%.*s", (int)(pos - uri - 2), uri + 1);
+ }
+ else
+ {
+ snprintf(buf, sizeof(buf), "%.*s", (int)(pos - uri), uri);
+ }
+ port = strtoul(pos + 1, &pos, 10);
+ if (port == ULONG_MAX || *pos || port > 65535)
+ {
+ return -1;
+ }
+ host = host_create_from_dns(buf, AF_UNSPEC, port);
+ if (!host)
+ {
+ return -1;
+ }
+ len = *host->get_sockaddr_len(host);
+ memcpy(addr, host->get_sockaddr(host), len);
+ host->destroy(host);
+ return len;
+}
+
+/**
+ * See header
+ */
+stream_t *stream_create_tcp(char *uri)
+{
+ union {
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr sa;
+ } addr;
+ int fd, len;
+
+ len = stream_parse_uri_tcp(uri, &addr.sa);
+ if (len == -1)
+ {
+ DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
+ return NULL;
+ }
+ fd = socket(addr.sa.sa_family, SOCK_STREAM, 0);
+ if (fd < 0)
+ {
+ DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
+ return NULL;
+ }
+ if (connect(fd, &addr.sa, len))
+ {
+ 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_tcp.h b/src/libstrongswan/networking/streams/stream_tcp.h
new file mode 100644
index 000000000..5bf6c8235
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_tcp.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup stream_tcp stream_tcp
+ * @{ @ingroup streams
+ */
+
+#ifndef STREAM_TCP_H_
+#define STREAM_TCP_H_
+
+#include <library.h>
+
+/**
+ * Create a stream for TCP sockets.
+ *
+ * TCP URIs start with tcp://, followed by a hostname (FQDN or IP), followed
+ * by a colon separated port. A full TCP uri looks something like:
+ *
+ * tcp://srv.example.com:5555
+ * tcp://0.0.0.0:1234
+ * tcp://[fec2::1]:7654
+ *
+ * There is no default port, so a colon after tcp:// is mandatory.
+ *
+ * @param uri TCP socket specific URI, must start with "tcp://"
+ * @return stream instance, NULL on failure
+ */
+stream_t *stream_create_tcp(char *uri);
+
+/**
+ * Helper function to parse a tcp:// URI to a sockaddr
+ *
+ * @param uri URI
+ * @param addr sockaddr, large enough for URI
+ * @return length of sockaddr, -1 on error
+ */
+int stream_parse_uri_tcp(char *uri, struct sockaddr *addr);
+
+#endif /** STREAM_TCP_H_ @}*/
diff --git a/src/libstrongswan/networking/streams/stream_unix.c b/src/libstrongswan/networking/streams/stream_unix.c
new file mode 100644
index 000000000..13e56bc78
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_unix.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <library.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "stream_unix.h"
+
+/**
+ * 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));
+ addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
+
+ 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_unix.h b/src/libstrongswan/networking/streams/stream_unix.h
new file mode 100644
index 000000000..5204251b3
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_unix.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup stream_unix stream_unix
+ * @{ @ingroup streams
+ */
+
+#ifndef STREAM_UNIX_H_
+#define STREAM_UNIX_H_
+
+#include <sys/un.h>
+
+/**
+ * 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);
+
+#endif /** STREAM_UNIX_H_ @}*/
diff --git a/src/libstrongswan/networking/tun_device.c b/src/libstrongswan/networking/tun_device.c
index ecefdc233..ff2c4a337 100644
--- a/src/libstrongswan/networking/tun_device.c
+++ b/src/libstrongswan/networking/tun_device.c
@@ -16,24 +16,12 @@
* for more details.
*/
-#include <errno.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <net/if.h>
-
-#if !defined(__APPLE__) && !defined(__linux__) && !defined(HAVE_NET_IF_TUN_H)
-
#include "tun_device.h"
#include <utils/debug.h>
+#include <threading/thread.h>
-#warning TUN devices are not supported!
+#if !defined(__APPLE__) && !defined(__linux__) && !defined(HAVE_NET_IF_TUN_H)
tun_device_t *tun_device_create(const char *name_tmpl)
{
@@ -43,6 +31,17 @@ tun_device_t *tun_device_create(const char *name_tmpl)
#else /* TUN devices supported */
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <net/if.h>
+
#ifdef __APPLE__
#include <net/if_utun.h>
#include <netinet/in_var.h>
@@ -50,15 +49,14 @@ tun_device_t *tun_device_create(const char *name_tmpl)
#elif defined(__linux__)
#include <linux/types.h>
#include <linux/if_tun.h>
+#elif __FreeBSD__ >= 10
+#include <net/if_tun.h>
+#include <net/if_var.h>
+#include <netinet/in_var.h>
#else
#include <net/if_tun.h>
#endif
-#include "tun_device.h"
-
-#include <utils/debug.h>
-#include <threading/thread.h>
-
#define TUN_DEFAULT_MTU 1500
typedef struct private_tun_device_t private_tun_device_t;
@@ -101,8 +99,79 @@ struct private_tun_device_t {
u_int8_t netmask;
};
-METHOD(tun_device_t, set_address, bool,
- private_tun_device_t *this, host_t *addr, u_int8_t netmask)
+/**
+ * FreeBSD 10 deprecated the SIOCSIFADDR etc. commands.
+ */
+#if __FreeBSD__ >= 10
+
+static bool set_address_and_mask(struct in_aliasreq *ifra, host_t *addr,
+ u_int8_t netmask)
+{
+ host_t *mask;
+
+ memcpy(&ifra->ifra_addr, addr->get_sockaddr(addr),
+ *addr->get_sockaddr_len(addr));
+ /* set the same address as destination address */
+ memcpy(&ifra->ifra_dstaddr, addr->get_sockaddr(addr),
+ *addr->get_sockaddr_len(addr));
+
+ mask = host_create_netmask(addr->get_family(addr), netmask);
+ if (!mask)
+ {
+ DBG1(DBG_LIB, "invalid netmask: %d", netmask);
+ return FALSE;
+ }
+ memcpy(&ifra->ifra_mask, mask->get_sockaddr(mask),
+ *mask->get_sockaddr_len(mask));
+ mask->destroy(mask);
+ return TRUE;
+}
+
+/**
+ * Set the address using the more flexible SIOCAIFADDR/SIOCDIFADDR commands
+ * on FreeBSD 10 an newer.
+ */
+static bool set_address_impl(private_tun_device_t *this, host_t *addr,
+ u_int8_t netmask)
+{
+ struct in_aliasreq ifra;
+
+ memset(&ifra, 0, sizeof(ifra));
+ strncpy(ifra.ifra_name, this->if_name, IFNAMSIZ);
+
+ if (this->address)
+ { /* remove the existing address first */
+ if (!set_address_and_mask(&ifra, this->address, this->netmask))
+ {
+ return FALSE;
+ }
+ if (ioctl(this->sock, SIOCDIFADDR, &ifra) < 0)
+ {
+ DBG1(DBG_LIB, "failed to remove existing address on %s: %s",
+ this->if_name, strerror(errno));
+ return FALSE;
+ }
+ }
+ if (!set_address_and_mask(&ifra, addr, netmask))
+ {
+ return FALSE;
+ }
+ if (ioctl(this->sock, SIOCAIFADDR, &ifra) < 0)
+ {
+ DBG1(DBG_LIB, "failed to add address on %s: %s",
+ this->if_name, strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#else /* __FreeBSD__ */
+
+/**
+ * Set the address using the classic SIOCSIFADDR etc. commands on other systems.
+ */
+static bool set_address_impl(private_tun_device_t *this, host_t *addr,
+ u_int8_t netmask)
{
struct ifreq ifr;
host_t *mask;
@@ -143,6 +212,19 @@ METHOD(tun_device_t, set_address, bool,
this->if_name, strerror(errno));
return FALSE;
}
+ return TRUE;
+}
+
+#endif /* __FreeBSD__ */
+
+METHOD(tun_device_t, set_address, bool,
+ private_tun_device_t *this, host_t *addr, u_int8_t netmask)
+{
+ if (!set_address_impl(this, addr, netmask))
+ {
+ return FALSE;
+ }
+ DESTROY_IF(this->address);
this->address = addr->clone(addr);
this->netmask = netmask;
return TRUE;