// Based on proto/rip/rip.c #include #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*/ };