diff options
author | Mikael Magnusson <mikma@users.sourceforge.net> | 2019-09-27 22:14:05 +0200 |
---|---|---|
committer | Mikael Magnusson <mikma@users.sourceforge.net> | 2021-01-12 23:34:17 +0100 |
commit | f773a3c93922cb4a122b97082f34053aeaae9f26 (patch) | |
tree | aa617e83eb4128e0b33528aed43d9f469e9662e0 /lib | |
parent | beb99f38ec4a889441f5675c1f5c8b8c815c8641 (diff) |
Wireguard: Refactor tunnel encaps decoding
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/tunnel_encaps.c | 180 | ||||
-rw-r--r-- | lib/tunnel_encaps.h | 19 |
3 files changed, 200 insertions, 1 deletions
diff --git a/lib/Makefile b/lib/Makefile index 5c78b2a9..300ccc85 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,4 +1,4 @@ -src := bitmap.c bitops.c checksum.c event.c flowspec.c idm.c ip.c lists.c mac.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c +src := bitmap.c bitops.c checksum.c event.c flowspec.c idm.c ip.c lists.c mac.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c tunnel_encaps.c obj := $(src-o-files) $(all-daemon) diff --git a/lib/tunnel_encaps.c b/lib/tunnel_encaps.c new file mode 100644 index 00000000..43fcdbcb --- /dev/null +++ b/lib/tunnel_encaps.c @@ -0,0 +1,180 @@ +#include "lib/tunnel_encaps.h" + +static +int decode_wireguard(const void *p, size_t sub_tlv_len, wg_key *pubkey, u16 *flags) +{ + if (sub_tlv_len != sizeof(wg_key)) { + log(L_TRACE "WG: wireguard len error %d", sub_tlv_len); + return -1; + } + + memcpy(pubkey, p, sizeof(wg_key)); + *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) +{ + if (sub_tlv_len != 8) { + log(L_TRACE "WG: color len error %d", sub_tlv_len); + return -1; + } + + if (get_u16(p) != 0x030b) { + log(L_TRACE "WG: color error %04x", get_u16(p)); + return -1; + } + + *color = get_u32(p+2); + *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) +{ + 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; + return 0; +} + +static +int decode_tunnel_ep(const void *p, size_t sub_tlv_len, u32 *as4, ip_addr *tunnel_ep, u16 *flags) +{ + if (sub_tlv_len < 6) { + log(L_TRACE "WG: tunnel ep len error"); + return -1; + } + + *as4 = get_u32(p); + u16 af = get_u16(p + 4); + switch (af) { + case NET_IP4: + if (sub_tlv_len != 10) { + 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; + 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; + return 0; + default: + log(L_TRACE "WG: Address family error %d", af); + return -1; + } +} + +static +int decode_sub_tlv(const u8 *p, size_t len, wg_key *pubkey, + u32 *tunnel_ep_as, ip_addr *tunnel_ep_addr, + u32 *color, u16 *udp_dest_port, u16 *flags) +{ + if (len < 3) { + log(L_TRACE "WG: sub_tlv len error %d", len); + return -1; + } + + const u8 *first = p; + const u8 *last = p + len; + int type = get_u8(p++); + u16 sub_tlv_len = 0; + + log(L_TRACE "WG: sub tlv type %d", type); + if (type >= 0 && type <= 127) { + sub_tlv_len = get_u8(p); + p++; + } else if (type >= 128 && type <= 255) { + sub_tlv_len = get_u16(p); + p += 2; + } else { + log(L_TRACE "WG: sub_tlv type error %d", type); + return -1; + } + + log(L_TRACE "WG: sub tlv len %d", sub_tlv_len); + if (p + sub_tlv_len > last) { + log(L_TRACE "WG: sub_tlv value len error %d", sub_tlv_len); + return -1; + } + + int res = 0; + + switch (type) { + case BGP_TUNNEL_ENCAP_A_SUB_TLV_ENCAP: + res = decode_wireguard(p, sub_tlv_len, pubkey, flags); + 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); + break; + case BGP_TUNNEL_ENCAP_A_SUB_TLV_COLOR: + res = decode_color(p, sub_tlv_len, color, flags); + break; + case BGP_TUNNEL_ENCAP_A_SUB_TLV_UDP_DEST_PORT: + res = decode_udp_dest_port(p, sub_tlv_len, udp_dest_port, flags); + break; + default: + /* Skip unsupported sub-TLV. */ + res = 0; + break; + } + + if (res < 0) + return res; + + return p - first + sub_tlv_len; +} + +int decode_tunnel_encap(const eattr *e, u16 wg_tunnel_type, wg_key *pubkey, u32 *as4, ip_addr *tunnel_ep, u32 *color, u16 *udp_port, u16 *flags) +{ + const u8 *p = e->u.ptr->data; + int len = e->u.ptr->length; + + if (len < 4) { + log(L_TRACE "WG: tunnel_encap len error %d", len); + return -1; + } + + u16 tunnel_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; + } + + u16 value_length = get_u16(p + 2); + + log(L_TRACE "WG: tunnel encap value len %d", value_length); + + if (len < value_length + 4) { + log(L_TRACE "WG: tunnel encap len error %d", value_length); + return -1; + } + + for (const u8 *cur = p + 4; cur < p + 4 + value_length;) { + int res = decode_sub_tlv(cur, value_length, pubkey, as4, tunnel_ep, color, udp_port, flags); + + if (res < 0) { + log(L_TRACE "WG: decode error %d", res); + return res; + } + + cur += res; + } + + return 0; +} diff --git a/lib/tunnel_encaps.h b/lib/tunnel_encaps.h new file mode 100644 index 00000000..6c85a883 --- /dev/null +++ b/lib/tunnel_encaps.h @@ -0,0 +1,19 @@ +#ifndef _BIRD_TUNNEL_ENCAPS_ +#define _BIRD_TUNNEL_ENCAPS_ + +#include "nest/route.h" +#include "sysdep/linux/wireguard.h" + +#define BGP_TUNNEL_ENCAP_A_SUB_TLV_ENCAP 1 +#define BGP_TUNNEL_ENCAP_A_SUB_TLV_COLOR 4 +#define BGP_TUNNEL_ENCAP_A_SUB_TLV_TUNNEL_EP 6 +#define BGP_TUNNEL_ENCAP_A_SUB_TLV_UDP_DEST_PORT 8 + +#define FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_ENCAP (1<<BGP_TUNNEL_ENCAP_A_SUB_TLV_ENCAP) +#define FLAG_BGP_TUNNEL_ENCAP_A_SUB_TLV_COLOR (1<<BGP_TUNNEL_ENCAP_A_SUB_TLV_COLOR) +#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, wg_key *pubkey, u32 *as4, ip_addr *tunnel_ep, u32 *color, u16 *udp_port, u16 *flags); + +#endif /* _BIRD_TUNNEL_ENCAPS_ */ |