diff options
Diffstat (limited to 'proto/wireguard/wireguard.c')
-rw-r--r-- | proto/wireguard/wireguard.c | 249 |
1 files changed, 6 insertions, 243 deletions
diff --git a/proto/wireguard/wireguard.c b/proto/wireguard/wireguard.c index 76333fb5..dd66ab32 100644 --- a/proto/wireguard/wireguard.c +++ b/proto/wireguard/wireguard.c @@ -7,256 +7,17 @@ #include <sys/un.h> #include <unistd.h> #include "lib/lists.h" -#include "lib/socket.h" +#include "lib/ip.h" #include "nest/protocol.h" #include "nest/iface.h" #include "sysdep/linux/wireguard.h" #include "sysdep/unix/unix.h" +#include "sysdep/unix/wg_user.h" #include "wireguard.h" -#define SOCKET_PATH PATH_RUNSTATEDIR "/wireguard/" - #define BA_TUNNEL_ENCAP 0x17 static -char *get_socket_path(struct wg_proto *p, char *buf, uint size) -{ - struct wg_config *c = (struct wg_config *) p->p.cf; - bsnprintf(buf, size, SOCKET_PATH "%s.sock", c->ifname); - return buf; -} - -static -bool has_userspace(struct wg_proto *p) -{ - struct wg_config *c = (struct wg_config *) p->p.cf; - struct stat sb; - char tmp[sizeof(struct sockaddr_un)]; - - if (stat(get_socket_path(p, tmp, sizeof(tmp)), &sb) == 0) - return (sb.st_mode & S_IFMT) == S_IFSOCK; - else - { - log(L_TRACE "WG: no socket %s", tmp); - return false; - } -} - -/* NULL=receiving turned off, returns 1 to clear rx buffer */ -static -int user_rx_hook(struct birdsock *sk, uint size) -{ - log(L_TRACE "WG: RX %d", size); - return 1; -} - -static -void user_tx_hook(struct birdsock *bs) -{ - log(L_TRACE "WG: TX"); -} - -/* errno or zero if EOF */ -static -void user_err_hook(struct birdsock *bs, int err) -{ - /* if (err == 0) */ - /* return; */ - - log(L_TRACE "WG: ERR %d %s", err, bs->err); - if (bs->fd >= 0) - close(bs->fd); - bs->fd = -1; -} - -static void -wg_puts(const char *str, byte **buf, uint *size) -{ - int len = strlen(str); - if (0 < len && len < (int)*size) - { - strcpy(*buf, str); - *size -= len; - *buf += len; - } - else - *size = 0; -} - -static void -wg_put_str(const char *key, const char *value, byte **buf, uint *size) -{ - char tmp[128]; - - int len = snprintf(tmp, sizeof(tmp), "%s=%s\n", key, value); - if (0 < len && len < (int)*size) - { - strcpy(*buf, tmp); - *size -= len; - *buf += len; - } - else - *size = 0; -} - -static void -wg_put_u16(const char *key, u16 value, byte **buf, uint *size) -{ - char tmp[64]; - - int len = snprintf(tmp, sizeof(tmp), "%u", value); - if (len > 0) - wg_put_str(key, tmp, buf, size); - else - *size = 0; -} - -static void -wg_put_bool(const char *key, bool value, byte **buf, uint *size) -{ - char tmp[64]; - - if (value) - wg_put_str(key, "true", buf, size); -} - -static void -wg_put_key(const char *key, wg_key value, byte **buf, uint *size) -{ - char tmp[128]; - - for (uint i=0; i < sizeof(wg_key); i++) - bsnprintf(tmp+2*i, sizeof(tmp)-2*i, "%02x", value[i]); - - wg_put_str(key, tmp, buf, size); -} - -static void -wg_put_endpoint(const char *key, const wg_endpoint *endpoint, byte **buf, uint *size) -{ - char tmp[INET6_ADDRSTRLEN + 16]; - ip_addr ip; - struct iface *ifa = NULL; - uint port = 0; - - if (sockaddr_read((sockaddr*)&endpoint->addr, endpoint->addr.sa_family, - &ip, &ifa, &port) == 0) - { - char *pos = NULL; - - if (ipa_is_ip4(ip)) - pos = ip4_ntop(ipa_to_ip4(ip), tmp); - else - { - tmp[0] = '['; - pos = ip6_ntop(ipa_to_ip6(ip), tmp + 1); - if (ifa) - pos += bsprintf(pos, "%%%u", ifa->index); - *pos++ = ']'; - } - bsprintf(pos, ":%u", port); - wg_put_str("endpoint", tmp, buf, size); - } -} - -static void -wg_put_allowedip(wg_allowedip *allowedip, byte **buf, uint *size) -{ - char tmp[INET6_ADDRSTRLEN + 10]; - ip_addr ip = IP6_NONE; - - switch (allowedip->family) - { - case AF_INET: - ip = ipa_from_in4(allowedip->ip4); - break; - case AF_INET6: - ip = ipa_from_in6(allowedip->ip6); - break; - default: - return; - } - - int res = bsnprintf(tmp, sizeof(tmp), "%I/%u", ip, allowedip->cidr); - - if (res < 0) - { - *size = 0; - return; - } - - wg_put_str("allowed_ip", tmp, buf, size); -} - -static int -user_put_device(wg_device *dev, byte **buf, uint *size) -{ - wg_put_u16("set", 1, buf, size); - wg_put_key("private_key", dev->private_key, buf, size); - wg_put_u16("listen_port", dev->listen_port, buf, size); - wg_put_bool("replace_peers", dev->flags & WGDEVICE_REPLACE_PEERS, buf, size); - - wg_peer *peer = NULL; - wg_for_each_peer(dev, peer) - { - wg_put_key("public_key", peer->public_key, buf, size); - wg_put_endpoint("endpoint", &peer->endpoint, buf, size); - wg_put_bool("replace_allowed_ips", peer->flags & WGPEER_REPLACE_ALLOWEDIPS, buf, size); - - wg_allowedip *allowedip = NULL; - wg_for_each_allowedip(peer, allowedip) - { - wg_put_allowedip(allowedip, buf, size); - } - } - wg_puts("\n", buf, size); - - if (*size > 0) - return 0; - else - return -1; -} - -static int -user_set_device(struct wg_proto *p) -{ - struct wg_config *c = (struct wg_config *) p->p.cf; - char path[sizeof(struct sockaddr_un)]; - - bsnprintf(path, sizeof(path), SOCKET_PATH "%s.sock", c->ifname); - - struct birdsock *sock = sk_new(p->p.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); - log(L_TRACE "WG: socket %d %d %s", res, sock->fd, path); - if (res < 0) - return -1; - - uint tbsize = 8192; - sk_set_tbsize(sock, tbsize); - sk_set_rbsize(sock, 16); - byte *pos = sock->tbuf; - uint size = tbsize; - int len = user_put_device(p->dev, &pos, &size); - - log(L_TRACE "WG: put %d %s", size, sock->tbuf); - - if (len < 0) - { - /* FIXME close */ - return -1; - } - res = sk_send(sock, tbsize - size); - /* Send data, <0=err, >0=ok, 0=sleep */ - log(L_TRACE "WG: send %d", res); - - /* abort(); */ - return -1; -} - -static int get_device(struct wg_proto *p, wg_device **pdev, const char *device_name) { struct wg_config *c = (struct wg_config *) p->p.cf; @@ -339,8 +100,10 @@ int get_device(struct wg_proto *p, wg_device **pdev, const char *device_name) static int set_device(struct wg_proto *p) { - if (has_userspace(p)) - return user_set_device(p); + struct wg_config *c = (struct wg_config *) p->p.cf; + + if (wg_has_userspace(c->ifname)) + return wg_user_set_device(p->p.pool, c->ifname, p->dev); else { log(L_TRACE "WG: wg_set_device"); |