diff options
Diffstat (limited to 'src/libstrongswan/networking')
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; |