summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sysdep/unix/io.c10
-rw-r--r--sysdep/unix/unix.h2
-rw-r--r--sysdep/unix/wg_user.c27
-rw-r--r--sysdep/unix/wg_user.h2
4 files changed, 30 insertions, 11 deletions
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 3aba48d2..14bf99fe 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -1513,11 +1513,14 @@ sk_open_unix(sock *s, char *name)
}
int
-sk_connect_unix(sock *s, char *name)
+sk_connect_unix(sock *s, char *name, socklen_t namelen)
{
struct sockaddr_un sa;
int fd;
+ if (namelen > sizeof(sa.sun_path))
+ return -1;
+
/* We are sloppy during error (leak fd and not set s->err), but we die anyway */
fd = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -1528,10 +1531,11 @@ sk_connect_unix(sock *s, char *name)
return -1;
/* Path length checked in test_old_bird() */
+ memset(&sa, 0, sizeof(sa));
sa.sun_family = AF_UNIX;
- strcpy(sa.sun_path, name);
+ memcpy(sa.sun_path, name, namelen);
- if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) < 0)
+ if (connect(fd, (struct sockaddr *) &sa, sizeof(sa.sun_family) + namelen) < 0)
return -1;
s->fd = fd;
diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h
index 849e5947..a95e5c25 100644
--- a/sysdep/unix/unix.h
+++ b/sysdep/unix/unix.h
@@ -108,7 +108,7 @@ void io_loop(void);
void io_log_dump(void);
int sk_open_unix(struct birdsock *s, char *name);
struct rfile *rf_open(struct pool *, const char *name, const char *mode);
-int sk_connect_unix(struct birdsock *s, char *name);
+int sk_connect_unix(struct birdsock *s, char *name, socklen_t namelen);
void *rf_file(struct rfile *f);
int rf_fileno(struct rfile *f);
void test_old_bird(char *path);
diff --git a/sysdep/unix/wg_user.c b/sysdep/unix/wg_user.c
index db92ea8e..5d4d59a0 100644
--- a/sysdep/unix/wg_user.c
+++ b/sysdep/unix/wg_user.c
@@ -12,18 +12,32 @@
#include "sysdep/linux/wireguard.h"
static
-char *get_socket_path(const char *ifname, char *buf, uint size)
+socklen_t get_socket_path(const char *ifname, char *buf, uint size)
{
- bsnprintf(buf, size, SOCKET_PATH "%s.sock", ifname);
- return buf;
+ int pos = 0;
+
+ if (size < 1)
+ return 0;
+
+#ifdef ANDROID
+ /* Abstract socket */
+ buf[pos++] = 0;
+#endif
+ bsnprintf(buf+pos, size-pos, SOCKET_PATH "%s.sock", ifname);
+ return pos + strlen(buf+pos);
}
bool wg_has_userspace(const char *ifname)
{
struct stat sb;
char tmp[sizeof(struct sockaddr_un)];
+ socklen_t tmplen = get_socket_path(ifname, tmp, sizeof(tmp));
- if (stat(get_socket_path(ifname, tmp, sizeof(tmp)), &sb) == 0)
+ if (tmplen > 0 && tmp[0] == 0)
+ /* System with abstract socket (Android) always use WireGuard's userspace
+ implementation. */
+ return true;
+ else if (stat(tmp, &sb) == 0)
return (sb.st_mode & S_IFMT) == S_IFSOCK;
else
{
@@ -210,14 +224,13 @@ wg_user_set_device(struct pool *pool,
struct wg_device *dev)
{
char path[sizeof(struct sockaddr_un)];
-
- bsnprintf(path, sizeof(path), SOCKET_PATH "%s.sock", ifname);
+ socklen_t pathlen = get_socket_path(ifname, path, sizeof(path));
struct birdsock *sock = sk_new(pool);
sock->rx_hook = user_rx_hook;
sock->tx_hook = user_tx_hook;
sock->err_hook = user_err_hook;
- int res = sk_connect_unix(sock, path);
+ int res = sk_connect_unix(sock, path, pathlen);
DBG(L_TRACE "WG: socket %d %d %s", res, sock->fd, path);
if (res < 0)
{
diff --git a/sysdep/unix/wg_user.h b/sysdep/unix/wg_user.h
index a5e4251a..5bd9a41a 100644
--- a/sysdep/unix/wg_user.h
+++ b/sysdep/unix/wg_user.h
@@ -3,7 +3,9 @@
#include "sysdep/config.h"
+#ifndef SOCKET_PATH
#define SOCKET_PATH PATH_RUNSTATEDIR "/wireguard/"
+#endif /* SOCKET_PATH */
struct pool;
struct wg_device;