diff options
Diffstat (limited to 'src/vnet/ipsec')
-rw-r--r-- | src/vnet/ipsec/ipsec_input.c | 41 |
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", |