summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Skorichenko <askorichenko@netgate.com>2023-01-19 14:26:47 +0100
committerMatthew Smith <mgsmith@netgate.com>2023-02-16 15:01:07 +0000
commitedd28a4102949a6f91280dd7d2fd0d0139de8198 (patch)
treeac96f8164bef525e7dbfec90f13dc4d9d0b793d2
parent5b704f4fa1280b5603ed1cbf8ae9be4b2b1cb016 (diff)
wireguard: move buffer when insufficient pre_data left
Currently wg-output-tun() doesn't check if a buffer has enough space for prepending an ethernet header (wg header over ipv6 vxlan header case leaves only 8 bytes free). In such a case move buffer's content. Type: fix Change-Id: Iad18860e6b86a3d81f3d96d782de7c59556152d0 Signed-off-by: Alexander Skorichenko <askorichenko@netgate.com>
-rw-r--r--src/plugins/wireguard/wireguard_output_tun.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/src/plugins/wireguard/wireguard_output_tun.c b/src/plugins/wireguard/wireguard_output_tun.c
index f613d6c0c16..c009d0ca57f 100644
--- a/src/plugins/wireguard/wireguard_output_tun.c
+++ b/src/plugins/wireguard/wireguard_output_tun.c
@@ -423,20 +423,7 @@ wg_output_tun_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
goto out;
}
- is_ip4_out = ip46_address_is_ip4 (&peer->src.addr);
- if (is_ip4_out)
- {
- hdr4_out = vlib_buffer_get_current (b[0]);
- message_data_wg = &hdr4_out->wg;
- }
- else
- {
- hdr6_out = vlib_buffer_get_current (b[0]);
- message_data_wg = &hdr6_out->wg;
- }
-
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;
u8 *iv_data = b[0]->pre_data;
@@ -447,13 +434,36 @@ wg_output_tun_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
* into the packet
*/
if (PREDICT_FALSE (encrypted_packet_len >= WG_DEFAULT_DATA_SIZE) ||
- PREDICT_FALSE ((b[0]->current_data + encrypted_packet_len) >=
+ PREDICT_FALSE ((iph_offset + encrypted_packet_len) >=
vlib_buffer_get_default_data_size (vm)))
{
b[0]->error = node->errors[WG_OUTPUT_ERROR_TOO_BIG];
goto out;
}
+ /*
+ * Move the buffer to fit ethernet header
+ */
+ if (b[0]->current_data + VLIB_BUFFER_PRE_DATA_SIZE <
+ sizeof (ethernet_header_t))
+ {
+ vlib_buffer_move (vm, b[0], 0);
+ }
+
+ plain_data = vlib_buffer_get_current (b[0]) + iph_offset;
+
+ is_ip4_out = ip46_address_is_ip4 (&peer->src.addr);
+ if (is_ip4_out)
+ {
+ hdr4_out = vlib_buffer_get_current (b[0]);
+ message_data_wg = &hdr4_out->wg;
+ }
+ else
+ {
+ hdr6_out = vlib_buffer_get_current (b[0]);
+ message_data_wg = &hdr6_out->wg;
+ }
+
if (PREDICT_FALSE (last_adj_index != adj_index))
{
wg_timers_any_authenticated_packet_sent_opt (peer, time);