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 <nranns@cisco.com>
diff --git a/src/vnet/ipsec/ipsec_if_in.c b/src/vnet/ipsec/ipsec_if_in.c
index b585c3d..9565078 100644
--- a/src/vnet/ipsec/ipsec_if_in.c
+++ b/src/vnet/ipsec/ipsec_if_in.c
@@ -440,7 +440,7 @@
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 @@
(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 @@
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 598f140..b93188e 100644
--- a/test/test_punt.py
+++ b/test/test_punt.py
@@ -141,6 +141,7 @@
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 @@
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 @@
}
#
- # 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 @@
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 @@
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(
@@ -844,6 +852,19 @@
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
#
for cfg in cfgs.values():
@@ -854,7 +875,13 @@
#
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 bc689b3..223ea4d 100644
--- a/test/vpp_ipsec_tun_interface.py
+++ b/test/vpp_ipsec_tun_interface.py
@@ -9,6 +9,7 @@
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 @@
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 @@
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 ec98e1d..6a6fb45 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -1889,7 +1889,8 @@
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 @@
'anti_replay': anti_replay,
'renumber': renumber,
'show_instance': show_instance,
+ 'udp_encap': udp_encap,
'salt': salt
})