diff options
Diffstat (limited to 'proto')
-rw-r--r-- | proto/wireguard/Makefile | 8 | ||||
-rw-r--r-- | proto/wireguard/config.Y | 48 | ||||
-rw-r--r-- | proto/wireguard/wireguard.c | 222 | ||||
-rw-r--r-- | proto/wireguard/wireguard.h | 22 |
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 */ |