ipsec: Correctly rewind the buffer to the IP header when punting UDP encapped SPI... 28/20128/2
authorNeale Ranns <nranns@cisco.com>
Fri, 14 Jun 2019 08:13:25 +0000 (01:13 -0700)
committerDamjan Marion <dmarion@me.com>
Fri, 14 Jun 2019 11:19:01 +0000 (11:19 +0000)
Type: fix
Fixes: b71fa75d48

Change-Id: I2d81b373f7659e702759939c096b315afa36f621
Signed-off-by: Neale Ranns <nranns@cisco.com>
src/vnet/ipsec/ipsec_if_in.c
test/test_punt.py
test/vpp_ipsec_tun_interface.py
test/vpp_papi_provider.py

index b585c3d..9565078 100644 (file)
@@ -440,7 +440,7 @@ ipsec_if_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
       ip6_header_t *ip60;
       esp_header_t *esp0;
       u32 len0;
-      u16 buf_adv0;
+      u16 buf_adv0, buf_rewind0;
       u32 tid0;
       ipsec_tunnel_if_t *t0;
       ipsec4_tunnel_key_t key40;
@@ -464,11 +464,12 @@ ipsec_if_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
                (esp_header_t *) ((u8 *) ip40 + ip4_header_bytes (ip40) +
                                  sizeof (udp_header_t));
              buf_adv0 = 0;
+             buf_rewind0 = ip4_header_bytes (ip40) + sizeof (udp_header_t);
            }
          else
            {
              esp0 = (esp_header_t *) ((u8 *) ip40 + ip4_header_bytes (ip40));
-             buf_adv0 = ip4_header_bytes (ip40);
+             buf_rewind0 = buf_adv0 = ip4_header_bytes (ip40);
            }
        }
 
@@ -527,7 +528,8 @@ ipsec_if_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
              else
                {
                  next[0] =
-                   ipsec_ip4_if_no_tunnel (node, b[0], esp0, ip40, buf_adv0);
+                   ipsec_ip4_if_no_tunnel (node, b[0], esp0, ip40,
+                                           buf_rewind0);
                  n_no_tunnel++;
                  goto trace00;
                }
index 598f140..b93188e 100644 (file)
@@ -141,6 +141,7 @@ class TestPuntSocket(VppTestCase):
     def verify_udp_pkts(self, rxs, n_rx, port):
         n_match = 0
         for rx in rxs:
+            rx.show()
             self.assertTrue(rx.haslayer(UDP))
             if rx[UDP].dport == port:
                 n_match += 1
@@ -772,11 +773,14 @@ class TestExceptionPuntSocket(TestPuntSocket):
         punts = self.vapi.punt_socket_dump(type=pt_ex)
         self.assertEqual(len(punts), 0)
 
-    def verify_esp_pkts(self, rxs, n_sent, spi):
+    def verify_esp_pkts(self, rxs, n_sent, spi, has_udp):
         self.assertEqual(len(rxs), n_sent)
         for rx in rxs:
+            self.assertTrue(rx.haslayer(IP))
             self.assertTrue(rx.haslayer(ESP))
             self.assertEqual(rx[ESP].spi, spi)
+            if has_udp:
+                self.assertTrue(rx.haslayer(UDP))
 
     def test_traffic(self):
         """ Punt socket traffic """
@@ -791,7 +795,7 @@ class TestExceptionPuntSocket(TestPuntSocket):
         }
 
         #
-        # we need an IPSec tunnel for this to work otherwise ESP gets dropped
+        # we need an IPSec tunnels for this to work otherwise ESP gets dropped
         # due to unknown IP proto
         #
         VppIpsecTunInterface(self, self.pg0, 1000, 1000,
@@ -803,14 +807,25 @@ class TestExceptionPuntSocket(TestPuntSocket):
                               IPSEC_API_INTEG_ALG_SHA1_96),
                              "0123456701234567",
                              "0123456701234567").add_vpp_config()
+        VppIpsecTunInterface(self, self.pg0, 1001, 1001,
+                             (VppEnum.vl_api_ipsec_crypto_alg_t.
+                              IPSEC_API_CRYPTO_ALG_AES_CBC_128),
+                             "0123456701234567",
+                             "0123456701234567",
+                             (VppEnum.vl_api_ipsec_integ_alg_t.
+                              IPSEC_API_INTEG_ALG_SHA1_96),
+                             "0123456701234567",
+                             "0123456701234567",
+                             udp_encap=True).add_vpp_config()
 
         #
         # we're dealing with IPSec tunnels punting for no-such-tunnel
         # adn SPI=0
         #
         cfgs = dict()
-        cfgs['ipsec4-no-such-tunnel'] = {'spi': 99}
-        cfgs['ipsec4-spi-0'] = {'spi': 0}
+        cfgs['ipsec4-no-such-tunnel'] = {'spi': 99, 'udp': False}
+        cfgs['ipsec4-spi-0'] = {'spi': 0, 'udp': False}
+        cfgs['ipsec4-spi-o-udp-0'] = {'spi': 0, 'udp': True}
 
         #
         # find the VPP ID for these punt exception reasin
@@ -826,16 +841,9 @@ class TestExceptionPuntSocket(TestPuntSocket):
                     break
 
         #
-        # create packet streams and configure a punt sockets
+        # configure punt sockets
         #
         for cfg in cfgs.values():
-            pkt = (Ether(src=self.pg0.remote_mac,
-                         dst=self.pg0.local_mac) /
-                   IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
-                   ESP(spi=cfg['spi'], seq=3) /
-                   Raw('\xa5' * 100))
-            cfg['pkts'] = pkt * self.nr_packets
-
             cfg['sock'] = self.socket_client_create(b"%s/socket_%d" % (
                 six.ensure_binary(self.tempdir), cfg['id']))
             self.vapi.punt_socket_register(
@@ -843,6 +851,19 @@ class TestExceptionPuntSocket(TestPuntSocket):
                 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
                                    cfg['id']))
 
+        #
+        # create packet streams for 'no-such-tunnel' exception
+        #
+        for cfg in cfgs.values():
+            pkt = (Ether(src=self.pg0.remote_mac,
+                         dst=self.pg0.local_mac) /
+                   IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4))
+            if (cfg['udp']):
+                pkt = pkt / UDP(sport=666, dport=4500)
+            pkt = (pkt / ESP(spi=cfg['spi'], seq=3) /
+                   Raw('\xa5' * 100))
+            cfg['pkts'] = [pkt]
+
         #
         # send packets for each SPI we expect to be punted
         #
@@ -854,7 +875,13 @@ class TestExceptionPuntSocket(TestPuntSocket):
         #
         for cfg in cfgs.values():
             rx = cfg['sock'].close()
-            self.verify_esp_pkts(rx, len(cfg['pkts']), cfg['spi'])
+            self.verify_esp_pkts(rx, len(cfg['pkts']),
+                                 cfg['spi'], cfg['udp'])
+
+        #
+        # socket deregister
+        #
+        for cfg in cfgs.values():
             self.vapi.punt_socket_deregister(cfg['vpp'])
 
 
index bc689b3..223ea4d 100644 (file)
@@ -9,6 +9,7 @@ class VppIpsecTunInterface(VppTunnelInterface):
     def __init__(self, test, parent_if, local_spi,
                  remote_spi, crypto_alg, local_crypto_key, remote_crypto_key,
                  integ_alg, local_integ_key, remote_integ_key, salt=0,
+                 udp_encap=False,
                  is_ip6=False):
         super(VppIpsecTunInterface, self).__init__(test, parent_if)
         self.local_spi = local_spi
@@ -26,6 +27,7 @@ class VppIpsecTunInterface(VppTunnelInterface):
         else:
             self.local_ip = self.parent_if.local_ip4
             self.remote_ip = self.parent_if.remote_ip4
+        self.udp_encap = False
 
     def add_vpp_config(self):
         r = self.test.vapi.ipsec_tunnel_if_add_del(
@@ -33,7 +35,8 @@ class VppIpsecTunInterface(VppTunnelInterface):
             self.remote_spi, self.local_spi,
             self.crypto_alg, self.local_crypto_key, self.remote_crypto_key,
             self.integ_alg, self.local_integ_key, self.remote_integ_key,
-            salt=self.salt)
+            salt=self.salt,
+            udp_encap=self.udp_encap)
         self.set_sw_if_index(r.sw_if_index)
         self.generate_remote_hosts()
         self.test.registry.register(self, self.test.logger)
index ec98e1d..6a6fb45 100644 (file)
@@ -1889,7 +1889,8 @@ class VppPapiProvider(object):
                                 remote_spi, crypto_alg, local_crypto_key,
                                 remote_crypto_key, integ_alg, local_integ_key,
                                 remote_integ_key, is_add=1, esn=0, salt=0,
-                                anti_replay=1, renumber=0, show_instance=0):
+                                anti_replay=1, renumber=0,
+                                udp_encap=0, show_instance=0):
         return self.api(
             self.papi.ipsec_tunnel_if_add_del,
             {
@@ -1912,6 +1913,7 @@ class VppPapiProvider(object):
                 'anti_replay': anti_replay,
                 'renumber': renumber,
                 'show_instance': show_instance,
+                'udp_encap': udp_encap,
                 'salt': salt
             })