wireguard: add ipv6 support

Type: improvement
Signed-off-by: Artem Glazychev <artem.glazychev@xored.com>
Change-Id: If1a7e82ce163c4c4acaa5acf45ad2b88371396f6
This commit is contained in:
Artem Glazychev
2021-06-03 20:11:54 +07:00
committed by Ed Warnicke
parent 0c4931cb35
commit 7dd3b5b5e3
15 changed files with 966 additions and 245 deletions

21
src/plugins/wireguard/wireguard.c Executable file → Normal file
View File

@ -15,7 +15,6 @@
#include <vnet/vnet.h>
#include <vnet/plugin/plugin.h>
#include <vnet/ipip/ipip.h>
#include <vpp/app/version.h>
#include <wireguard/wireguard_send.h>
@ -32,9 +31,12 @@ wg_init (vlib_main_t * vm)
wmp->vlib_main = vm;
wmp->in_fq_index = vlib_frame_queue_main_init (wg_input_node.index, 0);
wmp->out_fq_index =
vlib_frame_queue_main_init (wg_output_tun_node.index, 0);
wmp->in4_fq_index = vlib_frame_queue_main_init (wg4_input_node.index, 0);
wmp->in6_fq_index = vlib_frame_queue_main_init (wg6_input_node.index, 0);
wmp->out4_fq_index =
vlib_frame_queue_main_init (wg4_output_tun_node.index, 0);
wmp->out6_fq_index =
vlib_frame_queue_main_init (wg6_output_tun_node.index, 0);
vlib_thread_main_t *tm = vlib_get_thread_main ();
@ -50,13 +52,18 @@ VLIB_INIT_FUNCTION (wg_init);
/* *INDENT-OFF* */
VNET_FEATURE_INIT (wg_output_tun, static) =
{
VNET_FEATURE_INIT (wg4_output_tun, static) = {
.arc_name = "ip4-output",
.node_name = "wg-output-tun",
.node_name = "wg4-output-tun",
.runs_after = VNET_FEATURES ("gso-ip4"),
};
VNET_FEATURE_INIT (wg6_output_tun, static) = {
.arc_name = "ip6-output",
.node_name = "wg6-output-tun",
.runs_after = VNET_FEATURES ("gso-ip6"),
};
VLIB_PLUGIN_REGISTER () =
{
.version = VPP_BUILD_VER,

View File

@ -21,8 +21,10 @@
#define WG_DEFAULT_DATA_SIZE 2048
extern vlib_node_registration_t wg_input_node;
extern vlib_node_registration_t wg_output_tun_node;
extern vlib_node_registration_t wg4_input_node;
extern vlib_node_registration_t wg6_input_node;
extern vlib_node_registration_t wg4_output_tun_node;
extern vlib_node_registration_t wg6_output_tun_node;
typedef struct wg_per_thread_data_t_
{
@ -37,8 +39,10 @@ typedef struct
wg_index_table_t index_table;
u32 in_fq_index;
u32 out_fq_index;
u32 in4_fq_index;
u32 in6_fq_index;
u32 out4_fq_index;
u32 out6_fq_index;
wg_per_thread_data_t *per_thread_data;
u8 feature_init;

View File

@ -47,19 +47,13 @@ static void
ip_address_decode2 (&mp->interface.src_ip, &src);
if (AF_IP6 == ip_addr_version (&src))
rv = VNET_API_ERROR_INVALID_PROTOCOL;
if (mp->generate_key)
curve25519_gen_secret (private_key);
else
{
if (mp->generate_key)
curve25519_gen_secret (private_key);
else
clib_memcpy (private_key, mp->interface.private_key,
NOISE_PUBLIC_KEY_LEN);
clib_memcpy (private_key, mp->interface.private_key, NOISE_PUBLIC_KEY_LEN);
rv = wg_if_create (ntohl (mp->interface.user_instance), private_key,
ntohs (mp->interface.port), &src, &sw_if_index);
}
rv = wg_if_create (ntohl (mp->interface.user_instance), private_key,
ntohs (mp->interface.port), &src, &sw_if_index);
/* *INDENT-OFF* */
REPLY_MACRO2(VL_API_WIREGUARD_INTERFACE_CREATE_REPLY,
@ -177,19 +171,10 @@ vl_api_wireguard_peer_add_t_handler (vl_api_wireguard_peer_add_t * mp)
for (ii = 0; ii < mp->peer.n_allowed_ips; ii++)
ip_prefix_decode (&mp->peer.allowed_ips[ii], &allowed_ips[ii]);
if (AF_IP6 == ip_addr_version (&endpoint) ||
FIB_PROTOCOL_IP6 == allowed_ips[0].fp_proto)
/* ip6 currently not supported, but the API needs to support it
* else we'll need to change it later, and that's a PITA */
rv = VNET_API_ERROR_INVALID_PROTOCOL;
else
rv = wg_peer_add (ntohl (mp->peer.sw_if_index),
mp->peer.public_key,
ntohl (mp->peer.table_id),
&ip_addr_46 (&endpoint),
allowed_ips,
ntohs (mp->peer.port),
ntohs (mp->peer.persistent_keepalive), &peeri);
rv = wg_peer_add (ntohl (mp->peer.sw_if_index), mp->peer.public_key,
ntohl (mp->peer.table_id), &ip_addr_46 (&endpoint),
allowed_ips, ntohs (mp->peer.port),
ntohs (mp->peer.persistent_keepalive), &peeri);
vec_free (allowed_ips);
done:

12
src/plugins/wireguard/wireguard_cli.c Executable file → Normal file
View File

@ -213,16 +213,8 @@ wg_peer_add_command_fn (vlib_main_t * vm,
}
}
if (AF_IP6 == ip_addr_version (&ip) ||
FIB_PROTOCOL_IP6 == allowed_ip.fp_proto)
rv = VNET_API_ERROR_INVALID_PROTOCOL;
else
rv = wg_peer_add (tun_sw_if_index,
public_key,
table_id,
&ip_addr_46 (&ip),
allowed_ips,
portDst, persistent_keepalive, &peer_index);
rv = wg_peer_add (tun_sw_if_index, public_key, table_id, &ip_addr_46 (&ip),
allowed_ips, portDst, persistent_keepalive, &peer_index);
switch (rv)
{

25
src/plugins/wireguard/wireguard_cookie.c Executable file → Normal file
View File

@ -29,9 +29,9 @@ static void cookie_macs_mac1 (message_macs_t *, const void *, size_t,
const uint8_t[COOKIE_KEY_SIZE]);
static void cookie_macs_mac2 (message_macs_t *, const void *, size_t,
const uint8_t[COOKIE_COOKIE_SIZE]);
static void cookie_checker_make_cookie (vlib_main_t * vm, cookie_checker_t *,
static void cookie_checker_make_cookie (vlib_main_t *vm, cookie_checker_t *,
uint8_t[COOKIE_COOKIE_SIZE],
ip4_address_t ip4, u16 udp_port);
ip46_address_t *ip, u16 udp_port);
/* Public Functions */
void
@ -76,9 +76,9 @@ cookie_maker_mac (cookie_maker_t * cp, message_macs_t * cm, void *buf,
}
enum cookie_mac_state
cookie_checker_validate_macs (vlib_main_t * vm, cookie_checker_t * cc,
message_macs_t * cm, void *buf, size_t len,
bool busy, ip4_address_t ip4, u16 udp_port)
cookie_checker_validate_macs (vlib_main_t *vm, cookie_checker_t *cc,
message_macs_t *cm, void *buf, size_t len,
bool busy, ip46_address_t *ip, u16 udp_port)
{
message_macs_t our_cm;
uint8_t cookie[COOKIE_COOKIE_SIZE];
@ -93,7 +93,7 @@ cookie_checker_validate_macs (vlib_main_t * vm, cookie_checker_t * cc,
if (!busy)
return VALID_MAC_BUT_NO_COOKIE;
cookie_checker_make_cookie (vm, cc, cookie, ip4, udp_port);
cookie_checker_make_cookie (vm, cc, cookie, ip, udp_port);
cookie_macs_mac2 (&our_cm, buf, len, cookie);
/* If the mac2 is invalid, we want to send a cookie response */
@ -139,9 +139,9 @@ cookie_macs_mac2 (message_macs_t * cm, const void *buf, size_t len,
}
static void
cookie_checker_make_cookie (vlib_main_t * vm, cookie_checker_t * cc,
cookie_checker_make_cookie (vlib_main_t *vm, cookie_checker_t *cc,
uint8_t cookie[COOKIE_COOKIE_SIZE],
ip4_address_t ip4, u16 udp_port)
ip46_address_t *ip, u16 udp_port)
{
blake2s_state_t state;
@ -155,7 +155,14 @@ cookie_checker_make_cookie (vlib_main_t * vm, cookie_checker_t * cc,
blake2s_init_key (&state, COOKIE_COOKIE_SIZE, cc->cc_secret,
COOKIE_SECRET_SIZE);
blake2s_update (&state, ip4.as_u8, sizeof (ip4_address_t)); //TODO: IP6
if (ip46_address_is_ip4 (ip))
{
blake2s_update (&state, ip->ip4.as_u8, sizeof (ip4_address_t));
}
else
{
blake2s_update (&state, ip->ip6.as_u8, sizeof (ip6_address_t));
}
blake2s_update (&state, (u8 *) & udp_port, sizeof (u16));
blake2s_final (&state, cookie, COOKIE_COOKIE_SIZE);
}

12
src/plugins/wireguard/wireguard_cookie.h Executable file → Normal file
View File

@ -18,7 +18,7 @@
#ifndef __included_wg_cookie_h__
#define __included_wg_cookie_h__
#include <vnet/ip/ip4_packet.h>
#include <vnet/ip/ip46_address.h>
#include <wireguard/wireguard_noise.h>
enum cookie_mac_state
@ -83,12 +83,10 @@ typedef struct cookie_checker
void cookie_maker_init (cookie_maker_t *, const uint8_t[COOKIE_INPUT_SIZE]);
void cookie_checker_update (cookie_checker_t *, uint8_t[COOKIE_INPUT_SIZE]);
void cookie_maker_mac (cookie_maker_t *, message_macs_t *, void *, size_t);
enum cookie_mac_state cookie_checker_validate_macs (vlib_main_t * vm,
cookie_checker_t *,
message_macs_t *, void *,
size_t, bool,
ip4_address_t ip4,
u16 udp_port);
enum cookie_mac_state
cookie_checker_validate_macs (vlib_main_t *vm, cookie_checker_t *,
message_macs_t *, void *, size_t, bool,
ip46_address_t *ip, u16 udp_port);
#endif /* __included_wg_cookie_h__ */

View File

@ -129,40 +129,64 @@ wg_handoff (vlib_main_t * vm,
return n_enq;
}
VLIB_NODE_FN (wg_handshake_handoff) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * from_frame)
VLIB_NODE_FN (wg4_handshake_handoff)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
{
wg_main_t *wmp = &wg_main;
return wg_handoff (vm, node, from_frame, wmp->in_fq_index,
return wg_handoff (vm, node, from_frame, wmp->in4_fq_index,
WG_HANDOFF_HANDSHAKE);
}
VLIB_NODE_FN (wg_input_data_handoff) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * from_frame)
VLIB_NODE_FN (wg6_handshake_handoff)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
{
wg_main_t *wmp = &wg_main;
return wg_handoff (vm, node, from_frame, wmp->in_fq_index,
return wg_handoff (vm, node, from_frame, wmp->in6_fq_index,
WG_HANDOFF_HANDSHAKE);
}
VLIB_NODE_FN (wg4_input_data_handoff)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
{
wg_main_t *wmp = &wg_main;
return wg_handoff (vm, node, from_frame, wmp->in4_fq_index,
WG_HANDOFF_INP_DATA);
}
VLIB_NODE_FN (wg_output_tun_handoff) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * from_frame)
VLIB_NODE_FN (wg6_input_data_handoff)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
{
wg_main_t *wmp = &wg_main;
return wg_handoff (vm, node, from_frame, wmp->out_fq_index,
return wg_handoff (vm, node, from_frame, wmp->in6_fq_index,
WG_HANDOFF_INP_DATA);
}
VLIB_NODE_FN (wg4_output_tun_handoff)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
{
wg_main_t *wmp = &wg_main;
return wg_handoff (vm, node, from_frame, wmp->out4_fq_index,
WG_HANDOFF_OUT_TUN);
}
VLIB_NODE_FN (wg6_output_tun_handoff)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
{
wg_main_t *wmp = &wg_main;
return wg_handoff (vm, node, from_frame, wmp->out6_fq_index,
WG_HANDOFF_OUT_TUN);
}
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (wg_handshake_handoff) =
VLIB_REGISTER_NODE (wg4_handshake_handoff) =
{
.name = "wg-handshake-handoff",
.name = "wg4-handshake-handoff",
.vector_size = sizeof (u32),
.format_trace = format_wg_handoff_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
@ -174,9 +198,9 @@ VLIB_REGISTER_NODE (wg_handshake_handoff) =
},
};
VLIB_REGISTER_NODE (wg_input_data_handoff) =
VLIB_REGISTER_NODE (wg6_handshake_handoff) =
{
.name = "wg-input-data-handoff",
.name = "wg6-handshake-handoff",
.vector_size = sizeof (u32),
.format_trace = format_wg_handoff_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
@ -188,9 +212,51 @@ VLIB_REGISTER_NODE (wg_input_data_handoff) =
},
};
VLIB_REGISTER_NODE (wg_output_tun_handoff) =
VLIB_REGISTER_NODE (wg4_input_data_handoff) =
{
.name = "wg-output-tun-handoff",
.name = "wg4-input-data-handoff",
.vector_size = sizeof (u32),
.format_trace = format_wg_handoff_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = ARRAY_LEN (wg_handoff_error_strings),
.error_strings = wg_handoff_error_strings,
.n_next_nodes = 1,
.next_nodes = {
[0] = "error-drop",
},
};
VLIB_REGISTER_NODE (wg6_input_data_handoff) =
{
.name = "wg6-input-data-handoff",
.vector_size = sizeof (u32),
.format_trace = format_wg_handoff_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = ARRAY_LEN (wg_handoff_error_strings),
.error_strings = wg_handoff_error_strings,
.n_next_nodes = 1,
.next_nodes = {
[0] = "error-drop",
},
};
VLIB_REGISTER_NODE (wg4_output_tun_handoff) =
{
.name = "wg4-output-tun-handoff",
.vector_size = sizeof (u32),
.format_trace = format_wg_handoff_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = ARRAY_LEN (wg_handoff_error_strings),
.error_strings = wg_handoff_error_strings,
.n_next_nodes = 1,
.next_nodes = {
[0] = "error-drop",
},
};
VLIB_REGISTER_NODE (wg6_output_tun_handoff) =
{
.name = "wg6-output-tun-handoff",
.vector_size = sizeof (u32),
.format_trace = format_wg_handoff_trace,
.type = VLIB_NODE_TYPE_INTERNAL,

View File

@ -49,7 +49,6 @@ format_wg_if (u8 * s, va_list * args)
noise_local_t *local = noise_local_get (wgi->local_idx);
u8 key[NOISE_KEY_LEN_BASE64];
s = format (s, "[%d] %U src:%U port:%d",
wgii,
format_vnet_sw_if_index_name, vnet_get_main (),
@ -290,7 +289,12 @@ wg_if_create (u32 user_instance,
vec_validate_init_empty (wg_if_indexes_by_port, port, NULL);
if (vec_len (wg_if_indexes_by_port[port]) == 0)
udp_register_dst_port (vlib_get_main (), port, wg_input_node.index, 1);
{
udp_register_dst_port (vlib_get_main (), port, wg4_input_node.index,
UDP_IP4);
udp_register_dst_port (vlib_get_main (), port, wg6_input_node.index,
UDP_IP6);
}
vec_add1 (wg_if_indexes_by_port[port], t_idx);
@ -350,7 +354,10 @@ wg_if_delete (u32 sw_if_index)
}
}
if (vec_len (ifs) == 0)
udp_unregister_dst_port (vlib_get_main (), wg_if->port, 1);
{
udp_unregister_dst_port (vlib_get_main (), wg_if->port, 1);
udp_unregister_dst_port (vlib_get_main (), wg_if->port, 0);
}
vnet_delete_hw_interface (vnm, hw->hw_if_index);
pool_put_index (noise_local_pool, wg_if->local_idx);
@ -365,8 +372,12 @@ wg_if_peer_add (wg_if_t * wgi, index_t peeri)
hash_set (wgi->peers, peeri, peeri);
if (1 == hash_elts (wgi->peers))
vnet_feature_enable_disable ("ip4-output", "wg-output-tun",
wgi->sw_if_index, 1, 0, 0);
{
vnet_feature_enable_disable ("ip4-output", "wg4-output-tun",
wgi->sw_if_index, 1, 0, 0);
vnet_feature_enable_disable ("ip6-output", "wg6-output-tun",
wgi->sw_if_index, 1, 0, 0);
}
}
void
@ -375,8 +386,12 @@ wg_if_peer_remove (wg_if_t * wgi, index_t peeri)
hash_unset (wgi->peers, peeri);
if (0 == hash_elts (wgi->peers))
vnet_feature_enable_disable ("ip4-output", "wg-output-tun",
wgi->sw_if_index, 0, 0, 0);
{
vnet_feature_enable_disable ("ip4-output", "wg4-output-tun",
wgi->sw_if_index, 0, 0, 0);
vnet_feature_enable_disable ("ip6-output", "wg6-output-tun",
wgi->sw_if_index, 0, 0, 0);
}
}
void

View File

@ -31,8 +31,6 @@ typedef struct wg_if_t_
cookie_checker_t cookie_checker;
u16 port;
wg_index_table_t index_table;
/* Source IP address for originated packets */
ip_address_t src_ip;

View File

@ -79,11 +79,11 @@ format_wg_input_trace (u8 * s, va_list * args)
wg_input_trace_t *t = va_arg (*args, wg_input_trace_t *);
s = format (s, "WG input: \n");
s = format (s, " Type: %U\n", format_wg_message_type, t->type);
s = format (s, " peer: %d\n", t->peer);
s = format (s, " Length: %d\n", t->current_length);
s = format (s, " Keepalive: %s", t->is_keepalive ? "true" : "false");
s = format (s, "Wireguard input: \n");
s = format (s, " Type: %U\n", format_wg_message_type, t->type);
s = format (s, " Peer: %d\n", t->peer);
s = format (s, " Length: %d\n", t->current_length);
s = format (s, " Keepalive: %s", t->is_keepalive ? "true" : "false");
return s;
}
@ -93,6 +93,7 @@ typedef enum
WG_INPUT_NEXT_HANDOFF_HANDSHAKE,
WG_INPUT_NEXT_HANDOFF_DATA,
WG_INPUT_NEXT_IP4_INPUT,
WG_INPUT_NEXT_IP6_INPUT,
WG_INPUT_NEXT_PUNT,
WG_INPUT_NEXT_ERROR,
WG_INPUT_N_NEXT,
@ -108,8 +109,15 @@ typedef enum
/* } */
/* } */
static u8
is_ip4_header (u8 *data)
{
return (data[0] >> 4) == 0x4;
}
static wg_input_error_t
wg_handshake_process (vlib_main_t * vm, wg_main_t * wmp, vlib_buffer_t * b)
wg_handshake_process (vlib_main_t *vm, wg_main_t *wmp, vlib_buffer_t *b,
u32 node_idx, u8 is_ip4)
{
ASSERT (vm->thread_index == 0);
@ -122,10 +130,21 @@ wg_handshake_process (vlib_main_t * vm, wg_main_t * wmp, vlib_buffer_t * b)
void *current_b_data = vlib_buffer_get_current (b);
ip46_address_t src_ip;
if (is_ip4)
{
ip4_header_t *iph4 =
current_b_data - sizeof (udp_header_t) - sizeof (ip4_header_t);
ip46_address_set_ip4 (&src_ip, &iph4->src_address);
}
else
{
ip6_header_t *iph6 =
current_b_data - sizeof (udp_header_t) - sizeof (ip6_header_t);
ip46_address_set_ip6 (&src_ip, &iph6->src_address);
}
udp_header_t *uhd = current_b_data - sizeof (udp_header_t);
ip4_header_t *iph =
current_b_data - sizeof (udp_header_t) - sizeof (ip4_header_t);
ip4_address_t ip4_src = iph->src_address;
u16 udp_src_port = clib_host_to_net_u16 (uhd->src_port);;
u16 udp_dst_port = clib_host_to_net_u16 (uhd->dst_port);;
@ -168,7 +187,7 @@ wg_handshake_process (vlib_main_t * vm, wg_main_t * wmp, vlib_buffer_t * b)
mac_state = cookie_checker_validate_macs (
vm, &wg_if->cookie_checker, macs, current_b_data, len, under_load,
ip4_src, udp_src_port);
&src_ip, udp_src_port);
if (mac_state == INVALID_MAC)
{
wg_if = NULL;
@ -214,7 +233,7 @@ wg_handshake_process (vlib_main_t * vm, wg_main_t * wmp, vlib_buffer_t * b)
// set_peer_address (peer, ip4_src, udp_src_port);
if (PREDICT_FALSE (!wg_send_handshake_response (vm, peer)))
{
vlib_node_increment_counter (vm, wg_input_node.index,
vlib_node_increment_counter (vm, node_idx,
WG_INPUT_ERROR_HANDSHAKE_SEND, 1);
}
break;
@ -254,9 +273,8 @@ wg_handshake_process (vlib_main_t * vm, wg_main_t * wmp, vlib_buffer_t * b)
wg_timers_handshake_complete (peer);
if (PREDICT_FALSE (!wg_send_keepalive (vm, peer)))
{
vlib_node_increment_counter (vm, wg_input_node.index,
WG_INPUT_ERROR_KEEPALIVE_SEND,
1);
vlib_node_increment_counter (vm, node_idx,
WG_INPUT_ERROR_KEEPALIVE_SEND, 1);
}
}
break;
@ -270,9 +288,9 @@ wg_handshake_process (vlib_main_t * vm, wg_main_t * wmp, vlib_buffer_t * b)
return WG_INPUT_ERROR_NONE;
}
VLIB_NODE_FN (wg_input_node) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame)
always_inline uword
wg_input_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_frame_t *frame, u8 is_ip4)
{
message_type_t header_type;
u32 n_left_from;
@ -382,7 +400,20 @@ VLIB_NODE_FN (wg_input_node) (vlib_main_t * vm,
wg_timers_data_received (peer);
ip4_header_t *iph = vlib_buffer_get_current (b[0]);
ip46_address_t src_ip;
u8 is_ip4_inner = is_ip4_header (vlib_buffer_get_current (b[0]));
if (is_ip4_inner)
{
ip46_address_set_ip4 (
&src_ip, &((ip4_header_t *) vlib_buffer_get_current (b[0]))
->src_address);
}
else
{
ip46_address_set_ip6 (
&src_ip, &((ip6_header_t *) vlib_buffer_get_current (b[0]))
->src_address);
}
const fib_prefix_t *allowed_ip;
bool allowed = false;
@ -392,9 +423,10 @@ VLIB_NODE_FN (wg_input_node) (vlib_main_t * vm,
* is that there aren't many allowed IPs and thus a linear
* walk is fater than an ACL
*/
vec_foreach (allowed_ip, peer->allowed_ips)
{
if (fib_prefix_is_cover_addr_4 (allowed_ip, &iph->src_address))
if (fib_prefix_is_cover_addr_46 (allowed_ip, &src_ip))
{
allowed = true;
break;
@ -403,7 +435,8 @@ VLIB_NODE_FN (wg_input_node) (vlib_main_t * vm,
if (allowed)
{
vnet_buffer (b[0])->sw_if_index[VLIB_RX] = peer->wg_sw_if_index;
next[0] = WG_INPUT_NEXT_IP4_INPUT;
next[0] = is_ip4_inner ? WG_INPUT_NEXT_IP4_INPUT :
WG_INPUT_NEXT_IP6_INPUT;
}
}
else
@ -417,7 +450,8 @@ VLIB_NODE_FN (wg_input_node) (vlib_main_t * vm,
goto next;
}
wg_input_error_t ret = wg_handshake_process (vm, wmp, b[0]);
wg_input_error_t ret =
wg_handshake_process (vm, wmp, b[0], node->node_index, is_ip4);
if (ret != WG_INPUT_ERROR_NONE)
{
next[0] = WG_INPUT_NEXT_ERROR;
@ -445,10 +479,22 @@ VLIB_NODE_FN (wg_input_node) (vlib_main_t * vm,
return frame->n_vectors;
}
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (wg_input_node) =
VLIB_NODE_FN (wg4_input_node)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
{
.name = "wg-input",
return wg_input_inline (vm, node, frame, /* is_ip4 */ 1);
}
VLIB_NODE_FN (wg6_input_node)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
{
return wg_input_inline (vm, node, frame, /* is_ip4 */ 0);
}
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (wg4_input_node) =
{
.name = "wg4-input",
.vector_size = sizeof (u32),
.format_trace = format_wg_input_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
@ -457,9 +503,30 @@ VLIB_REGISTER_NODE (wg_input_node) =
.n_next_nodes = WG_INPUT_N_NEXT,
/* edit / add dispositions here */
.next_nodes = {
[WG_INPUT_NEXT_HANDOFF_HANDSHAKE] = "wg-handshake-handoff",
[WG_INPUT_NEXT_HANDOFF_DATA] = "wg-input-data-handoff",
[WG_INPUT_NEXT_HANDOFF_HANDSHAKE] = "wg4-handshake-handoff",
[WG_INPUT_NEXT_HANDOFF_DATA] = "wg4-input-data-handoff",
[WG_INPUT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
[WG_INPUT_NEXT_IP6_INPUT] = "ip6-input",
[WG_INPUT_NEXT_PUNT] = "error-punt",
[WG_INPUT_NEXT_ERROR] = "error-drop",
},
};
VLIB_REGISTER_NODE (wg6_input_node) =
{
.name = "wg6-input",
.vector_size = sizeof (u32),
.format_trace = format_wg_input_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = ARRAY_LEN (wg_input_error_strings),
.error_strings = wg_input_error_strings,
.n_next_nodes = WG_INPUT_N_NEXT,
/* edit / add dispositions here */
.next_nodes = {
[WG_INPUT_NEXT_HANDOFF_HANDSHAKE] = "wg6-handshake-handoff",
[WG_INPUT_NEXT_HANDOFF_DATA] = "wg6-input-data-handoff",
[WG_INPUT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
[WG_INPUT_NEXT_IP6_INPUT] = "ip6-input",
[WG_INPUT_NEXT_PUNT] = "error-punt",
[WG_INPUT_NEXT_ERROR] = "error-drop",
},

136
src/plugins/wireguard/wireguard_output_tun.c Executable file → Normal file
View File

@ -51,18 +51,28 @@ typedef enum
typedef struct
{
ip4_udp_header_t hdr;
index_t peer;
u8 header[sizeof (ip6_udp_header_t)];
u8 is_ip4;
} wg_output_tun_trace_t;
u8 *
format_ip4_udp_header (u8 * s, va_list * args)
{
ip4_udp_header_t *hdr = va_arg (*args, ip4_udp_header_t *);
ip4_udp_header_t *hdr4 = va_arg (*args, ip4_udp_header_t *);
s = format (s, "%U:$U",
format_ip4_header, &hdr->ip4, format_udp_header, &hdr->udp);
s = format (s, "%U:$U", format_ip4_header, &hdr4->ip4, format_udp_header,
&hdr4->udp);
return (s);
}
u8 *
format_ip6_udp_header (u8 *s, va_list *args)
{
ip6_udp_header_t *hdr6 = va_arg (*args, ip6_udp_header_t *);
s = format (s, "%U:$U", format_ip6_header, &hdr6->ip6, format_udp_header,
&hdr6->udp);
return (s);
}
@ -76,16 +86,22 @@ format_wg_output_tun_trace (u8 * s, va_list * args)
wg_output_tun_trace_t *t = va_arg (*args, wg_output_tun_trace_t *);
s = format (s, "peer: %d\n", t->peer);
s = format (s, " Encrypted packet: %U", format_ip4_udp_header, &t->hdr);
s = format (s, " Encrypted packet: ");
s = t->is_ip4 ? format (s, "%U", format_ip4_udp_header, t->header) :
format (s, "%U", format_ip6_udp_header, t->header);
return s;
}
VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame)
/* is_ip4 - inner header flag */
always_inline uword
wg_output_tun_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_frame_t *frame, u8 is_ip4)
{
u32 n_left_from;
u32 *from;
ip4_udp_header_t *hdr4_out = NULL;
ip6_udp_header_t *hdr6_out = NULL;
vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
u16 nexts[VLIB_FRAME_SIZE], *next;
u32 thread_index = vm->thread_index;
@ -102,12 +118,11 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
while (n_left_from > 0)
{
ip4_udp_header_t *hdr = vlib_buffer_get_current (b[0]);
u8 *plain_data = (vlib_buffer_get_current (b[0]) +
sizeof (ip4_udp_header_t));
u16 plain_data_len =
clib_net_to_host_u16 (((ip4_header_t *) plain_data)->length);
index_t peeri;
u8 iph_offset = 0;
u8 is_ip4_out = 1;
u8 *plain_data;
u16 plain_data_len;
next[0] = WG_OUTPUT_NEXT_ERROR;
peeri =
@ -119,7 +134,6 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
b[0]->error = node->errors[WG_OUTPUT_ERROR_PEER];
goto out;
}
if (PREDICT_FALSE (~0 == peer->output_thread_index))
{
/* this is the first packet to use this peer, claim the peer
@ -141,6 +155,21 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
b[0]->error = node->errors[WG_OUTPUT_ERROR_KEYPAIR];
goto out;
}
is_ip4_out = ip46_address_is_ip4 (&peer->src.addr);
if (is_ip4_out)
{
hdr4_out = vlib_buffer_get_current (b[0]);
}
else
{
hdr6_out = vlib_buffer_get_current (b[0]);
}
iph_offset = vnet_buffer (b[0])->ip.save_rewrite_length;
plain_data = vlib_buffer_get_current (b[0]) + iph_offset;
plain_data_len = vlib_buffer_length_in_chain (vm, b[0]) - iph_offset;
size_t encrypted_packet_len = message_data_len (plain_data_len);
/*
@ -159,13 +188,10 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
(message_data_t *) wmp->per_thread_data[thread_index].data;
enum noise_state_crypt state;
state =
noise_remote_encrypt (vm,
&peer->remote,
&encrypted_packet->receiver_index,
&encrypted_packet->counter, plain_data,
plain_data_len,
encrypted_packet->encrypted_data);
state = noise_remote_encrypt (
vm, &peer->remote, &encrypted_packet->receiver_index,
&encrypted_packet->counter, plain_data, plain_data_len,
encrypted_packet->encrypted_data);
if (PREDICT_FALSE (state == SC_KEEP_KEY_FRESH))
{
@ -184,12 +210,24 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
clib_memcpy (plain_data, (u8 *) encrypted_packet, encrypted_packet_len);
hdr->udp.length = clib_host_to_net_u16 (encrypted_packet_len +
sizeof (udp_header_t));
b[0]->current_length = (encrypted_packet_len +
sizeof (ip4_header_t) + sizeof (udp_header_t));
ip4_header_set_len_w_chksum
(&hdr->ip4, clib_host_to_net_u16 (b[0]->current_length));
if (is_ip4_out)
{
hdr4_out->udp.length = clib_host_to_net_u16 (encrypted_packet_len +
sizeof (udp_header_t));
b[0]->current_length =
(encrypted_packet_len + sizeof (ip4_udp_header_t));
ip4_header_set_len_w_chksum (
&hdr4_out->ip4, clib_host_to_net_u16 (b[0]->current_length));
}
else
{
hdr6_out->udp.length = clib_host_to_net_u16 (encrypted_packet_len +
sizeof (udp_header_t));
b[0]->current_length =
(encrypted_packet_len + sizeof (ip6_udp_header_t));
hdr6_out->ip6.payload_length =
clib_host_to_net_u16 (b[0]->current_length);
}
wg_timers_any_authenticated_packet_sent (peer);
wg_timers_data_sent (peer);
@ -201,9 +239,15 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
{
wg_output_tun_trace_t *t =
vlib_add_trace (vm, node, b[0], sizeof (*t));
t->hdr = *hdr;
t->peer = peeri;
t->is_ip4 = is_ip4_out;
if (hdr4_out)
clib_memcpy (t->header, hdr4_out, sizeof (*hdr4_out));
else if (hdr6_out)
clib_memcpy (t->header, hdr6_out, sizeof (*hdr6_out));
}
next:
n_left_from -= 1;
next += 1;
@ -214,10 +258,22 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
return frame->n_vectors;
}
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (wg_output_tun_node) =
VLIB_NODE_FN (wg4_output_tun_node)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
{
.name = "wg-output-tun",
return wg_output_tun_inline (vm, node, frame, /* is_ip4 */ 1);
}
VLIB_NODE_FN (wg6_output_tun_node)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
{
return wg_output_tun_inline (vm, node, frame, /* is_ip4 */ 0);
}
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (wg4_output_tun_node) =
{
.name = "wg4-output-tun",
.vector_size = sizeof (u32),
.format_trace = format_wg_output_tun_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
@ -225,7 +281,23 @@ VLIB_REGISTER_NODE (wg_output_tun_node) =
.error_strings = wg_output_error_strings,
.n_next_nodes = WG_OUTPUT_N_NEXT,
.next_nodes = {
[WG_OUTPUT_NEXT_HANDOFF] = "wg-output-tun-handoff",
[WG_OUTPUT_NEXT_HANDOFF] = "wg4-output-tun-handoff",
[WG_OUTPUT_NEXT_INTERFACE_OUTPUT] = "adj-midchain-tx",
[WG_OUTPUT_NEXT_ERROR] = "error-drop",
},
};
VLIB_REGISTER_NODE (wg6_output_tun_node) =
{
.name = "wg6-output-tun",
.vector_size = sizeof (u32),
.format_trace = format_wg_output_tun_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = ARRAY_LEN (wg_output_error_strings),
.error_strings = wg_output_error_strings,
.n_next_nodes = WG_OUTPUT_N_NEXT,
.next_nodes = {
[WG_OUTPUT_NEXT_HANDOFF] = "wg6-output-tun-handoff",
[WG_OUTPUT_NEXT_INTERFACE_OUTPUT] = "adj-midchain-tx",
[WG_OUTPUT_NEXT_ERROR] = "error-drop",
},

View File

@ -22,6 +22,7 @@
#include <wireguard/wireguard_key.h>
#include <wireguard/wireguard_send.h>
#include <wireguard/wireguard.h>
#include <vnet/tunnel/tunnel_dp.h>
wg_peer_t *wg_peer_pool;
@ -91,25 +92,44 @@ wg_peer_init (vlib_main_t * vm, wg_peer_t * peer)
}
static u8 *
wg_peer_build_rewrite (const wg_peer_t * peer)
wg_peer_build_rewrite (const wg_peer_t *peer, u8 is_ip4)
{
// v4 only for now
ip4_udp_header_t *hdr;
u8 *rewrite = NULL;
if (is_ip4)
{
ip4_udp_header_t *hdr;
vec_validate (rewrite, sizeof (*hdr) - 1);
hdr = (ip4_udp_header_t *) rewrite;
vec_validate (rewrite, sizeof (*hdr) - 1);
hdr = (ip4_udp_header_t *) rewrite;
hdr->ip4.ip_version_and_header_length = 0x45;
hdr->ip4.ttl = 64;
hdr->ip4.src_address = peer->src.addr.ip4;
hdr->ip4.dst_address = peer->dst.addr.ip4;
hdr->ip4.protocol = IP_PROTOCOL_UDP;
hdr->ip4.checksum = ip4_header_checksum (&hdr->ip4);
hdr->ip4.ip_version_and_header_length = 0x45;
hdr->ip4.ttl = 64;
hdr->ip4.src_address = peer->src.addr.ip4;
hdr->ip4.dst_address = peer->dst.addr.ip4;
hdr->ip4.protocol = IP_PROTOCOL_UDP;
hdr->ip4.checksum = ip4_header_checksum (&hdr->ip4);
hdr->udp.src_port = clib_host_to_net_u16 (peer->src.port);
hdr->udp.dst_port = clib_host_to_net_u16 (peer->dst.port);
hdr->udp.checksum = 0;
hdr->udp.src_port = clib_host_to_net_u16 (peer->src.port);
hdr->udp.dst_port = clib_host_to_net_u16 (peer->dst.port);
hdr->udp.checksum = 0;
}
else
{
ip6_udp_header_t *hdr;
vec_validate (rewrite, sizeof (*hdr) - 1);
hdr = (ip6_udp_header_t *) rewrite;
hdr->ip6.ip_version_traffic_class_and_flow_label = 0x60;
ip6_address_copy (&hdr->ip6.src_address, &peer->src.addr.ip6);
ip6_address_copy (&hdr->ip6.dst_address, &peer->dst.addr.ip6);
hdr->ip6.protocol = IP_PROTOCOL_UDP;
hdr->ip6.hop_limit = 64;
hdr->udp.src_port = clib_host_to_net_u16 (peer->src.port);
hdr->udp.dst_port = clib_host_to_net_u16 (peer->dst.port);
hdr->udp.checksum = 0;
}
return (rewrite);
}
@ -120,12 +140,15 @@ wg_peer_adj_stack (wg_peer_t *peer, adj_index_t ai)
ip_adjacency_t *adj;
u32 sw_if_index;
wg_if_t *wgi;
fib_protocol_t fib_proto;
if (!adj_is_valid (ai))
return;
adj = adj_get (ai);
sw_if_index = adj->rewrite_header.sw_if_index;
u8 is_ip4 = ip46_address_is_ip4 (&peer->src.addr);
fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
wgi = wg_if_get (wg_if_find_by_sw_if_index (sw_if_index));
@ -140,19 +163,76 @@ wg_peer_adj_stack (wg_peer_t *peer, adj_index_t ai)
{
/* *INDENT-OFF* */
fib_prefix_t dst = {
.fp_len = 32,
.fp_proto = FIB_PROTOCOL_IP4,
.fp_addr = peer->dst.addr,
.fp_len = is_ip4 ? 32 : 128,
.fp_proto = fib_proto,
.fp_addr = peer->dst.addr,
};
/* *INDENT-ON* */
u32 fib_index;
fib_index = fib_table_find (FIB_PROTOCOL_IP4, peer->table_id);
fib_index = fib_table_find (fib_proto, peer->table_id);
adj_midchain_delegate_stack (ai, fib_index, &dst);
}
}
static void
wg_peer_66_fixup (vlib_main_t *vm, const ip_adjacency_t *adj, vlib_buffer_t *b,
const void *data)
{
u8 iph_offset = 0;
ip6_header_t *ip6_out;
ip6_header_t *ip6_in;
/* Must set locally originated otherwise we're not allowed to
fragment the packet later */
b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
ip6_out = vlib_buffer_get_current (b);
iph_offset = vnet_buffer (b)->ip.save_rewrite_length;
ip6_in = vlib_buffer_get_current (b) + iph_offset;
ip6_out->ip_version_traffic_class_and_flow_label =
ip6_in->ip_version_traffic_class_and_flow_label;
}
static void
wg_peer_46_fixup (vlib_main_t *vm, const ip_adjacency_t *adj, vlib_buffer_t *b,
const void *data)
{
u8 iph_offset = 0;
ip6_header_t *ip6_out;
ip4_header_t *ip4_in;
/* Must set locally originated otherwise we're not allowed to
fragment the packet later */
b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
ip6_out = vlib_buffer_get_current (b);
iph_offset = vnet_buffer (b)->ip.save_rewrite_length;
ip4_in = vlib_buffer_get_current (b) + iph_offset;
u32 vtcfl = 0x6 << 28;
vtcfl |= ip4_in->tos << 20;
vtcfl |= vnet_buffer (b)->ip.flow_hash & 0x000fffff;
ip6_out->ip_version_traffic_class_and_flow_label =
clib_host_to_net_u32 (vtcfl);
}
static adj_midchain_fixup_t
wg_peer_get_fixup (wg_peer_t *peer, vnet_link_t lt)
{
if (!ip46_address_is_ip4 (&peer->dst.addr))
{
if (lt == VNET_LINK_IP4)
return (wg_peer_46_fixup);
if (lt == VNET_LINK_IP6)
return (wg_peer_66_fixup);
}
return (NULL);
}
walk_rc_t
wg_peer_if_admin_state_change (index_t peeri, void *data)
{
@ -170,6 +250,7 @@ walk_rc_t
wg_peer_if_adj_change (index_t peeri, void *data)
{
adj_index_t *adj_index = data;
adj_midchain_fixup_t fixup;
ip_adjacency_t *adj;
wg_peer_t *peer;
fib_prefix_t *allowed_ip;
@ -179,15 +260,16 @@ wg_peer_if_adj_change (index_t peeri, void *data)
peer = wg_peer_get (peeri);
vec_foreach (allowed_ip, peer->allowed_ips)
{
if (fib_prefix_is_cover_addr_4 (allowed_ip,
&adj->sub_type.nbr.next_hop.ip4))
if (fib_prefix_is_cover_addr_46 (allowed_ip,
&adj->sub_type.nbr.next_hop))
{
vec_add1 (peer->adj_indices, *adj_index);
vec_validate_init_empty (wg_peer_by_adj_index, *adj_index,
INDEX_INVALID);
wg_peer_by_adj_index[*adj_index] = peer - wg_peer_pool;
adj_nbr_midchain_update_rewrite (*adj_index, NULL, NULL,
fixup = wg_peer_get_fixup (peer, adj_get_link_type (*adj_index));
adj_nbr_midchain_update_rewrite (*adj_index, fixup, NULL,
ADJ_FLAG_MIDCHAIN_IP_STACK,
vec_dup (peer->rewrite));
@ -236,7 +318,9 @@ wg_peer_fill (vlib_main_t *vm, wg_peer_t *peer, u32 table_id,
ip_address_to_46 (&wgi->src_ip, &peer->src.addr);
peer->src.port = wgi->port;
peer->rewrite = wg_peer_build_rewrite (peer);
u8 is_ip4 = ip46_address_is_ip4 (&peer->dst.addr);
peer->rewrite = wg_peer_build_rewrite (peer, is_ip4);
u32 ii;
vec_validate (peer->allowed_ips, vec_len (allowed_ips) - 1);

View File

@ -31,7 +31,14 @@ typedef struct ip4_udp_header_t_
udp_header_t udp;
} __clib_packed ip4_udp_header_t;
typedef struct ip6_udp_header_t_
{
ip6_header_t ip6;
udp_header_t udp;
} __clib_packed ip6_udp_header_t;
u8 *format_ip4_udp_header (u8 * s, va_list * va);
u8 *format_ip6_udp_header (u8 *s, va_list *va);
typedef struct wg_peer_endpoint_t_
{
@ -141,15 +148,16 @@ wg_peer_assign_thread (u32 thread_id)
}
static_always_inline bool
fib_prefix_is_cover_addr_4 (const fib_prefix_t *p1, const ip4_address_t *ip4)
fib_prefix_is_cover_addr_46 (const fib_prefix_t *p1, const ip46_address_t *ip)
{
switch (p1->fp_proto)
{
case FIB_PROTOCOL_IP4:
return (ip4_destination_matches_route (&ip4_main, &p1->fp_addr.ip4, ip4,
p1->fp_len) != 0);
return (ip4_destination_matches_route (&ip4_main, &p1->fp_addr.ip4,
&ip->ip4, p1->fp_len) != 0);
case FIB_PROTOCOL_IP6:
return (false);
return (ip6_destination_matches_route (&ip6_main, &p1->fp_addr.ip6,
&ip->ip6, p1->fp_len) != 0);
case FIB_PROTOCOL_MPLS:
break;
}

65
src/plugins/wireguard/wireguard_send.c Executable file → Normal file
View File

@ -22,11 +22,11 @@
#include <wireguard/wireguard_send.h>
static int
ip46_enqueue_packet (vlib_main_t * vm, u32 bi0, int is_ip6)
ip46_enqueue_packet (vlib_main_t *vm, u32 bi0, int is_ip4)
{
vlib_frame_t *f = 0;
u32 lookup_node_index =
is_ip6 ? ip6_lookup_node.index : ip4_lookup_node.index;
is_ip4 ? ip4_lookup_node.index : ip6_lookup_node.index;
f = vlib_get_frame_to_node (vm, lookup_node_index);
/* f can not be NULL here - frame allocation failure causes panic */
@ -41,25 +41,41 @@ ip46_enqueue_packet (vlib_main_t * vm, u32 bi0, int is_ip6)
}
static void
wg_buffer_prepend_rewrite (vlib_buffer_t * b0, const wg_peer_t * peer)
wg_buffer_prepend_rewrite (vlib_buffer_t *b0, const wg_peer_t *peer, u8 is_ip4)
{
ip4_udp_header_t *hdr;
if (is_ip4)
{
ip4_udp_header_t *hdr4;
vlib_buffer_advance (b0, -sizeof (*hdr));
vlib_buffer_advance (b0, -sizeof (*hdr4));
hdr = vlib_buffer_get_current (b0);
clib_memcpy (hdr, peer->rewrite, vec_len (peer->rewrite));
hdr4 = vlib_buffer_get_current (b0);
clib_memcpy (hdr4, peer->rewrite, vec_len (peer->rewrite));
hdr->udp.length =
clib_host_to_net_u16 (b0->current_length - sizeof (ip4_header_t));
ip4_header_set_len_w_chksum (&hdr->ip4,
clib_host_to_net_u16 (b0->current_length));
hdr4->udp.length =
clib_host_to_net_u16 (b0->current_length - sizeof (ip4_header_t));
ip4_header_set_len_w_chksum (&hdr4->ip4,
clib_host_to_net_u16 (b0->current_length));
}
else
{
ip6_udp_header_t *hdr6;
vlib_buffer_advance (b0, -sizeof (*hdr6));
hdr6 = vlib_buffer_get_current (b0);
clib_memcpy (hdr6, peer->rewrite, vec_len (peer->rewrite));
hdr6->udp.length =
clib_host_to_net_u16 (b0->current_length - sizeof (ip6_header_t));
hdr6->ip6.payload_length = clib_host_to_net_u16 (b0->current_length);
}
}
static bool
wg_create_buffer (vlib_main_t * vm,
const wg_peer_t * peer,
const u8 * packet, u32 packet_len, u32 * bi)
wg_create_buffer (vlib_main_t *vm, const wg_peer_t *peer, const u8 *packet,
u32 packet_len, u32 *bi, u8 is_ip4)
{
u32 n_buf0 = 0;
vlib_buffer_t *b0;
@ -75,7 +91,7 @@ wg_create_buffer (vlib_main_t * vm,
b0->current_length = packet_len;
wg_buffer_prepend_rewrite (b0, peer);
wg_buffer_prepend_rewrite (b0, peer, is_ip4);
return true;
}
@ -113,11 +129,13 @@ wg_send_handshake (vlib_main_t * vm, wg_peer_t * peer, bool is_retry)
else
return false;
u8 is_ip4 = ip46_address_is_ip4 (&peer->dst.addr);
u32 bi0 = 0;
if (!wg_create_buffer (vm, peer, (u8 *) & packet, sizeof (packet), &bi0))
if (!wg_create_buffer (vm, peer, (u8 *) &packet, sizeof (packet), &bi0,
is_ip4))
return false;
ip46_enqueue_packet (vm, bi0, false);
ip46_enqueue_packet (vm, bi0, is_ip4);
return true;
}
@ -185,15 +203,17 @@ wg_send_keepalive (vlib_main_t * vm, wg_peer_t * peer)
goto out;
}
u8 is_ip4 = ip46_address_is_ip4 (&peer->dst.addr);
packet->header.type = MESSAGE_DATA;
if (!wg_create_buffer (vm, peer, (u8 *) packet, size_of_packet, &bi0))
if (!wg_create_buffer (vm, peer, (u8 *) packet, size_of_packet, &bi0,
is_ip4))
{
ret = false;
goto out;
}
ip46_enqueue_packet (vm, bi0, false);
ip46_enqueue_packet (vm, bi0, is_ip4);
wg_timers_any_authenticated_packet_sent (peer);
wg_timers_any_authenticated_packet_traversal (peer);
@ -226,11 +246,12 @@ wg_send_handshake_response (vlib_main_t * vm, wg_peer_t * peer)
peer->last_sent_handshake = vlib_time_now (vm);
u32 bi0 = 0;
if (!wg_create_buffer (vm, peer, (u8 *) & packet,
sizeof (packet), &bi0))
u8 is_ip4 = ip46_address_is_ip4 (&peer->dst.addr);
if (!wg_create_buffer (vm, peer, (u8 *) &packet, sizeof (packet),
&bi0, is_ip4))
return false;
ip46_enqueue_packet (vm, bi0, false);
ip46_enqueue_packet (vm, bi0, is_ip4);
}
else
return false;

File diff suppressed because it is too large Load Diff