diff options
-rw-r--r-- | proto/wireguard/config.Y | 18 | ||||
-rw-r--r-- | proto/wireguard/wireguard.c | 75 | ||||
-rw-r--r-- | proto/wireguard/wireguard.h | 17 |
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 { |