diff options
author | Alexander Skorichenko <askorichenko@netgate.com> | 2023-01-19 14:26:47 +0100 |
---|---|---|
committer | Matthew Smith <mgsmith@netgate.com> | 2023-02-16 15:01:07 +0000 |
commit | edd28a4102949a6f91280dd7d2fd0d0139de8198 (patch) | |
tree | ac96f8164bef525e7dbfec90f13dc4d9d0b793d2 /src/plugins/wireguard/wireguard_output_tun.c | |
parent | 5b704f4fa1280b5603ed1cbf8ae9be4b2b1cb016 (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>
Diffstat (limited to 'src/plugins/wireguard/wireguard_output_tun.c')
-rw-r--r-- | src/plugins/wireguard/wireguard_output_tun.c | 38 |
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); |