summaryrefslogtreecommitdiff
path: root/proto
diff options
context:
space:
mode:
Diffstat (limited to 'proto')
-rw-r--r--proto/wireguard/Makefile8
-rw-r--r--proto/wireguard/config.Y48
-rw-r--r--proto/wireguard/wireguard.c222
-rw-r--r--proto/wireguard/wireguard.h22
4 files changed, 300 insertions, 0 deletions
diff --git a/proto/wireguard/Makefile b/proto/wireguard/Makefile
new file mode 100644
index 00000000..26a7970f
--- /dev/null
+++ b/proto/wireguard/Makefile
@@ -0,0 +1,8 @@
+WG := $(srcdir)/../WireGuard/contrib/examples/embeddable-wg-library
+
+src := wireguard.c
+obj := $(src-o-files)
+$(all-daemon)
+$(cf-local)
+
+tests_objs := $(tests_objs) $(src-o-files)
diff --git a/proto/wireguard/config.Y b/proto/wireguard/config.Y
new file mode 100644
index 00000000..dfe621bd
--- /dev/null
+++ b/proto/wireguard/config.Y
@@ -0,0 +1,48 @@
+/*
+ * BIRD -- Wireguard Protocol Configuration
+ *
+ * (c) 1999 Martin Mares <mj@ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+CF_HDR
+
+#include "proto/wireguard/wireguard.h"
+
+CF_DEFINES
+
+#define WG_CFG ((struct wg_config *) this_proto)
+
+CF_DECLS
+
+CF_KEYWORDS(WIREGUARD, PEERS)
+
+CF_GRAMMAR
+
+proto: wireguard_proto '}' ;
+
+wireguard_proto_start: proto_start WIREGUARD {
+ this_proto = proto_config_new(&proto_wireguard, $1);
+ }
+ ;
+
+wireguard_proto:
+ wireguard_proto_start proto_name '{'
+ | wireguard_proto proto_channel ';' { this_proto->net_type = $2->net_type; }
+ | wireguard_proto proto_item ';'
+ | wireguard_proto INTERFACE TEXT ';' { WG_CFG->ifname = $3; }
+ | wireguard_proto PEERS '{' peers '}'
+ ;
+
+peers:
+ /* empty */
+ | peers peer
+
+peer: ipa pubkey ';'
+
+pubkey: TEXT
+
+CF_CODE
+
+CF_END
diff --git a/proto/wireguard/wireguard.c b/proto/wireguard/wireguard.c
new file mode 100644
index 00000000..f45796d5
--- /dev/null
+++ b/proto/wireguard/wireguard.c
@@ -0,0 +1,222 @@
+// Based on proto/rip/rip.c
+
+#include <stdio.h>
+#include "nest/protocol.h"
+#include "nest/iface.h"
+#include "sysdep/linux/wireguard.h"
+#include "wireguard.h"
+#include "proto/bgp/bgp.h"
+
+static void
+wg_init_entry(void *e_)
+{
+ struct wg_entry *e = e_;
+// debug("wg_init_entry\n");
+}
+
+static void
+wg_postconfig(struct proto_config *C)
+{
+ C;
+ debug("postconfig\n");
+}
+
+static void
+wg_if_notify(struct proto *P, unsigned flags, struct iface *i)
+{
+ struct wg_proto *p = (struct wg_proto *) P;
+ struct wg_config *c = P->cf;
+
+ debug("WG: if_notify %p %s %d %s\n", i, i->name, flags, c->ifname);
+ if (c->ifname && !strcmp(i->name, c->ifname)) {
+ debug("WG: found ifname\n");
+ p->iface = i;
+ }
+}
+
+static void
+wg_rt_notify(struct proto *P, rtable *src_table, net *n,
+ rte *new, rte *old, ea_list *attrs)
+{
+ struct wg_proto *p = (struct wg_proto *) P;
+ struct wg_entry *en;
+ struct iface *iface = NULL;
+ const char *ifname = NULL;
+
+// debug("WG: notify\n");
+
+ if (new) {
+ iface = new->attrs->nh.iface;
+ ifname = iface ? iface->name : NULL;
+
+ if (iface && iface == p->iface) {
+ struct eattr *t;
+
+ debug("WG: found iface\n");
+ en = fib_get(&p->rtable, n->n.addr);
+
+ debug("WG: notify new %d %N\n",
+ new->attrs->dest, n->n.addr);
+
+ t = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_TUNNEL_ENCAP));
+ if (t) {
+ log(L_TRACE "WG: Attr %x %x", t->flags, t->type);
+/*
+ struct sub_tlv_remove_endpoint {
+ u32 asn;
+ u8 address_family;
+ union {
+ ip4_addr ip4;
+ ip6_addr ip6;
+ };
+ };
+
+ struct sub_tlv_udp_dest_port {
+ u16 port;
+ };
+
+ struct sub_tlv_wireguard {
+ u8 pubkey[32];
+ };
+
+ struct sub_tlv {
+ u8 type;
+ union {
+ struct {
+ u8 length;
+ struct sub_tlv_value value[];
+ } s8;
+ struct {
+ u16 length;
+ struct sub_tlv_value value[];
+ } s16;
+ } u;
+ };
+
+ struct bgp_tunnel_encap_attr {
+ u16 type;
+ u16 length;
+ struct sub_tlv stlv[];
+ };
+*/
+ } else {
+ log(L_TRACE "WG: No Attr");
+ }
+
+ // old_metric = en->valid ? en->metric : -1;
+
+// en->valid = RIP_ENTRY_VALID;
+// en->metric = rt_metric;
+// en->tag = rt_tag;
+// en->from = (new->attrs->src->proto == P) ? new->u.rip.from : NULL;
+// en->iface = new->attrs->iface;
+// en->next_hop = new->attrs->gw;
+ }
+
+ } else {
+ debug("WG: notify withdraw\n");
+
+ /* Withdraw */
+ en = fib_find(&p->rtable, n->n.addr);
+
+ if (!en) // || en->valid != RIP_ENTRY_VALID)
+ return;
+
+/*
+ old_metric = en->metric;
+
+ en->valid = RIP_ENTRY_STALE;
+ en->metric = p->infinity;
+ en->tag = 0;
+ en->from = NULL;
+ en->iface = NULL;
+ en->next_hop = IPA_NONE;
+*/
+ }
+
+// TRACE(D_EVENTS, "wg notify %s %s", src_table->name, ifname?ifname:"(null)");
+}
+
+static int
+wg_reload_routes(struct proto *P)
+{
+ struct wg_proto *p = (struct wg_proto *) P;
+
+ debug("reload routes\n");
+
+// TODO
+// WALK_LIST(c, p->channels)
+// channel_request_feeding(c);
+
+ return 1;
+}
+
+
+static struct proto *
+wg_init(struct proto_config *C)
+{
+ struct wg_config *c = (struct pipe_config *) C;
+ struct proto *P = proto_new(C);
+ struct wg_proto *p = (struct wg_proto *) P;
+
+ debug("init\n");
+
+ P->main_channel = proto_add_channel(P, proto_cf_main_channel(C));
+
+ P->if_notify = wg_if_notify;
+ P->rt_notify = wg_rt_notify;
+ P->reload_routes = wg_reload_routes;
+// P->accept_ra_types = RA_ANY;
+
+ return P;
+}
+
+
+static int
+wg_start(struct proto *P)
+{
+ struct wg_config *cf = (struct wg_config *) P->cf;
+ struct wg_proto *p = (struct wg_proto *) P;
+
+ debug("start\n");
+ fib_init(&p->rtable, P->pool, P->net_type, sizeof(struct wg_entry),
+ OFFSETOF(struct wg_entry, n), 0, wg_init_entry);
+ return PS_UP;
+}
+
+static void
+wg_dump(struct proto *P)
+{
+ struct wg_proto *p = (struct wg_proto *) P;
+ int i;
+
+ i = 0;
+ FIB_WALK(&p->rtable, struct wg_entry, en)
+ {
+// struct wg_entry *en = (struct wg_entry *) e;
+ debug("WG: entry #%d:\n",
+ i++);
+ }
+ FIB_WALK_END;
+}
+
+
+struct protocol proto_wireguard = {
+ .name = "Wireguard",
+ .template = "wg%d",
+ .class = PROTOCOL_WG,
+ .channel_mask = NB_ANY,
+ .proto_size = sizeof(struct wg_proto),
+ .config_size = sizeof(struct wg_config),
+ .postconfig = wg_postconfig,
+ .init = wg_init,
+ .start = wg_start,
+ .dump = wg_dump,
+/* .multitable = 1,
+ .preference = DEF_PREF_PIPE,
+ .cleanup = wg_cleanup,
+ .reconfigure = wg_reconfigure,
+ .copy_config = wg_copy_config,
+ .get_status = wg_get_status,
+ .show_proto_info = wg_show_proto_info*/
+};
diff --git a/proto/wireguard/wireguard.h b/proto/wireguard/wireguard.h
new file mode 100644
index 00000000..992bb12b
--- /dev/null
+++ b/proto/wireguard/wireguard.h
@@ -0,0 +1,22 @@
+#ifndef _BIRD_WIREGUARD_H
+#define _BIRD_WIREGUARD_H
+
+#include "nest/protocol.h"
+
+struct wg_config {
+ struct proto_config c;
+ const char *ifname;
+};
+
+struct wg_proto {
+ struct proto p;
+ struct fib rtable;
+ struct iface *iface;
+};
+
+struct wg_entry {
+ struct fib_node n;
+};
+
+
+#endif /* _BIRD_WIREGUARD_H */