ipsec: fix missing udp port check

Type: fix

This patch fixes the missing UDP port check in IPsec NAT-T
case. As of RFC3948 UDP encapped ESP traffic should have
destination port ID of 4500, which was missing.

The related tests are updated with this port ID, too.

Change-Id: I73ecc6a93de8d0f4b642313b0f4d9c2f214a7790
Signed-off-by: Fan Zhang <fanzhang.oss@gmail.com>
diff --git a/src/vnet/ipsec/ipsec_input.c b/src/vnet/ipsec/ipsec_input.c
index 6ccc0be..9cec7dd 100644
--- a/src/vnet/ipsec/ipsec_input.c
+++ b/src/vnet/ipsec/ipsec_input.c
@@ -299,10 +299,11 @@
   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 */
+      /* RFC 4303, section 2.1: The SPI value of zero (0 is reserved for
+       * local, implementation-specific use and MUST NOT be sent on the wire.
+       */
       *ipsec_unprocessed += 1;
       next[0] = IPSEC_INPUT_NEXT_DROP;
       return;
@@ -552,12 +553,10 @@
 	  udp_header_t *udp0 = NULL;
 	  udp0 = (udp_header_t *) ((u8 *) ip0 + ip4_header_bytes (ip0));
 
-	  /* 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)
+	  /* RFC5996 Section 2.23 "Port 4500 is reserved for
+	   * UDP-encapsulated ESP and IKE."
+	   */
+	  if (clib_host_to_net_u16 (4500) == udp0->dst_port)
 	    {
 	      esp0 = (esp_header_t *) ((u8 *) udp0 + sizeof (udp_header_t));
 
diff --git a/test/template_ipsec.py b/test/template_ipsec.py
index b5cd922..7953f60 100644
--- a/test/template_ipsec.py
+++ b/test/template_ipsec.py
@@ -3022,7 +3022,7 @@
             return False
 
     def create_stream(
-        cls, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=5678, proto="UDP-ESP"
+        cls, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=4500, proto="UDP-ESP"
     ):
         packets = []
         packets = super(SpdFlowCacheTemplate, cls).create_stream(
@@ -3031,7 +3031,7 @@
         return packets
 
     def verify_capture(
-        self, src_if, dst_if, capture, tcp_port_in=1234, udp_port_in=5678
+        self, src_if, dst_if, capture, tcp_port_in=1234, udp_port_in=4500
     ):
         super(SpdFlowCacheTemplate, self).verify_l3_l4_capture(
             src_if, dst_if, capture, tcp_port_in, udp_port_in
@@ -3056,7 +3056,7 @@
         super(SpdFastPathTemplate, self).tearDown()
 
     def create_stream(
-        cls, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=5678, proto="UDP-ESP"
+        cls, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=4500, proto="UDP-ESP"
     ):
         packets = []
         packets = super(SpdFastPathTemplate, cls).create_stream(
@@ -3065,7 +3065,7 @@
         return packets
 
     def verify_capture(
-        self, src_if, dst_if, capture, tcp_port_in=1234, udp_port_in=5678
+        self, src_if, dst_if, capture, tcp_port_in=1234, udp_port_in=4500
     ):
         super(SpdFastPathTemplate, self).verify_l3_l4_capture(
             src_if, dst_if, capture, tcp_port_in, udp_port_in
@@ -3084,7 +3084,7 @@
         super(IpsecDefaultTemplate, self).tearDown()
 
     def create_stream(
-        cls, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=5678, proto="UDP-ESP"
+        cls, src_if, dst_if, pkt_count, src_prt=1234, dst_prt=4500, proto="UDP-ESP"
     ):
         packets = []
         packets = super(IpsecDefaultTemplate, cls).create_stream(
@@ -3093,7 +3093,7 @@
         return packets
 
     def verify_capture(
-        self, src_if, dst_if, capture, tcp_port_in=1234, udp_port_in=5678
+        self, src_if, dst_if, capture, tcp_port_in=1234, udp_port_in=4500
     ):
         super(IpsecDefaultTemplate, self).verify_l3_l4_capture(
             src_if, dst_if, capture, tcp_port_in, udp_port_in
diff --git a/test/test_ipsec_spd_flow_cache_input.py b/test/test_ipsec_spd_flow_cache_input.py
index 283f345..b913a98 100644
--- a/test/test_ipsec_spd_flow_cache_input.py
+++ b/test/test_ipsec_spd_flow_cache_input.py
@@ -785,9 +785,9 @@
             # create the packet streams
             # packet hashes to:
             # ad727628
-            packets1 = self.create_stream(self.pg2, self.pg1, pkt_count, 1, 1)
+            packets1 = self.create_stream(self.pg2, self.pg1, pkt_count, 1, 4500)
             # b5512898
-            packets2 = self.create_stream(self.pg0, self.pg3, pkt_count, 1, 1)
+            packets2 = self.create_stream(self.pg0, self.pg3, pkt_count, 1, 4500)
             # add the streams to the source interfaces
             self.pg2.add_stream(packets1)
             self.pg0.add_stream(packets2)
@@ -821,9 +821,9 @@
 
             # create the packet streams
             # 2f8f90f557eef12c
-            packets1 = self.create_stream(self.pg2, self.pg1, pkt_count, 1, 1)
+            packets1 = self.create_stream(self.pg2, self.pg1, pkt_count, 1, 4500)
             # 6b7f9987719ffc1c
-            packets2 = self.create_stream(self.pg3, self.pg2, pkt_count, 1, 1)
+            packets2 = self.create_stream(self.pg3, self.pg2, pkt_count, 1, 4500)
             # add the streams to the source interfaces
             self.pg2.add_stream(packets1)
             self.pg3.add_stream(packets2)