From b49989e1b7c026f30a774d01dcce549cab818350 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Wed, 27 Mar 2019 02:17:49 +0100 Subject: Wireguard: Add peer list --- proto/wireguard/config.Y | 17 ++++++--- proto/wireguard/wireguard.c | 93 ++++++++++++++++++++++++++------------------- proto/wireguard/wireguard.h | 24 ++++++------ 3 files changed, 76 insertions(+), 58 deletions(-) diff --git a/proto/wireguard/config.Y b/proto/wireguard/config.Y index ff57c9bc..dceebb67 100644 --- a/proto/wireguard/config.Y +++ b/proto/wireguard/config.Y @@ -14,6 +14,8 @@ CF_DEFINES #define WG_CFG ((struct wg_config *) this_proto) +static struct peer_config *this_peer = NULL; + CF_DECLS CF_KEYWORDS(WIREGUARD, PRIVATE_KEY, LISTEN_PORT, PUBLIC_KEY, ENDPOINT, ALLOWED_IP) @@ -24,6 +26,7 @@ proto: wireguard_proto '}' ; wireguard_proto_start: proto_start WIREGUARD { this_proto = proto_config_new(&proto_wireguard, $1); + init_list(&WG_CFG->peers); } ; @@ -39,9 +42,11 @@ wireguard_proto: wg_peer: wg_peer_start wg_peer_opt_list wg_peer_end; -wg_peer_start: PEER +wg_peer_start: PEER { this_peer = peer_new(WG_CFG); } -wg_peer_end: +wg_peer_end: { + this_peer = NULL; +} ; wg_peer_item: @@ -65,14 +70,14 @@ 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; } +public_key: text { this_peer->public_key = $1; } -endpoint: ipa { WG_CFG->peer.endpoint = $1; } +endpoint: ipa { this_peer->endpoint = $1; } -port: expr { WG_CFG->peer.remote_port = $1; } +port: expr { this_peer->remote_port = $1; } allowedip: - net_or_ipa { WG_CFG->peer.allowedip = $1; } + net_or_ipa { this_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 4b065751..56507e2b 100644 --- a/proto/wireguard/wireguard.c +++ b/proto/wireguard/wireguard.c @@ -25,39 +25,49 @@ int get_device(struct wg_proto *p, wg_device **pdev, const char *device_name) 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) + struct peer_config *pc = NULL; + WALK_LIST(pc,c->peers) { - 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; - } + wg_peer *peer = calloc(1, sizeof(wg_peer)); + if (!dev->first_peer) + dev->first_peer = peer; + if (dev->last_peer) + dev->last_peer->next_peer = peer; + dev->last_peer = peer; + + if (pc->public_key) + { + peer->flags = WGPEER_HAS_PUBLIC_KEY; + wg_key_from_base64(peer->public_key, pc->public_key); + } + peer->next_peer = NULL; + + sockaddr_fill((sockaddr*)&peer->endpoint.addr, + ipa_is_ip4(pc->endpoint) ? AF_INET : AF_INET6, + pc->endpoint, NULL, pc->remote_port); + + wg_allowedip *allowedip = calloc(1, sizeof(wg_allowedip)); + peer->first_allowedip = allowedip; + peer->last_allowedip = allowedip; + + switch (pc->allowedip.type) + { + case NET_IP4: + allowedip->family = AF_INET; + allowedip->ip4 = ipa_to_in4(net_prefix(&pc->allowedip)); + allowedip->cidr = net_pxlen(&pc->allowedip); + break; + case NET_IP6: + allowedip->family = AF_INET6; + allowedip->ip6 = ipa_to_in6(net_prefix(&pc->allowedip)); + allowedip->cidr = net_pxlen(&pc->allowedip); + break; + default: + break; + } - allowedip->next_allowedip = NULL; + allowedip->next_allowedip = NULL; + } *pdev = dev; return 0; @@ -393,9 +403,9 @@ wg_rt_notify(struct proto *P, struct channel *CH, struct network *n, if (t && t->u.ptr && decode_tunnel_encap(t, &pubkey, &remote_ep_as4, &remote_ep_addr, &color, &udp_dest_port, &flags) == 0) { log(L_TRACE "WG: Attr %x %x %d %04x", t->flags, t->type, t->u.ptr->length, flags); - struct wg_device *dev = NULL; + struct wg_device *dev = p->dev; - if (get_device(p, &dev, ifname) == 0) { + if (dev != NULL) { bool dirty = false; bool found = false; struct wg_peer *peer = NULL; @@ -429,8 +439,6 @@ wg_rt_notify(struct proto *P, struct channel *CH, struct network *n, int res = wg_set_device(dev); log(L_TRACE "WG: wg_set_device %d", res); } - wg_free_device(dev); - dev = NULL; } @@ -498,9 +506,9 @@ wg_rt_notify(struct proto *P, struct channel *CH, struct network *n, return; } - struct wg_device *dev = NULL; + struct wg_device *dev = p->dev; - if (get_device(p, &dev, c->ifname) == 0) { + if (dev != NULL) { bool found = false; struct wg_peer *peer = NULL; wg_for_each_peer(dev, peer) { @@ -575,9 +583,6 @@ wg_rt_notify(struct proto *P, struct channel *CH, struct network *n, } } - wg_free_device(dev); - dev = NULL; - /* old_metric = en->metric; @@ -679,6 +684,14 @@ wg_dump(struct proto *P) } } +struct peer_config *peer_new(struct wg_config *c) +{ + struct peer_config *pc = cfg_allocz(sizeof(struct peer_config)); + debug("peer_new %p\n", pc); + add_tail(&c->peers, (node*)pc); + return pc; +} + struct channel_class channel_wg = { .channel_size = sizeof(struct wg_channel), .config_size = sizeof(struct wg_channel_config), diff --git a/proto/wireguard/wireguard.h b/proto/wireguard/wireguard.h index cc116e38..69345953 100644 --- a/proto/wireguard/wireguard.h +++ b/proto/wireguard/wireguard.h @@ -4,20 +4,22 @@ #include "nest/protocol.h" #include "sysdep/linux/wireguard.h" +struct peer_config { + node n; + const char *public_key; + u16 listen_port; + ip_addr endpoint; + u16 remote_port; + struct net_addr allowedip; +}; + struct wg_config { struct proto_config c; const char *ifname; const char *socket_path; const char *private_key; u16 listen_port; - - struct peer_config { - const char *public_key; - u16 listen_port; - ip_addr endpoint; - u16 remote_port; - struct net_addr allowedip; - } peer; + list peers; }; struct wg_proto { @@ -25,10 +27,6 @@ struct wg_proto { struct iface *iface; wg_key private_key; wg_device *dev; - - struct peer { - wg_key public_key; - } peer; }; struct wg_channel_config { @@ -47,4 +45,6 @@ struct wg_entry { extern struct channel_class channel_wg; +struct peer_config *peer_new(struct wg_config *c); + #endif /* _BIRD_WIREGUARD_H */ -- cgit v1.2.3