summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--proto/wireguard/config.Y18
-rw-r--r--proto/wireguard/wireguard.c75
-rw-r--r--proto/wireguard/wireguard.h17
3 files changed, 98 insertions, 12 deletions
diff --git a/proto/wireguard/config.Y b/proto/wireguard/config.Y
index 9a414085..ff57c9bc 100644
--- a/proto/wireguard/config.Y
+++ b/proto/wireguard/config.Y
@@ -16,7 +16,7 @@ CF_DEFINES
CF_DECLS
-CF_KEYWORDS(WIREGUARD, PUBKEY, ENDPOINT, ALLOWED_IPS)
+CF_KEYWORDS(WIREGUARD, PRIVATE_KEY, LISTEN_PORT, PUBLIC_KEY, ENDPOINT, ALLOWED_IP)
CF_GRAMMAR
@@ -32,6 +32,8 @@ wireguard_proto:
| wireguard_proto wg_proto_channel ';'
| wireguard_proto proto_item ';'
| wireguard_proto INTERFACE TEXT ';' { WG_CFG->ifname = $3; }
+ | wireguard_proto PRIVATE_KEY private_key ';'
+ | wireguard_proto LISTEN_PORT listen_port ';'
| wireguard_proto wg_peer ';'
;
@@ -43,10 +45,10 @@ wg_peer_end:
;
wg_peer_item:
- PUBKEY pubkey
+ PUBLIC_KEY public_key
| ENDPOINT endpoint
| PORT port
- | ALLOWED_IPS allowed_ips
+ | ALLOWED_IP allowedip
;
wg_peer_opts:
@@ -59,14 +61,18 @@ wg_peer_opt_list:
| '{' wg_peer_opts '}'
;
-pubkey: text { WG_CFG->peer.pubkey = $1; }
+private_key: text { WG_CFG->private_key = $1; }
+
+listen_port: expr { WG_CFG->listen_port = $1; }
+
+public_key: text { WG_CFG->peer.public_key = $1; }
endpoint: ipa { WG_CFG->peer.endpoint = $1; }
port: expr { WG_CFG->peer.remote_port = $1; }
-allowed_ips:
- net_or_ipa { WG_CFG->peer.allowed_ips = $1; }
+allowedip:
+ net_or_ipa { WG_CFG->peer.allowedip = $1; }
;
wg_proto_channel: wg_channel_start channel_opt_list wg_channel_end;
diff --git a/proto/wireguard/wireguard.c b/proto/wireguard/wireguard.c
index 2a020be2..4b065751 100644
--- a/proto/wireguard/wireguard.c
+++ b/proto/wireguard/wireguard.c
@@ -8,6 +8,61 @@
#include "wireguard.h"
#include "proto/bgp/bgp.h"
+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;
+
+ /* if (has_user_space(p)) */
+ /* return user_get_device(p, dev, device_name); */
+ /* else */
+ /* return wg_get_device(dev, device_name); */
+
+ wg_device *dev = calloc(1, sizeof(wg_device));
+ strncpy(dev->name, device_name, sizeof(dev->name));
+ dev->flags = WGDEVICE_HAS_PRIVATE_KEY | WGDEVICE_HAS_LISTEN_PORT;
+ memcpy(dev->private_key, p->private_key, sizeof(dev->private_key));
+ dev->listen_port = c->listen_port;
+ debug("listen port %d\n", c->listen_port);
+
+ wg_peer *peer = calloc(1, sizeof(wg_peer));
+ dev->first_peer = peer;
+ dev->last_peer = peer;
+
+ peer->flags = WGPEER_HAS_PUBLIC_KEY;
+ memcpy(peer->public_key, p->peer.public_key, sizeof(peer->public_key));
+ peer->next_peer = NULL;
+
+ sockaddr_fill((sockaddr*)&peer->endpoint.addr,
+ ipa_is_ip4(c->peer.endpoint) ? AF_INET : AF_INET6,
+ c->peer.endpoint, NULL, c->peer.remote_port);
+
+ wg_allowedip *allowedip = calloc(1, sizeof(wg_allowedip));
+ peer->first_allowedip = allowedip;
+ peer->last_allowedip = allowedip;
+
+ switch (c->peer.allowedip.type)
+ {
+ case NET_IP4:
+ allowedip->family = AF_INET;
+ allowedip->ip4 = ipa_to_in4(net_prefix(&c->peer.allowedip));
+ allowedip->cidr = net_pxlen(&c->peer.allowedip);
+ break;
+ case NET_IP6:
+ allowedip->family = AF_INET6;
+ allowedip->ip6 = ipa_to_in6(net_prefix(&c->peer.allowedip));
+ allowedip->cidr = net_pxlen(&c->peer.allowedip);
+ break;
+ default:
+ break;
+ }
+
+ allowedip->next_allowedip = NULL;
+
+ *pdev = dev;
+ return 0;
+}
+
static void
wg_init_entry(void *e_)
{
@@ -340,7 +395,7 @@ wg_rt_notify(struct proto *P, struct channel *CH, struct network *n,
struct wg_device *dev = NULL;
- if (wg_get_device(&dev, ifname) == 0) {
+ if (get_device(p, &dev, ifname) == 0) {
bool dirty = false;
bool found = false;
struct wg_peer *peer = NULL;
@@ -445,7 +500,7 @@ wg_rt_notify(struct proto *P, struct channel *CH, struct network *n,
struct wg_device *dev = NULL;
- if (wg_get_device(&dev, c->ifname) == 0) {
+ if (get_device(p, &dev, c->ifname) == 0) {
bool found = false;
struct wg_peer *peer = NULL;
wg_for_each_peer(dev, peer) {
@@ -566,6 +621,13 @@ wg_init(struct proto_config *C)
P->reload_routes = wg_reload_routes;
// P->accept_ra_types = RA_ANY;
+ log(L_TRACE "WG: private_key %s", c->private_key);
+ if (c->private_key)
+ wg_key_from_base64(p->private_key, c->private_key);
+ log(L_TRACE "WG: public_key %s", c->peer.public_key);
+ if (c->peer.public_key)
+ wg_key_from_base64(p->peer.public_key, c->peer.public_key);
+
/* Add all channels */
struct wg_channel_config *cc;
WALK_LIST(cc, C->channels)
@@ -581,7 +643,14 @@ wg_start(struct proto *P)
struct wg_config *cf UNUSED = (struct wg_config *) P->cf;
struct wg_proto *p = (struct wg_proto *) P;
- debug("start\n");
+ log(L_TRACE "WG: start");
+
+ if (get_device(p, &p->dev, cf->ifname) >= 0)
+ {
+ int res = wg_set_device(p->dev);
+ log(L_TRACE "WG: wg_set_device %d", res);
+ }
+
struct wg_channel *ch;
WALK_LIST(ch,p->p.channels) {
fib_init(&ch->rtable, P->pool, ch->c.net_type, sizeof(struct wg_entry),
diff --git a/proto/wireguard/wireguard.h b/proto/wireguard/wireguard.h
index 1292b1c0..cc116e38 100644
--- a/proto/wireguard/wireguard.h
+++ b/proto/wireguard/wireguard.h
@@ -2,22 +2,33 @@
#define _BIRD_WIREGUARD_H
#include "nest/protocol.h"
+#include "sysdep/linux/wireguard.h"
struct wg_config {
struct proto_config c;
const char *ifname;
+ const char *socket_path;
+ const char *private_key;
+ u16 listen_port;
- struct peer {
- const char *pubkey;
+ struct peer_config {
+ const char *public_key;
+ u16 listen_port;
ip_addr endpoint;
u16 remote_port;
- struct net_addr allowed_ips;
+ struct net_addr allowedip;
} peer;
};
struct wg_proto {
struct proto p;
struct iface *iface;
+ wg_key private_key;
+ wg_device *dev;
+
+ struct peer {
+ wg_key public_key;
+ } peer;
};
struct wg_channel_config {