diff options
-rw-r--r-- | lib/tunnel_encaps.c | 65 | ||||
-rw-r--r-- | lib/tunnel_encaps.h | 18 | ||||
-rw-r--r-- | proto/wireguard/wireguard.c | 26 |
3 files changed, 58 insertions, 51 deletions
diff --git a/lib/tunnel_encaps.c b/lib/tunnel_encaps.c index c2b0f60d..5b72cb61 100644 --- a/lib/tunnel_encaps.c +++ b/lib/tunnel_encaps.c @@ -1,21 +1,19 @@ +#include <stdlib.h> #include "lib/tunnel_encaps.h" static -int decode_encap(const void *p, size_t sub_tlv_len, void *encap, size_t *encap_size, u16 *flags) +int decode_encap(const void *p, size_t sub_tlv_len, struct tunnel_encap *encap, struct pool *pool) { - if (sub_tlv_len > *encap_size) { - log(L_TRACE "WG: encapsulation len error %d > %d", sub_tlv_len, *encap_size); - return -1; - } - - memcpy(encap, p, sub_tlv_len); - *encap_size = sub_tlv_len; - *flags |= FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_ENCAP; + mb_free(encap->encap); + encap->encap = mb_alloc(pool, sub_tlv_len); + memcpy(encap->encap, p, sub_tlv_len); + encap->encap_len = sub_tlv_len; + encap->flags |= FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_ENCAP; return 0; } static -int decode_color(const void *p, size_t sub_tlv_len, u32 *color, u16 *flags) +int decode_color(const void *p, size_t sub_tlv_len, struct tunnel_encap *encap) { if (sub_tlv_len != 8) { log(L_TRACE "WG: color len error %d", sub_tlv_len); @@ -27,33 +25,33 @@ int decode_color(const void *p, size_t sub_tlv_len, u32 *color, u16 *flags) return -1; } - *color = get_u32(p+2); - *flags |= FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_COLOR; + encap->color = get_u32(p+2); + encap->flags |= FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_COLOR; return 0; } static -int decode_udp_dest_port(const void *p, size_t sub_tlv_len, u16 *udp_dest_port, u16 *flags) +int decode_udp_dest_port(const void *p, size_t sub_tlv_len, struct tunnel_encap *encap) { if (sub_tlv_len != 2) { log(L_TRACE "WG: udp dest port len error %d", sub_tlv_len); return -1; } - *udp_dest_port = get_u16(p); - *flags |= FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_UDP_DEST_PORT; + encap->udp_dest_port = get_u16(p); + encap->flags |= FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_UDP_DEST_PORT; return 0; } static -int decode_tunnel_ep(const void *p, size_t sub_tlv_len, u32 *as4, ip_addr *tunnel_ep, u16 *flags) +int decode_tunnel_ep(const void *p, size_t sub_tlv_len, struct tunnel_encap *encap) { if (sub_tlv_len < 6) { log(L_TRACE "WG: tunnel ep len error"); return -1; } - *as4 = get_u32(p); + encap->ep.asn = get_u32(p); u16 af = get_u16(p + 4); switch (af) { case NET_IP4: @@ -61,16 +59,16 @@ int decode_tunnel_ep(const void *p, size_t sub_tlv_len, u32 *as4, ip_addr *tunne log(L_TRACE "WG: IPv4 len error %d", sub_tlv_len); return -1; } - *tunnel_ep = ipa_from_ip4(get_ip4(p + 6)); - *flags |= FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_TUNNEL_EP; + encap->ep.ip = ipa_from_ip4(get_ip4(p + 6)); + encap->flags |= FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_TUNNEL_EP; return 0; case NET_IP6: if (sub_tlv_len != 22) { log(L_TRACE "WG: IPv6 len error %d", sub_tlv_len); return -1; } - *tunnel_ep = ipa_from_ip6(get_ip6(p + 6)); - *flags |= FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_TUNNEL_EP; + encap->ep.ip = ipa_from_ip6(get_ip6(p + 6)); + encap->flags |= FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_TUNNEL_EP; return 0; default: log(L_TRACE "WG: Address family error %d", af); @@ -79,9 +77,7 @@ int decode_tunnel_ep(const void *p, size_t sub_tlv_len, u32 *as4, ip_addr *tunne } static -int decode_sub_tlv(const u8 *p, size_t len, void *encap, size_t *encap_size, - u32 *tunnel_ep_as, ip_addr *tunnel_ep_addr, - u32 *color, u16 *udp_dest_port, u16 *flags) +int decode_sub_tlv(const u8 *p, size_t len, struct tunnel_encap *encap, struct pool *pool) { if (len < 3) { log(L_TRACE "WG: sub_tlv len error %d", len); @@ -115,16 +111,16 @@ int decode_sub_tlv(const u8 *p, size_t len, void *encap, size_t *encap_size, switch (type) { case BGP_TUNNEL_ENCAP_A_SUB_TLV_ENCAP: - res = decode_encap(p, sub_tlv_len, encap, encap_size, flags); + res = decode_encap(p, sub_tlv_len, encap, pool); break; case BGP_TUNNEL_ENCAP_A_SUB_TLV_TUNNEL_EP: - res = decode_tunnel_ep(p, sub_tlv_len, tunnel_ep_as, tunnel_ep_addr, flags); + res = decode_tunnel_ep(p, sub_tlv_len, encap); break; case BGP_TUNNEL_ENCAP_A_SUB_TLV_COLOR: - res = decode_color(p, sub_tlv_len, color, flags); + res = decode_color(p, sub_tlv_len, encap); break; case BGP_TUNNEL_ENCAP_A_SUB_TLV_UDP_DEST_PORT: - res = decode_udp_dest_port(p, sub_tlv_len, udp_dest_port, flags); + res = decode_udp_dest_port(p, sub_tlv_len, encap); break; default: /* Skip unsupported sub-TLV. */ @@ -138,7 +134,7 @@ int decode_sub_tlv(const u8 *p, size_t len, void *encap, size_t *encap_size, return p - first + sub_tlv_len; } -int decode_tunnel_encap(const eattr *e, u16 wg_tunnel_type, void *encap, size_t *encap_size, u32 *as4, ip_addr *tunnel_ep, u32 *color, u16 *udp_port, u16 *flags) +int decode_tunnel_encap(const eattr *e, struct tunnel_encap *encap, struct pool *pool) { const u8 *p = e->u.ptr->data; int len = e->u.ptr->length; @@ -148,14 +144,9 @@ int decode_tunnel_encap(const eattr *e, u16 wg_tunnel_type, void *encap, size_t return -1; } - u16 tunnel_type = get_u16(p); + encap->type = get_u16(p); - log(L_DEBUG "WG: tunnel type %d", tunnel_type); - - if (tunnel_type != wg_tunnel_type) { - log(L_TRACE "WG: tunnel type error %d", tunnel_type); - return -1; - } + log(L_DEBUG "WG: tunnel type %d", encap->type); u16 value_length = get_u16(p + 2); @@ -167,7 +158,7 @@ int decode_tunnel_encap(const eattr *e, u16 wg_tunnel_type, void *encap, size_t } for (const u8 *cur = p + 4; cur < p + 4 + value_length;) { - int res = decode_sub_tlv(cur, value_length, encap, encap_size, as4, tunnel_ep, color, udp_port, flags); + int res = decode_sub_tlv(cur, value_length, encap, pool); if (res < 0) { log(L_TRACE "WG: decode error %d", res); diff --git a/lib/tunnel_encaps.h b/lib/tunnel_encaps.h index 9d25e5c5..341dcf22 100644 --- a/lib/tunnel_encaps.h +++ b/lib/tunnel_encaps.h @@ -16,6 +16,22 @@ #define FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_TUNNEL_EP (1<<BGP_TUNNEL_ENCAP_A_SUB_TLV_TUNNEL_EP) #define FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_UDP_DEST_PORT (1<<BGP_TUNNEL_ENCAP_A_SUB_TLV_UDP_DEST_PORT) -int decode_tunnel_encap(const eattr *e, u16 wg_tunnel_type, void *encap, size_t *encap_size, u32 *as4, ip_addr *tunnel_ep, u32 *color, u16 *udp_port, u16 *flags); +/* Tunnel Encapsulation */ +struct tunnel_endpoint { + u32 asn; + ip_addr ip; +}; + +struct tunnel_encap { + int type; + void *encap; + size_t encap_len; + struct tunnel_endpoint ep; + u32 color; + u16 udp_dest_port; + u16 flags; +}; + +int decode_tunnel_encap(const eattr *e, struct tunnel_encap *encap, struct pool *pool); #endif /* _BIRD_TUNNEL_ENCAPS_ */ diff --git a/proto/wireguard/wireguard.c b/proto/wireguard/wireguard.c index a355bf43..815db91a 100644 --- a/proto/wireguard/wireguard.c +++ b/proto/wireguard/wireguard.c @@ -156,7 +156,7 @@ dump(void *ptr, size_t len) } static wg_peer * -add_peer(wg_device *dev, wg_key pubkey) +add_peer(wg_device *dev, const wg_key pubkey) { struct wg_peer *peer = malloc(sizeof(struct wg_peer)); memset(peer, 0, sizeof(struct wg_peer)); @@ -254,21 +254,18 @@ wg_rt_notify(struct proto *P, struct channel *CH, struct network *n, debug("WG: notify new %d %N\n", new->attrs->dest, n->n.addr); - wg_key pubkey; - size_t pubkey_size = sizeof(wg_key); - memset(pubkey, 0, pubkey_size); - u32 tunnel_ep_as4 = 0; - ip_addr tunnel_ep_addr = IPA_NONE; - u16 udp_dest_port = 0; - u32 color = 0; - u16 flags = 0; + struct tunnel_encap encap; + memset(&encap, 0, sizeof(encap)); + encap.ep.ip = IPA_NONE; t = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_TUNNEL_ENCAP)); if (!t && he && he->src) { t = ea_find(he->src->eattrs, EA_CODE(PROTOCOL_BGP, BA_TUNNEL_ENCAP)); } - if (t && t->u.ptr && decode_tunnel_encap(t, c->tunnel_type, &pubkey, &pubkey_size, &tunnel_ep_as4, &tunnel_ep_addr, &color, &udp_dest_port, &flags) == 0 && pubkey_size == sizeof(wg_key)) { - log(L_TRACE "WG: Attr %x %x %d %04x", t->flags, t->type, t->u.ptr->length, flags); + if (t && t->u.ptr && decode_tunnel_encap(t, &encap, P->pool) == 0 && encap.type == c->tunnel_type && encap.encap_len == sizeof(wg_key)) { + const wg_key *pubkey = encap.encap; + + log(L_TRACE "WG: Attr %x %x %d %04x", t->flags, t->type, t->u.ptr->length, encap.flags); struct wg_device *dev = p->dev; @@ -288,7 +285,7 @@ wg_rt_notify(struct proto *P, struct channel *CH, struct network *n, log(L_TRACE "WG: Found"); found = true; - set_peer_tunnel_ep(peer, tunnel_ep_addr, udp_dest_port); + set_peer_tunnel_ep(peer, encap.ep.ip, encap.udp_dest_port); add_allowed_ips(ch->c.net_type, n, peer); dirty = true; @@ -297,7 +294,7 @@ wg_rt_notify(struct proto *P, struct channel *CH, struct network *n, if (!found) { wg_peer *peer = add_peer(dev, pubkey); - set_peer_tunnel_ep(peer, tunnel_ep_addr, udp_dest_port); + set_peer_tunnel_ep(peer, encap.ep.ip, encap.udp_dest_port); add_allowed_ips(ch->c.net_type, n, peer); dirty = true; } @@ -351,6 +348,9 @@ wg_rt_notify(struct proto *P, struct channel *CH, struct network *n, log(L_TRACE "WG: No Attr"); } + mb_free(encap.encap); + encap.encap = NULL; + // old_metric = en->valid ? en->metric : -1; // en->valid = RIP_ENTRY_VALID; |