summaryrefslogtreecommitdiffstats
path: root/src/vnet/ipsec
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/ipsec')
-rw-r--r--src/vnet/ipsec/ipsec_input.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/src/vnet/ipsec/ipsec_input.c b/src/vnet/ipsec/ipsec_input.c
index 0e92ae9f1a7..8f9eb204c55 100644
--- a/src/vnet/ipsec/ipsec_input.c
+++ b/src/vnet/ipsec/ipsec_input.c
@@ -299,6 +299,15 @@ ipsec_esp_packet_process (vlib_main_t *vm, ipsec_main_t *im, ip4_header_t *ip0,
search_flow_cache = im->input_flow_cache_flag;
udp_or_esp:
+ /* SPI ID field in the ESP header MUST NOT be a zero value */
+ if (esp0->spi == 0)
+ {
+ /* Drop the packet if SPI ID is zero */
+ *ipsec_unprocessed += 1;
+ next[0] = IPSEC_INPUT_NEXT_DROP;
+ return;
+ }
+
if (im->fp_spd_ipv4_in_is_enabled &&
PREDICT_TRUE (INDEX_INVALID != spd0->fp_spd.ip4_in_lookup_hash_idx))
{
@@ -538,20 +547,36 @@ VLIB_NODE_FN (ipsec4_input_node) (vlib_main_t * vm,
ip0 = vlib_buffer_get_current (b[0]);
- if (PREDICT_TRUE
- (ip0->protocol == IP_PROTOCOL_IPSEC_ESP
- || ip0->protocol == IP_PROTOCOL_UDP))
+ if (ip0->protocol == IP_PROTOCOL_UDP)
{
+ udp_header_t *udp0 = NULL;
+ udp0 = (udp_header_t *) ((u8 *) ip0 + ip4_header_bytes (ip0));
- esp0 = (esp_header_t *) ((u8 *) ip0 + ip4_header_bytes (ip0));
- if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_UDP))
+ /* As per rfc3948 in UDP Encapsulated Header, UDP checksum must be
+ * Zero, and receivers must not depen upon UPD checksum.
+ * inside ESP header , SPI ID value MUST NOT be a zero value
+ * */
+
+ if (udp0->checksum == 0)
{
- /* FIXME Skip, if not a UDP encapsulated packet */
- esp0 = (esp_header_t *) ((u8 *) esp0 + sizeof (udp_header_t));
+ esp0 = (esp_header_t *) ((u8 *) udp0 + sizeof (udp_header_t));
+
+ ipsec_esp_packet_process (vm, im, ip0, esp0, thread_index, spd0,
+ b, node, &ipsec_bypassed,
+ &ipsec_dropped, &ipsec_matched,
+ &ipsec_unprocessed, next);
+ if (ipsec_bypassed > 0)
+ goto ipsec_bypassed;
}
+ }
+ else if (PREDICT_TRUE (ip0->protocol == IP_PROTOCOL_IPSEC_ESP))
+ {
+ esp0 = (esp_header_t *) ((u8 *) ip0 + ip4_header_bytes (ip0));
ipsec_esp_packet_process (vm, im, ip0, esp0, thread_index, spd0, b,
node, &ipsec_bypassed, &ipsec_dropped,
&ipsec_matched, &ipsec_unprocessed, next);
+ if (ipsec_bypassed > 0)
+ goto ipsec_bypassed;
}
else if (ip0->protocol == IP_PROTOCOL_IPSEC_AH)
{
@@ -694,6 +719,7 @@ VLIB_NODE_FN (ipsec4_input_node) (vlib_main_t * vm,
}
else
{
+ ipsec_bypassed:
ipsec_unprocessed += 1;
}
n_left_from -= 1;
@@ -725,7 +751,6 @@ VLIB_NODE_FN (ipsec4_input_node) (vlib_main_t * vm,
return frame->n_vectors;
}
-
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ipsec4_input_node) = {
.name = "ipsec4-input-feature",