From a6bee0a11a07e4e1e4ac67e5041e9ad197766ba2 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Fri, 14 Jun 2019 01:13:25 -0700 Subject: [PATCH] ipsec: Correctly rewind the buffer to the IP header when punting UDP encapped SPI-0 packets Type: fix Fixes: b71fa75d48 Change-Id: I2d81b373f7659e702759939c096b315afa36f621 Signed-off-by: Neale Ranns --- src/vnet/ipsec/ipsec_if_in.c | 8 ++++--- test/test_punt.py | 53 +++++++++++++++++++++++++++++++---------- test/vpp_ipsec_tun_interface.py | 5 +++- test/vpp_papi_provider.py | 4 +++- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/src/vnet/ipsec/ipsec_if_in.c b/src/vnet/ipsec/ipsec_if_in.c index b585c3d4dcf..9565078b3b9 100644 --- a/src/vnet/ipsec/ipsec_if_in.c +++ b/src/vnet/ipsec/ipsec_if_in.c @@ -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; } diff --git a/test/test_punt.py b/test/test_punt.py index 598f140547b..b93188e4fe2 100644 --- a/test/test_punt.py +++ b/test/test_punt.py @@ -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']) diff --git a/test/vpp_ipsec_tun_interface.py b/test/vpp_ipsec_tun_interface.py index bc689b321f0..223ea4df154 100644 --- a/test/vpp_ipsec_tun_interface.py +++ b/test/vpp_ipsec_tun_interface.py @@ -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) diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index ec98e1db754..6a6fb45529e 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -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 }) -- 2.16.6