xref: /aosp_15_r20/kernel/tests/net/test/xfrm_tunnel_test.py (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3
2*2f2c4c7aSAndroid Build Coastguard Worker#
3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2017 The Android Open Source Project
4*2f2c4c7aSAndroid Build Coastguard Worker#
5*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*2f2c4c7aSAndroid Build Coastguard Worker#
9*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0
10*2f2c4c7aSAndroid Build Coastguard Worker#
11*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License.
16*2f2c4c7aSAndroid Build Coastguard Worker
17*2f2c4c7aSAndroid Build Coastguard Worker# pylint: disable=g-bad-todo,g-bad-file-header,wildcard-import
18*2f2c4c7aSAndroid Build Coastguard Workerfrom errno import *  # pylint: disable=wildcard-import
19*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import *  # pylint: disable=wildcard-import
20*2f2c4c7aSAndroid Build Coastguard Worker
21*2f2c4c7aSAndroid Build Coastguard Workerimport random
22*2f2c4c7aSAndroid Build Coastguard Workerimport itertools
23*2f2c4c7aSAndroid Build Coastguard Workerimport struct
24*2f2c4c7aSAndroid Build Coastguard Workerimport unittest
25*2f2c4c7aSAndroid Build Coastguard Worker
26*2f2c4c7aSAndroid Build Coastguard Workerfrom net_test import LINUX_VERSION
27*2f2c4c7aSAndroid Build Coastguard Workerfrom scapy import all as scapy
28*2f2c4c7aSAndroid Build Coastguard Workerfrom tun_twister import TunTwister
29*2f2c4c7aSAndroid Build Coastguard Workerimport csocket
30*2f2c4c7aSAndroid Build Coastguard Workerimport iproute
31*2f2c4c7aSAndroid Build Coastguard Workerimport multinetwork_base
32*2f2c4c7aSAndroid Build Coastguard Workerimport net_test
33*2f2c4c7aSAndroid Build Coastguard Workerimport packets
34*2f2c4c7aSAndroid Build Coastguard Workerimport util
35*2f2c4c7aSAndroid Build Coastguard Workerimport xfrm
36*2f2c4c7aSAndroid Build Coastguard Workerimport xfrm_base
37*2f2c4c7aSAndroid Build Coastguard Worker
38*2f2c4c7aSAndroid Build Coastguard Worker_LOOPBACK_IFINDEX = 1
39*2f2c4c7aSAndroid Build Coastguard Worker_TEST_XFRM_IFNAME = "ipsec42"
40*2f2c4c7aSAndroid Build Coastguard Worker_TEST_XFRM_IF_ID = 42
41*2f2c4c7aSAndroid Build Coastguard Worker_TEST_SPI = 0x1234
42*2f2c4c7aSAndroid Build Coastguard Worker
43*2f2c4c7aSAndroid Build Coastguard Worker# Two kernel fixes have been added in 5.17 to allow XFRM_MIGRATE to work correctly
44*2f2c4c7aSAndroid Build Coastguard Worker# when (1) there are multiple tunnels with the same selectors; and (2) addresses
45*2f2c4c7aSAndroid Build Coastguard Worker# are updated to a different IP family. These two fixes were pulled into upstream
46*2f2c4c7aSAndroid Build Coastguard Worker# LTS releases 4.14.273, 4.19.236, 5.4.186, 5.10.107 and 5.15.30, from whence they
47*2f2c4c7aSAndroid Build Coastguard Worker# flowed into the Android Common Kernel (via standard LTS merges).
48*2f2c4c7aSAndroid Build Coastguard Worker#
49*2f2c4c7aSAndroid Build Coastguard Worker# Note 'xfrm: Check if_id in xfrm_migrate' did not end up in 4.14 LTS,
50*2f2c4c7aSAndroid Build Coastguard Worker# and is only present in ACK android-4.14-stable after 4.14.320 LTS merge.
51*2f2c4c7aSAndroid Build Coastguard Worker# See https://android-review.git.corp.google.com/c/kernel/common/+/2640243
52*2f2c4c7aSAndroid Build Coastguard Worker#
53*2f2c4c7aSAndroid Build Coastguard Worker# As such we require 4.14.321+, 4.19.236+, 5.4.186+, 5.10.107+, 5.15.30+ or 5.17+
54*2f2c4c7aSAndroid Build Coastguard Worker# to have these fixes.
55*2f2c4c7aSAndroid Build Coastguard Workerdef HasXfrmMigrateFixes():
56*2f2c4c7aSAndroid Build Coastguard Worker    return net_test.KernelAtLeast([(4, 19, 236), (5, 4, 186),
57*2f2c4c7aSAndroid Build Coastguard Worker                                   (5, 10, 107), (5, 15, 30)]) or net_test.NonGXI(4, 14)
58*2f2c4c7aSAndroid Build Coastguard Worker
59*2f2c4c7aSAndroid Build Coastguard Worker
60*2f2c4c7aSAndroid Build Coastguard Worker# Does the kernel support CONFIG_XFRM_MIGRATE and include the kernel fixes?
61*2f2c4c7aSAndroid Build Coastguard Workerdef SupportsXfrmMigrate():
62*2f2c4c7aSAndroid Build Coastguard Worker  if not HasXfrmMigrateFixes():
63*2f2c4c7aSAndroid Build Coastguard Worker    return False
64*2f2c4c7aSAndroid Build Coastguard Worker
65*2f2c4c7aSAndroid Build Coastguard Worker  # 5.10+ must have CONFIG_XFRM_MIGRATE enabled
66*2f2c4c7aSAndroid Build Coastguard Worker  if LINUX_VERSION >= (5, 10, 0):
67*2f2c4c7aSAndroid Build Coastguard Worker    return True
68*2f2c4c7aSAndroid Build Coastguard Worker
69*2f2c4c7aSAndroid Build Coastguard Worker  try:
70*2f2c4c7aSAndroid Build Coastguard Worker    x = xfrm.Xfrm()
71*2f2c4c7aSAndroid Build Coastguard Worker    wildcard_addr = net_test.GetWildcardAddress(6)
72*2f2c4c7aSAndroid Build Coastguard Worker    selector = xfrm.EmptySelector(AF_INET6)
73*2f2c4c7aSAndroid Build Coastguard Worker
74*2f2c4c7aSAndroid Build Coastguard Worker    # Expect migration to fail with EINVAL because it is trying to migrate a
75*2f2c4c7aSAndroid Build Coastguard Worker    # non-existent SA.
76*2f2c4c7aSAndroid Build Coastguard Worker    x.MigrateTunnel(xfrm.XFRM_POLICY_OUT, selector, wildcard_addr, wildcard_addr,
77*2f2c4c7aSAndroid Build Coastguard Worker                    wildcard_addr, wildcard_addr, _TEST_SPI,
78*2f2c4c7aSAndroid Build Coastguard Worker                    None, None, None, None, None, None)
79*2f2c4c7aSAndroid Build Coastguard Worker    print("Migration succeeded unexpectedly, assuming XFRM_MIGRATE is enabled")
80*2f2c4c7aSAndroid Build Coastguard Worker    return True
81*2f2c4c7aSAndroid Build Coastguard Worker  except IOError as err:
82*2f2c4c7aSAndroid Build Coastguard Worker    if err.errno == ENOPROTOOPT:
83*2f2c4c7aSAndroid Build Coastguard Worker      return False
84*2f2c4c7aSAndroid Build Coastguard Worker    elif err.errno == EINVAL:
85*2f2c4c7aSAndroid Build Coastguard Worker      return True
86*2f2c4c7aSAndroid Build Coastguard Worker    else:
87*2f2c4c7aSAndroid Build Coastguard Worker      print("Unexpected error, assuming XFRM_MIGRATE is enabled:", err.errno)
88*2f2c4c7aSAndroid Build Coastguard Worker      return True
89*2f2c4c7aSAndroid Build Coastguard Worker
90*2f2c4c7aSAndroid Build Coastguard WorkerSUPPORTS_XFRM_MIGRATE = SupportsXfrmMigrate()
91*2f2c4c7aSAndroid Build Coastguard Worker
92*2f2c4c7aSAndroid Build Coastguard Worker# Parameters to setup tunnels as special networks
93*2f2c4c7aSAndroid Build Coastguard Worker_TUNNEL_NETID_OFFSET = 0xFC00  # Matches reserved netid range for IpSecService
94*2f2c4c7aSAndroid Build Coastguard Worker_BASE_TUNNEL_NETID = {4: 40, 6: 60}
95*2f2c4c7aSAndroid Build Coastguard Worker_BASE_VTI_OKEY = 2000000100
96*2f2c4c7aSAndroid Build Coastguard Worker_BASE_VTI_IKEY = 2000000200
97*2f2c4c7aSAndroid Build Coastguard Worker
98*2f2c4c7aSAndroid Build Coastguard Worker_TEST_OUT_SPI = _TEST_SPI
99*2f2c4c7aSAndroid Build Coastguard Worker_TEST_IN_SPI = _TEST_OUT_SPI
100*2f2c4c7aSAndroid Build Coastguard Worker
101*2f2c4c7aSAndroid Build Coastguard Worker_TEST_OKEY = 2000000100
102*2f2c4c7aSAndroid Build Coastguard Worker_TEST_IKEY = 2000000200
103*2f2c4c7aSAndroid Build Coastguard Worker
104*2f2c4c7aSAndroid Build Coastguard Worker_TEST_REMOTE_PORT = 1234
105*2f2c4c7aSAndroid Build Coastguard Worker
106*2f2c4c7aSAndroid Build Coastguard Worker_SCAPY_IP_TYPE = {4: scapy.IP, 6: scapy.IPv6}
107*2f2c4c7aSAndroid Build Coastguard Worker
108*2f2c4c7aSAndroid Build Coastguard Worker
109*2f2c4c7aSAndroid Build Coastguard Workerdef _GetLocalInnerAddress(version):
110*2f2c4c7aSAndroid Build Coastguard Worker  return {4: "10.16.5.15", 6: "2001:db8:1::1"}[version]
111*2f2c4c7aSAndroid Build Coastguard Worker
112*2f2c4c7aSAndroid Build Coastguard Worker
113*2f2c4c7aSAndroid Build Coastguard Workerdef _GetRemoteInnerAddress(version):
114*2f2c4c7aSAndroid Build Coastguard Worker  return {4: "10.16.5.20", 6: "2001:db8:2::1"}[version]
115*2f2c4c7aSAndroid Build Coastguard Worker
116*2f2c4c7aSAndroid Build Coastguard Worker
117*2f2c4c7aSAndroid Build Coastguard Workerdef _GetRemoteOuterAddress(version):
118*2f2c4c7aSAndroid Build Coastguard Worker  return {4: net_test.IPV4_ADDR, 6: net_test.IPV6_ADDR}[version]
119*2f2c4c7aSAndroid Build Coastguard Worker
120*2f2c4c7aSAndroid Build Coastguard Worker
121*2f2c4c7aSAndroid Build Coastguard Workerdef _GetNullAuthCryptTunnelModePkt(inner_version, src_inner, src_outer,
122*2f2c4c7aSAndroid Build Coastguard Worker                                   src_port, dst_inner, dst_outer,
123*2f2c4c7aSAndroid Build Coastguard Worker                                   dst_port, spi, seq_num, ip_hdr_options=None):
124*2f2c4c7aSAndroid Build Coastguard Worker  if ip_hdr_options is None:
125*2f2c4c7aSAndroid Build Coastguard Worker    ip_hdr_options = {}
126*2f2c4c7aSAndroid Build Coastguard Worker
127*2f2c4c7aSAndroid Build Coastguard Worker  ip_hdr_options.update({'src': src_inner, 'dst': dst_inner})
128*2f2c4c7aSAndroid Build Coastguard Worker
129*2f2c4c7aSAndroid Build Coastguard Worker  # Build and receive an ESP packet destined for the inner socket
130*2f2c4c7aSAndroid Build Coastguard Worker  IpType = {4: scapy.IP, 6: scapy.IPv6}[inner_version]
131*2f2c4c7aSAndroid Build Coastguard Worker  input_pkt = (
132*2f2c4c7aSAndroid Build Coastguard Worker      IpType(**ip_hdr_options) / scapy.UDP(sport=src_port, dport=dst_port) /
133*2f2c4c7aSAndroid Build Coastguard Worker      net_test.UDP_PAYLOAD)
134*2f2c4c7aSAndroid Build Coastguard Worker  input_pkt = IpType(bytes(input_pkt))  # Compute length, checksum.
135*2f2c4c7aSAndroid Build Coastguard Worker  input_pkt = xfrm_base.EncryptPacketWithNull(input_pkt, spi, seq_num,
136*2f2c4c7aSAndroid Build Coastguard Worker                                              (src_outer, dst_outer))
137*2f2c4c7aSAndroid Build Coastguard Worker
138*2f2c4c7aSAndroid Build Coastguard Worker  return input_pkt
139*2f2c4c7aSAndroid Build Coastguard Worker
140*2f2c4c7aSAndroid Build Coastguard Worker
141*2f2c4c7aSAndroid Build Coastguard Workerdef _CreateReceiveSock(version, port=0):
142*2f2c4c7aSAndroid Build Coastguard Worker  # Create a socket to receive packets.
143*2f2c4c7aSAndroid Build Coastguard Worker  read_sock = socket(net_test.GetAddressFamily(version), SOCK_DGRAM, 0)
144*2f2c4c7aSAndroid Build Coastguard Worker  read_sock.bind((net_test.GetWildcardAddress(version), port))
145*2f2c4c7aSAndroid Build Coastguard Worker  # The second parameter of the tuple is the port number regardless of AF.
146*2f2c4c7aSAndroid Build Coastguard Worker  local_port = read_sock.getsockname()[1]
147*2f2c4c7aSAndroid Build Coastguard Worker  # Guard against the eventuality of the receive failing.
148*2f2c4c7aSAndroid Build Coastguard Worker  csocket.SetSocketTimeout(read_sock, 500)
149*2f2c4c7aSAndroid Build Coastguard Worker
150*2f2c4c7aSAndroid Build Coastguard Worker  return read_sock, local_port
151*2f2c4c7aSAndroid Build Coastguard Worker
152*2f2c4c7aSAndroid Build Coastguard Worker
153*2f2c4c7aSAndroid Build Coastguard Workerdef _SendPacket(testInstance, netid, version, remote, remote_port):
154*2f2c4c7aSAndroid Build Coastguard Worker  # Send a packet out via the tunnel-backed network, bound for the port number
155*2f2c4c7aSAndroid Build Coastguard Worker  # of the input socket.
156*2f2c4c7aSAndroid Build Coastguard Worker  write_sock = socket(net_test.GetAddressFamily(version), SOCK_DGRAM, 0)
157*2f2c4c7aSAndroid Build Coastguard Worker  testInstance.SelectInterface(write_sock, netid, "mark")
158*2f2c4c7aSAndroid Build Coastguard Worker  write_sock.sendto(net_test.UDP_PAYLOAD, (remote, remote_port))
159*2f2c4c7aSAndroid Build Coastguard Worker  local_port = write_sock.getsockname()[1]
160*2f2c4c7aSAndroid Build Coastguard Worker  write_sock.close()
161*2f2c4c7aSAndroid Build Coastguard Worker
162*2f2c4c7aSAndroid Build Coastguard Worker  return local_port
163*2f2c4c7aSAndroid Build Coastguard Worker
164*2f2c4c7aSAndroid Build Coastguard Worker
165*2f2c4c7aSAndroid Build Coastguard Workerdef InjectTests():
166*2f2c4c7aSAndroid Build Coastguard Worker  InjectParameterizedTests(XfrmTunnelTest)
167*2f2c4c7aSAndroid Build Coastguard Worker  InjectParameterizedTests(XfrmInterfaceTest)
168*2f2c4c7aSAndroid Build Coastguard Worker  InjectParameterizedTests(XfrmVtiTest)
169*2f2c4c7aSAndroid Build Coastguard Worker  InjectParameterizedMigrateTests(XfrmInterfaceMigrateTest)
170*2f2c4c7aSAndroid Build Coastguard Worker
171*2f2c4c7aSAndroid Build Coastguard Worker
172*2f2c4c7aSAndroid Build Coastguard Workerdef InjectParameterizedTests(cls):
173*2f2c4c7aSAndroid Build Coastguard Worker  VERSIONS = (4, 6)
174*2f2c4c7aSAndroid Build Coastguard Worker  param_list = itertools.product(VERSIONS, VERSIONS)
175*2f2c4c7aSAndroid Build Coastguard Worker
176*2f2c4c7aSAndroid Build Coastguard Worker  def NameGenerator(*args):
177*2f2c4c7aSAndroid Build Coastguard Worker    return "IPv%d_in_IPv%d" % tuple(args)
178*2f2c4c7aSAndroid Build Coastguard Worker
179*2f2c4c7aSAndroid Build Coastguard Worker  util.InjectParameterizedTest(cls, param_list, NameGenerator)
180*2f2c4c7aSAndroid Build Coastguard Worker
181*2f2c4c7aSAndroid Build Coastguard Workerdef InjectParameterizedMigrateTests(cls):
182*2f2c4c7aSAndroid Build Coastguard Worker  VERSIONS = (4, 6)
183*2f2c4c7aSAndroid Build Coastguard Worker  param_list = itertools.product(VERSIONS, VERSIONS, VERSIONS)
184*2f2c4c7aSAndroid Build Coastguard Worker
185*2f2c4c7aSAndroid Build Coastguard Worker  def NameGenerator(*args):
186*2f2c4c7aSAndroid Build Coastguard Worker    return "IPv%d_in_IPv%d_to_outer_IPv%d" % tuple(args)
187*2f2c4c7aSAndroid Build Coastguard Worker
188*2f2c4c7aSAndroid Build Coastguard Worker  util.InjectParameterizedTest(cls, param_list, NameGenerator)
189*2f2c4c7aSAndroid Build Coastguard Worker
190*2f2c4c7aSAndroid Build Coastguard Worker
191*2f2c4c7aSAndroid Build Coastguard Workerclass XfrmTunnelTest(xfrm_base.XfrmLazyTest):
192*2f2c4c7aSAndroid Build Coastguard Worker
193*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckTunnelOutput(self, inner_version, outer_version, underlying_netid,
194*2f2c4c7aSAndroid Build Coastguard Worker                         netid, local_inner, remote_inner, local_outer,
195*2f2c4c7aSAndroid Build Coastguard Worker                         remote_outer, write_sock):
196*2f2c4c7aSAndroid Build Coastguard Worker
197*2f2c4c7aSAndroid Build Coastguard Worker    write_sock.sendto(net_test.UDP_PAYLOAD, (remote_inner, 53))
198*2f2c4c7aSAndroid Build Coastguard Worker    self._ExpectEspPacketOn(underlying_netid, _TEST_OUT_SPI, 1, None,
199*2f2c4c7aSAndroid Build Coastguard Worker                            local_outer, remote_outer)
200*2f2c4c7aSAndroid Build Coastguard Worker
201*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckTunnelInput(self, inner_version, outer_version, underlying_netid,
202*2f2c4c7aSAndroid Build Coastguard Worker                        netid, local_inner, remote_inner, local_outer,
203*2f2c4c7aSAndroid Build Coastguard Worker                        remote_outer, read_sock):
204*2f2c4c7aSAndroid Build Coastguard Worker
205*2f2c4c7aSAndroid Build Coastguard Worker    # The second parameter of the tuple is the port number regardless of AF.
206*2f2c4c7aSAndroid Build Coastguard Worker    local_port = read_sock.getsockname()[1]
207*2f2c4c7aSAndroid Build Coastguard Worker
208*2f2c4c7aSAndroid Build Coastguard Worker    # Build and receive an ESP packet destined for the inner socket
209*2f2c4c7aSAndroid Build Coastguard Worker    input_pkt = _GetNullAuthCryptTunnelModePkt(
210*2f2c4c7aSAndroid Build Coastguard Worker        inner_version, remote_inner, remote_outer, _TEST_REMOTE_PORT,
211*2f2c4c7aSAndroid Build Coastguard Worker        local_inner, local_outer, local_port, _TEST_IN_SPI, 1)
212*2f2c4c7aSAndroid Build Coastguard Worker    self.ReceivePacketOn(underlying_netid, input_pkt)
213*2f2c4c7aSAndroid Build Coastguard Worker
214*2f2c4c7aSAndroid Build Coastguard Worker    # Verify that the packet data and src are correct
215*2f2c4c7aSAndroid Build Coastguard Worker    data, src = read_sock.recvfrom(4096)
216*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(net_test.UDP_PAYLOAD, data)
217*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual((remote_inner, _TEST_REMOTE_PORT), src[:2])
218*2f2c4c7aSAndroid Build Coastguard Worker
219*2f2c4c7aSAndroid Build Coastguard Worker  def _TestTunnel(self, inner_version, outer_version, func, direction,
220*2f2c4c7aSAndroid Build Coastguard Worker                  test_output_mark_unset):
221*2f2c4c7aSAndroid Build Coastguard Worker    """Test a unidirectional XFRM Tunnel with explicit selectors"""
222*2f2c4c7aSAndroid Build Coastguard Worker    # Select the underlying netid, which represents the external
223*2f2c4c7aSAndroid Build Coastguard Worker    # interface from/to which to route ESP packets.
224*2f2c4c7aSAndroid Build Coastguard Worker    u_netid = self.RandomNetid()
225*2f2c4c7aSAndroid Build Coastguard Worker    # Select a random netid that will originate traffic locally and
226*2f2c4c7aSAndroid Build Coastguard Worker    # which represents the netid on which the plaintext is sent
227*2f2c4c7aSAndroid Build Coastguard Worker    netid = self.RandomNetid(exclude=u_netid)
228*2f2c4c7aSAndroid Build Coastguard Worker
229*2f2c4c7aSAndroid Build Coastguard Worker    local_inner = self.MyAddress(inner_version, netid)
230*2f2c4c7aSAndroid Build Coastguard Worker    remote_inner = _GetRemoteInnerAddress(inner_version)
231*2f2c4c7aSAndroid Build Coastguard Worker    local_outer = self.MyAddress(outer_version, u_netid)
232*2f2c4c7aSAndroid Build Coastguard Worker    remote_outer = _GetRemoteOuterAddress(outer_version)
233*2f2c4c7aSAndroid Build Coastguard Worker
234*2f2c4c7aSAndroid Build Coastguard Worker    output_mark = u_netid
235*2f2c4c7aSAndroid Build Coastguard Worker    if test_output_mark_unset:
236*2f2c4c7aSAndroid Build Coastguard Worker      output_mark = None
237*2f2c4c7aSAndroid Build Coastguard Worker      self.SetDefaultNetwork(u_netid)
238*2f2c4c7aSAndroid Build Coastguard Worker
239*2f2c4c7aSAndroid Build Coastguard Worker    try:
240*2f2c4c7aSAndroid Build Coastguard Worker      # Create input/ouput SPs, SAs and sockets to simulate a more realistic
241*2f2c4c7aSAndroid Build Coastguard Worker      # environment.
242*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.CreateTunnel(
243*2f2c4c7aSAndroid Build Coastguard Worker          xfrm.XFRM_POLICY_IN, xfrm.SrcDstSelector(remote_inner, local_inner),
244*2f2c4c7aSAndroid Build Coastguard Worker          remote_outer, local_outer, _TEST_IN_SPI, xfrm_base._ALGO_CRYPT_NULL,
245*2f2c4c7aSAndroid Build Coastguard Worker          xfrm_base._ALGO_AUTH_NULL, None, None, None, xfrm.MATCH_METHOD_ALL)
246*2f2c4c7aSAndroid Build Coastguard Worker
247*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.CreateTunnel(
248*2f2c4c7aSAndroid Build Coastguard Worker          xfrm.XFRM_POLICY_OUT, xfrm.SrcDstSelector(local_inner, remote_inner),
249*2f2c4c7aSAndroid Build Coastguard Worker          local_outer, remote_outer, _TEST_OUT_SPI, xfrm_base._ALGO_CBC_AES_256,
250*2f2c4c7aSAndroid Build Coastguard Worker          xfrm_base._ALGO_HMAC_SHA1, None, output_mark, None, xfrm.MATCH_METHOD_ALL)
251*2f2c4c7aSAndroid Build Coastguard Worker
252*2f2c4c7aSAndroid Build Coastguard Worker      write_sock = socket(net_test.GetAddressFamily(inner_version), SOCK_DGRAM, 0)
253*2f2c4c7aSAndroid Build Coastguard Worker      self.SelectInterface(write_sock, netid, "mark")
254*2f2c4c7aSAndroid Build Coastguard Worker      read_sock, _ = _CreateReceiveSock(inner_version)
255*2f2c4c7aSAndroid Build Coastguard Worker
256*2f2c4c7aSAndroid Build Coastguard Worker      sock = write_sock if direction == xfrm.XFRM_POLICY_OUT else read_sock
257*2f2c4c7aSAndroid Build Coastguard Worker      func(inner_version, outer_version, u_netid, netid, local_inner,
258*2f2c4c7aSAndroid Build Coastguard Worker          remote_inner, local_outer, remote_outer, sock)
259*2f2c4c7aSAndroid Build Coastguard Worker
260*2f2c4c7aSAndroid Build Coastguard Worker      write_sock.close()
261*2f2c4c7aSAndroid Build Coastguard Worker      read_sock.close()
262*2f2c4c7aSAndroid Build Coastguard Worker    finally:
263*2f2c4c7aSAndroid Build Coastguard Worker      if test_output_mark_unset:
264*2f2c4c7aSAndroid Build Coastguard Worker        self.ClearDefaultNetwork()
265*2f2c4c7aSAndroid Build Coastguard Worker
266*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestTunnelInput(self, inner_version, outer_version):
267*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, self._CheckTunnelInput,
268*2f2c4c7aSAndroid Build Coastguard Worker                     xfrm.XFRM_POLICY_IN, False)
269*2f2c4c7aSAndroid Build Coastguard Worker
270*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestTunnelOutput(self, inner_version, outer_version):
271*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, self._CheckTunnelOutput,
272*2f2c4c7aSAndroid Build Coastguard Worker                     xfrm.XFRM_POLICY_OUT, False)
273*2f2c4c7aSAndroid Build Coastguard Worker
274*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestTunnelOutputNoSetMark(self, inner_version, outer_version):
275*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, self._CheckTunnelOutput,
276*2f2c4c7aSAndroid Build Coastguard Worker                     xfrm.XFRM_POLICY_OUT, True)
277*2f2c4c7aSAndroid Build Coastguard Worker
278*2f2c4c7aSAndroid Build Coastguard Worker
279*2f2c4c7aSAndroid Build Coastguard Workerclass XfrmAddDeleteVtiTest(xfrm_base.XfrmBaseTest):
280*2f2c4c7aSAndroid Build Coastguard Worker  def _VerifyVtiInfoData(self, vti_info_data, version, local_addr, remote_addr,
281*2f2c4c7aSAndroid Build Coastguard Worker                         ikey, okey):
282*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(vti_info_data["IFLA_VTI_IKEY"], ikey)
283*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(vti_info_data["IFLA_VTI_OKEY"], okey)
284*2f2c4c7aSAndroid Build Coastguard Worker
285*2f2c4c7aSAndroid Build Coastguard Worker    family = AF_INET if version == 4 else AF_INET6
286*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(inet_ntop(family, vti_info_data["IFLA_VTI_LOCAL"]),
287*2f2c4c7aSAndroid Build Coastguard Worker                      local_addr)
288*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(inet_ntop(family, vti_info_data["IFLA_VTI_REMOTE"]),
289*2f2c4c7aSAndroid Build Coastguard Worker                      remote_addr)
290*2f2c4c7aSAndroid Build Coastguard Worker
291*2f2c4c7aSAndroid Build Coastguard Worker  def testAddVti(self):
292*2f2c4c7aSAndroid Build Coastguard Worker    """Test the creation of a Virtual Tunnel Interface."""
293*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 6]:
294*2f2c4c7aSAndroid Build Coastguard Worker      netid = self.RandomNetid()
295*2f2c4c7aSAndroid Build Coastguard Worker      local_addr = self.MyAddress(version, netid)
296*2f2c4c7aSAndroid Build Coastguard Worker      self.iproute.CreateVirtualTunnelInterface(
297*2f2c4c7aSAndroid Build Coastguard Worker          dev_name=_TEST_XFRM_IFNAME,
298*2f2c4c7aSAndroid Build Coastguard Worker          local_addr=local_addr,
299*2f2c4c7aSAndroid Build Coastguard Worker          remote_addr=_GetRemoteOuterAddress(version),
300*2f2c4c7aSAndroid Build Coastguard Worker          o_key=_TEST_OKEY,
301*2f2c4c7aSAndroid Build Coastguard Worker          i_key=_TEST_IKEY)
302*2f2c4c7aSAndroid Build Coastguard Worker      self._VerifyVtiInfoData(
303*2f2c4c7aSAndroid Build Coastguard Worker          self.iproute.GetIfinfoData(_TEST_XFRM_IFNAME), version, local_addr,
304*2f2c4c7aSAndroid Build Coastguard Worker          _GetRemoteOuterAddress(version), _TEST_IKEY, _TEST_OKEY)
305*2f2c4c7aSAndroid Build Coastguard Worker
306*2f2c4c7aSAndroid Build Coastguard Worker      new_remote_addr = {4: net_test.IPV4_ADDR2, 6: net_test.IPV6_ADDR2}
307*2f2c4c7aSAndroid Build Coastguard Worker      new_okey = _TEST_OKEY + _TEST_XFRM_IF_ID
308*2f2c4c7aSAndroid Build Coastguard Worker      new_ikey = _TEST_IKEY + _TEST_XFRM_IF_ID
309*2f2c4c7aSAndroid Build Coastguard Worker      self.iproute.CreateVirtualTunnelInterface(
310*2f2c4c7aSAndroid Build Coastguard Worker          dev_name=_TEST_XFRM_IFNAME,
311*2f2c4c7aSAndroid Build Coastguard Worker          local_addr=local_addr,
312*2f2c4c7aSAndroid Build Coastguard Worker          remote_addr=new_remote_addr[version],
313*2f2c4c7aSAndroid Build Coastguard Worker          o_key=new_okey,
314*2f2c4c7aSAndroid Build Coastguard Worker          i_key=new_ikey,
315*2f2c4c7aSAndroid Build Coastguard Worker          is_update=True)
316*2f2c4c7aSAndroid Build Coastguard Worker
317*2f2c4c7aSAndroid Build Coastguard Worker      self._VerifyVtiInfoData(
318*2f2c4c7aSAndroid Build Coastguard Worker          self.iproute.GetIfinfoData(_TEST_XFRM_IFNAME), version, local_addr,
319*2f2c4c7aSAndroid Build Coastguard Worker          new_remote_addr[version], new_ikey, new_okey)
320*2f2c4c7aSAndroid Build Coastguard Worker
321*2f2c4c7aSAndroid Build Coastguard Worker      if_index = self.iproute.GetIfIndex(_TEST_XFRM_IFNAME)
322*2f2c4c7aSAndroid Build Coastguard Worker
323*2f2c4c7aSAndroid Build Coastguard Worker      # Validate that the netlink interface matches the ioctl interface.
324*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(net_test.GetInterfaceIndex(_TEST_XFRM_IFNAME), if_index)
325*2f2c4c7aSAndroid Build Coastguard Worker      self.iproute.DeleteLink(_TEST_XFRM_IFNAME)
326*2f2c4c7aSAndroid Build Coastguard Worker      with self.assertRaises(IOError):
327*2f2c4c7aSAndroid Build Coastguard Worker        self.iproute.GetIfIndex(_TEST_XFRM_IFNAME)
328*2f2c4c7aSAndroid Build Coastguard Worker
329*2f2c4c7aSAndroid Build Coastguard Worker  def _QuietDeleteLink(self, ifname):
330*2f2c4c7aSAndroid Build Coastguard Worker    try:
331*2f2c4c7aSAndroid Build Coastguard Worker      self.iproute.DeleteLink(ifname)
332*2f2c4c7aSAndroid Build Coastguard Worker    except IOError:
333*2f2c4c7aSAndroid Build Coastguard Worker      # The link was not present.
334*2f2c4c7aSAndroid Build Coastguard Worker      pass
335*2f2c4c7aSAndroid Build Coastguard Worker
336*2f2c4c7aSAndroid Build Coastguard Worker  def tearDown(self):
337*2f2c4c7aSAndroid Build Coastguard Worker    super(XfrmAddDeleteVtiTest, self).tearDown()
338*2f2c4c7aSAndroid Build Coastguard Worker    self._QuietDeleteLink(_TEST_XFRM_IFNAME)
339*2f2c4c7aSAndroid Build Coastguard Worker
340*2f2c4c7aSAndroid Build Coastguard Worker
341*2f2c4c7aSAndroid Build Coastguard Workerclass SaInfo(object):
342*2f2c4c7aSAndroid Build Coastguard Worker
343*2f2c4c7aSAndroid Build Coastguard Worker  def __init__(self, spi):
344*2f2c4c7aSAndroid Build Coastguard Worker    self.spi = spi
345*2f2c4c7aSAndroid Build Coastguard Worker    self.seq_num = 1
346*2f2c4c7aSAndroid Build Coastguard Worker
347*2f2c4c7aSAndroid Build Coastguard Worker
348*2f2c4c7aSAndroid Build Coastguard Workerclass IpSecBaseInterface(object):
349*2f2c4c7aSAndroid Build Coastguard Worker
350*2f2c4c7aSAndroid Build Coastguard Worker  def __init__(self, iface, netid, underlying_netid, local, remote, version):
351*2f2c4c7aSAndroid Build Coastguard Worker    self.iface = iface
352*2f2c4c7aSAndroid Build Coastguard Worker    self.netid = netid
353*2f2c4c7aSAndroid Build Coastguard Worker    self.underlying_netid = underlying_netid
354*2f2c4c7aSAndroid Build Coastguard Worker    self.local, self.remote = local, remote
355*2f2c4c7aSAndroid Build Coastguard Worker
356*2f2c4c7aSAndroid Build Coastguard Worker    # XFRM interfaces technically do not have a version. This keeps track of
357*2f2c4c7aSAndroid Build Coastguard Worker    # the IP version of the local and remote addresses.
358*2f2c4c7aSAndroid Build Coastguard Worker    self.version = version
359*2f2c4c7aSAndroid Build Coastguard Worker    self.rx = self.tx = 0
360*2f2c4c7aSAndroid Build Coastguard Worker    self.addrs = {}
361*2f2c4c7aSAndroid Build Coastguard Worker
362*2f2c4c7aSAndroid Build Coastguard Worker    self.iproute = iproute.IPRoute()
363*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm = xfrm.Xfrm()
364*2f2c4c7aSAndroid Build Coastguard Worker
365*2f2c4c7aSAndroid Build Coastguard Worker  def Teardown(self):
366*2f2c4c7aSAndroid Build Coastguard Worker    self.TeardownXfrm()
367*2f2c4c7aSAndroid Build Coastguard Worker    self.TeardownInterface()
368*2f2c4c7aSAndroid Build Coastguard Worker
369*2f2c4c7aSAndroid Build Coastguard Worker  def TeardownInterface(self):
370*2f2c4c7aSAndroid Build Coastguard Worker    self.iproute.DeleteLink(self.iface)
371*2f2c4c7aSAndroid Build Coastguard Worker
372*2f2c4c7aSAndroid Build Coastguard Worker  def SetupXfrm(self, use_null_crypt):
373*2f2c4c7aSAndroid Build Coastguard Worker    rand_spi = random.randint(0, 0x7fffffff)
374*2f2c4c7aSAndroid Build Coastguard Worker    self.in_sa = SaInfo(rand_spi)
375*2f2c4c7aSAndroid Build Coastguard Worker    self.out_sa = SaInfo(rand_spi)
376*2f2c4c7aSAndroid Build Coastguard Worker
377*2f2c4c7aSAndroid Build Coastguard Worker    # Select algorithms:
378*2f2c4c7aSAndroid Build Coastguard Worker    if use_null_crypt:
379*2f2c4c7aSAndroid Build Coastguard Worker      auth, crypt = xfrm_base._ALGO_AUTH_NULL, xfrm_base._ALGO_CRYPT_NULL
380*2f2c4c7aSAndroid Build Coastguard Worker    else:
381*2f2c4c7aSAndroid Build Coastguard Worker      auth, crypt = xfrm_base._ALGO_HMAC_SHA1, xfrm_base._ALGO_CBC_AES_256
382*2f2c4c7aSAndroid Build Coastguard Worker
383*2f2c4c7aSAndroid Build Coastguard Worker    self.auth = auth
384*2f2c4c7aSAndroid Build Coastguard Worker    self.crypt = crypt
385*2f2c4c7aSAndroid Build Coastguard Worker
386*2f2c4c7aSAndroid Build Coastguard Worker    self._SetupXfrmByType(auth, crypt)
387*2f2c4c7aSAndroid Build Coastguard Worker
388*2f2c4c7aSAndroid Build Coastguard Worker  def Rekey(self, outer_family, new_out_sa, new_in_sa):
389*2f2c4c7aSAndroid Build Coastguard Worker    """Rekeys the Tunnel Interface
390*2f2c4c7aSAndroid Build Coastguard Worker
391*2f2c4c7aSAndroid Build Coastguard Worker    Creates new SAs and updates the outbound security policy to use new SAs.
392*2f2c4c7aSAndroid Build Coastguard Worker
393*2f2c4c7aSAndroid Build Coastguard Worker    Args:
394*2f2c4c7aSAndroid Build Coastguard Worker      outer_family: AF_INET or AF_INET6
395*2f2c4c7aSAndroid Build Coastguard Worker      new_out_sa: An SaInfo struct representing the new outbound SA's info
396*2f2c4c7aSAndroid Build Coastguard Worker      new_in_sa: An SaInfo struct representing the new inbound SA's info
397*2f2c4c7aSAndroid Build Coastguard Worker    """
398*2f2c4c7aSAndroid Build Coastguard Worker    self._Rekey(outer_family, new_out_sa, new_in_sa)
399*2f2c4c7aSAndroid Build Coastguard Worker
400*2f2c4c7aSAndroid Build Coastguard Worker    # Update Interface object
401*2f2c4c7aSAndroid Build Coastguard Worker    self.out_sa = new_out_sa
402*2f2c4c7aSAndroid Build Coastguard Worker    self.in_sa = new_in_sa
403*2f2c4c7aSAndroid Build Coastguard Worker
404*2f2c4c7aSAndroid Build Coastguard Worker  def TeardownXfrm(self):
405*2f2c4c7aSAndroid Build Coastguard Worker    raise NotImplementedError("Subclasses should implement this")
406*2f2c4c7aSAndroid Build Coastguard Worker
407*2f2c4c7aSAndroid Build Coastguard Worker  def _SetupXfrmByType(self, auth_algo, crypt_algo):
408*2f2c4c7aSAndroid Build Coastguard Worker    raise NotImplementedError("Subclasses should implement this")
409*2f2c4c7aSAndroid Build Coastguard Worker
410*2f2c4c7aSAndroid Build Coastguard Worker  def _Rekey(self, outer_family, new_out_sa, new_in_sa):
411*2f2c4c7aSAndroid Build Coastguard Worker    raise NotImplementedError("Subclasses should implement this")
412*2f2c4c7aSAndroid Build Coastguard Worker
413*2f2c4c7aSAndroid Build Coastguard Worker
414*2f2c4c7aSAndroid Build Coastguard Workerclass VtiInterface(IpSecBaseInterface):
415*2f2c4c7aSAndroid Build Coastguard Worker
416*2f2c4c7aSAndroid Build Coastguard Worker  def __init__(self, iface, netid, underlying_netid, _, local, remote, version):
417*2f2c4c7aSAndroid Build Coastguard Worker    super(VtiInterface, self).__init__(iface, netid, underlying_netid, local,
418*2f2c4c7aSAndroid Build Coastguard Worker                                       remote, version)
419*2f2c4c7aSAndroid Build Coastguard Worker
420*2f2c4c7aSAndroid Build Coastguard Worker    self.ikey = _TEST_IKEY + netid
421*2f2c4c7aSAndroid Build Coastguard Worker    self.okey = _TEST_OKEY + netid
422*2f2c4c7aSAndroid Build Coastguard Worker
423*2f2c4c7aSAndroid Build Coastguard Worker    self.SetupInterface()
424*2f2c4c7aSAndroid Build Coastguard Worker    self.SetupXfrm(False)
425*2f2c4c7aSAndroid Build Coastguard Worker
426*2f2c4c7aSAndroid Build Coastguard Worker  def SetupInterface(self):
427*2f2c4c7aSAndroid Build Coastguard Worker    return self.iproute.CreateVirtualTunnelInterface(
428*2f2c4c7aSAndroid Build Coastguard Worker        self.iface, self.local, self.remote, self.ikey, self.okey)
429*2f2c4c7aSAndroid Build Coastguard Worker
430*2f2c4c7aSAndroid Build Coastguard Worker  def _SetupXfrmByType(self, auth_algo, crypt_algo):
431*2f2c4c7aSAndroid Build Coastguard Worker    # For the VTI, the selectors are wildcard since packets will only
432*2f2c4c7aSAndroid Build Coastguard Worker    # be selected if they have the appropriate mark, hence the inner
433*2f2c4c7aSAndroid Build Coastguard Worker    # addresses are wildcard.
434*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.CreateTunnel(xfrm.XFRM_POLICY_OUT, None, self.local, self.remote,
435*2f2c4c7aSAndroid Build Coastguard Worker                           self.out_sa.spi, crypt_algo, auth_algo,
436*2f2c4c7aSAndroid Build Coastguard Worker                           xfrm.ExactMatchMark(self.okey),
437*2f2c4c7aSAndroid Build Coastguard Worker                           self.underlying_netid, None, xfrm.MATCH_METHOD_ALL)
438*2f2c4c7aSAndroid Build Coastguard Worker
439*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.CreateTunnel(xfrm.XFRM_POLICY_IN, None, self.remote, self.local,
440*2f2c4c7aSAndroid Build Coastguard Worker                           self.in_sa.spi, crypt_algo, auth_algo,
441*2f2c4c7aSAndroid Build Coastguard Worker                           xfrm.ExactMatchMark(self.ikey), None, None,
442*2f2c4c7aSAndroid Build Coastguard Worker                           xfrm.MATCH_METHOD_MARK)
443*2f2c4c7aSAndroid Build Coastguard Worker
444*2f2c4c7aSAndroid Build Coastguard Worker  def TeardownXfrm(self):
445*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeleteTunnel(xfrm.XFRM_POLICY_OUT, None, self.remote,
446*2f2c4c7aSAndroid Build Coastguard Worker                           self.out_sa.spi, self.okey, None)
447*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeleteTunnel(xfrm.XFRM_POLICY_IN, None, self.local,
448*2f2c4c7aSAndroid Build Coastguard Worker                           self.in_sa.spi, self.ikey, None)
449*2f2c4c7aSAndroid Build Coastguard Worker
450*2f2c4c7aSAndroid Build Coastguard Worker  def _Rekey(self, outer_family, new_out_sa, new_in_sa):
451*2f2c4c7aSAndroid Build Coastguard Worker    # TODO: Consider ways to share code with xfrm.CreateTunnel(). It's mostly
452*2f2c4c7aSAndroid Build Coastguard Worker    #       the same, but rekeys are asymmetric, and only update the outbound
453*2f2c4c7aSAndroid Build Coastguard Worker    #       policy.
454*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddSaInfo(self.local, self.remote, new_out_sa.spi,
455*2f2c4c7aSAndroid Build Coastguard Worker                        xfrm.XFRM_MODE_TUNNEL, 0, xfrm_base._ALGO_CRYPT_NULL,
456*2f2c4c7aSAndroid Build Coastguard Worker                        xfrm_base._ALGO_AUTH_NULL, None, None,
457*2f2c4c7aSAndroid Build Coastguard Worker                        xfrm.ExactMatchMark(self.okey), self.underlying_netid)
458*2f2c4c7aSAndroid Build Coastguard Worker
459*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddSaInfo(self.remote, self.local, new_in_sa.spi,
460*2f2c4c7aSAndroid Build Coastguard Worker                        xfrm.XFRM_MODE_TUNNEL, 0, xfrm_base._ALGO_CRYPT_NULL,
461*2f2c4c7aSAndroid Build Coastguard Worker                        xfrm_base._ALGO_AUTH_NULL, None, None,
462*2f2c4c7aSAndroid Build Coastguard Worker                        xfrm.ExactMatchMark(self.ikey), None)
463*2f2c4c7aSAndroid Build Coastguard Worker
464*2f2c4c7aSAndroid Build Coastguard Worker    # Create new policies for IPv4 and IPv6.
465*2f2c4c7aSAndroid Build Coastguard Worker    for sel in [xfrm.EmptySelector(AF_INET), xfrm.EmptySelector(AF_INET6)]:
466*2f2c4c7aSAndroid Build Coastguard Worker      # Add SPI-specific output policy to enforce using new outbound SPI
467*2f2c4c7aSAndroid Build Coastguard Worker      policy = xfrm.UserPolicy(xfrm.XFRM_POLICY_OUT, sel)
468*2f2c4c7aSAndroid Build Coastguard Worker      tmpl = xfrm.UserTemplate(outer_family, new_out_sa.spi, 0,
469*2f2c4c7aSAndroid Build Coastguard Worker                                    (self.local, self.remote))
470*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.UpdatePolicyInfo(policy, tmpl, xfrm.ExactMatchMark(self.okey),
471*2f2c4c7aSAndroid Build Coastguard Worker                                 0)
472*2f2c4c7aSAndroid Build Coastguard Worker
473*2f2c4c7aSAndroid Build Coastguard Worker  def DeleteOldSaInfo(self, outer_family, old_in_spi, old_out_spi):
474*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeleteSaInfo(self.local, old_in_spi, IPPROTO_ESP,
475*2f2c4c7aSAndroid Build Coastguard Worker                           xfrm.ExactMatchMark(self.ikey))
476*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeleteSaInfo(self.remote, old_out_spi, IPPROTO_ESP,
477*2f2c4c7aSAndroid Build Coastguard Worker                           xfrm.ExactMatchMark(self.okey))
478*2f2c4c7aSAndroid Build Coastguard Worker
479*2f2c4c7aSAndroid Build Coastguard Worker
480*2f2c4c7aSAndroid Build Coastguard Workerclass XfrmAddDeleteXfrmInterfaceTest(xfrm_base.XfrmBaseTest):
481*2f2c4c7aSAndroid Build Coastguard Worker  """Test the creation of an XFRM Interface."""
482*2f2c4c7aSAndroid Build Coastguard Worker
483*2f2c4c7aSAndroid Build Coastguard Worker  def testAddXfrmInterface(self):
484*2f2c4c7aSAndroid Build Coastguard Worker    self.iproute.CreateXfrmInterface(_TEST_XFRM_IFNAME, _TEST_XFRM_IF_ID,
485*2f2c4c7aSAndroid Build Coastguard Worker                                     _LOOPBACK_IFINDEX)
486*2f2c4c7aSAndroid Build Coastguard Worker    if_index = self.iproute.GetIfIndex(_TEST_XFRM_IFNAME)
487*2f2c4c7aSAndroid Build Coastguard Worker    net_test.SetInterfaceUp(_TEST_XFRM_IFNAME)
488*2f2c4c7aSAndroid Build Coastguard Worker
489*2f2c4c7aSAndroid Build Coastguard Worker    # Validate that the netlink interface matches the ioctl interface.
490*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(net_test.GetInterfaceIndex(_TEST_XFRM_IFNAME), if_index)
491*2f2c4c7aSAndroid Build Coastguard Worker    self.iproute.DeleteLink(_TEST_XFRM_IFNAME)
492*2f2c4c7aSAndroid Build Coastguard Worker    with self.assertRaises(IOError):
493*2f2c4c7aSAndroid Build Coastguard Worker      self.iproute.GetIfIndex(_TEST_XFRM_IFNAME)
494*2f2c4c7aSAndroid Build Coastguard Worker
495*2f2c4c7aSAndroid Build Coastguard Worker
496*2f2c4c7aSAndroid Build Coastguard Workerclass XfrmInterface(IpSecBaseInterface):
497*2f2c4c7aSAndroid Build Coastguard Worker
498*2f2c4c7aSAndroid Build Coastguard Worker  def __init__(self, iface, netid, underlying_netid, ifindex, local, remote,
499*2f2c4c7aSAndroid Build Coastguard Worker               version, use_null_crypt=False):
500*2f2c4c7aSAndroid Build Coastguard Worker    super(XfrmInterface, self).__init__(iface, netid, underlying_netid, local,
501*2f2c4c7aSAndroid Build Coastguard Worker                                        remote, version)
502*2f2c4c7aSAndroid Build Coastguard Worker
503*2f2c4c7aSAndroid Build Coastguard Worker    self.ifindex = ifindex
504*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm_if_id = netid
505*2f2c4c7aSAndroid Build Coastguard Worker
506*2f2c4c7aSAndroid Build Coastguard Worker    self.SetupInterface()
507*2f2c4c7aSAndroid Build Coastguard Worker    self.SetupXfrm(use_null_crypt)
508*2f2c4c7aSAndroid Build Coastguard Worker
509*2f2c4c7aSAndroid Build Coastguard Worker  def SetupInterface(self):
510*2f2c4c7aSAndroid Build Coastguard Worker    """Create an XFRM interface."""
511*2f2c4c7aSAndroid Build Coastguard Worker    return self.iproute.CreateXfrmInterface(self.iface, self.netid, self.ifindex)
512*2f2c4c7aSAndroid Build Coastguard Worker
513*2f2c4c7aSAndroid Build Coastguard Worker  def _SetupXfrmByType(self, auth_algo, crypt_algo):
514*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.CreateTunnel(xfrm.XFRM_POLICY_OUT, None, self.local, self.remote,
515*2f2c4c7aSAndroid Build Coastguard Worker                           self.out_sa.spi, crypt_algo, auth_algo, None,
516*2f2c4c7aSAndroid Build Coastguard Worker                           self.underlying_netid, self.xfrm_if_id,
517*2f2c4c7aSAndroid Build Coastguard Worker                           xfrm.MATCH_METHOD_ALL)
518*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.CreateTunnel(xfrm.XFRM_POLICY_IN, None, self.remote, self.local,
519*2f2c4c7aSAndroid Build Coastguard Worker                           self.in_sa.spi, crypt_algo, auth_algo, None, None,
520*2f2c4c7aSAndroid Build Coastguard Worker                           self.xfrm_if_id, xfrm.MATCH_METHOD_IFID)
521*2f2c4c7aSAndroid Build Coastguard Worker
522*2f2c4c7aSAndroid Build Coastguard Worker  def TeardownXfrm(self):
523*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeleteTunnel(xfrm.XFRM_POLICY_OUT, None, self.remote,
524*2f2c4c7aSAndroid Build Coastguard Worker                           self.out_sa.spi, None, self.xfrm_if_id)
525*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeleteTunnel(xfrm.XFRM_POLICY_IN, None, self.local,
526*2f2c4c7aSAndroid Build Coastguard Worker                           self.in_sa.spi, None, self.xfrm_if_id)
527*2f2c4c7aSAndroid Build Coastguard Worker
528*2f2c4c7aSAndroid Build Coastguard Worker  def _Rekey(self, outer_family, new_out_sa, new_in_sa):
529*2f2c4c7aSAndroid Build Coastguard Worker    # TODO: Consider ways to share code with xfrm.CreateTunnel(). It's mostly
530*2f2c4c7aSAndroid Build Coastguard Worker    #       the same, but rekeys are asymmetric, and only update the outbound
531*2f2c4c7aSAndroid Build Coastguard Worker    #       policy.
532*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddSaInfo(
533*2f2c4c7aSAndroid Build Coastguard Worker        self.local, self.remote, new_out_sa.spi, xfrm.XFRM_MODE_TUNNEL, 0,
534*2f2c4c7aSAndroid Build Coastguard Worker        xfrm_base._ALGO_CRYPT_NULL, xfrm_base._ALGO_AUTH_NULL, None, None,
535*2f2c4c7aSAndroid Build Coastguard Worker        None, self.underlying_netid, xfrm_if_id=self.xfrm_if_id)
536*2f2c4c7aSAndroid Build Coastguard Worker
537*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddSaInfo(
538*2f2c4c7aSAndroid Build Coastguard Worker        self.remote, self.local, new_in_sa.spi, xfrm.XFRM_MODE_TUNNEL, 0,
539*2f2c4c7aSAndroid Build Coastguard Worker        xfrm_base._ALGO_CRYPT_NULL, xfrm_base._ALGO_AUTH_NULL, None, None,
540*2f2c4c7aSAndroid Build Coastguard Worker        None, None, xfrm_if_id=self.xfrm_if_id)
541*2f2c4c7aSAndroid Build Coastguard Worker
542*2f2c4c7aSAndroid Build Coastguard Worker    # Create new policies for IPv4 and IPv6.
543*2f2c4c7aSAndroid Build Coastguard Worker    for sel in [xfrm.EmptySelector(AF_INET), xfrm.EmptySelector(AF_INET6)]:
544*2f2c4c7aSAndroid Build Coastguard Worker      # Add SPI-specific output policy to enforce using new outbound SPI
545*2f2c4c7aSAndroid Build Coastguard Worker      policy = xfrm.UserPolicy(xfrm.XFRM_POLICY_OUT, sel)
546*2f2c4c7aSAndroid Build Coastguard Worker      tmpl = xfrm.UserTemplate(outer_family, new_out_sa.spi, 0,
547*2f2c4c7aSAndroid Build Coastguard Worker                                    (self.local, self.remote))
548*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.UpdatePolicyInfo(policy, tmpl, None, self.xfrm_if_id)
549*2f2c4c7aSAndroid Build Coastguard Worker
550*2f2c4c7aSAndroid Build Coastguard Worker  def DeleteOldSaInfo(self, outer_family, old_in_spi, old_out_spi):
551*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeleteSaInfo(self.local, old_in_spi, IPPROTO_ESP, None,
552*2f2c4c7aSAndroid Build Coastguard Worker                           self.xfrm_if_id)
553*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeleteSaInfo(self.remote, old_out_spi, IPPROTO_ESP, None,
554*2f2c4c7aSAndroid Build Coastguard Worker                           self.xfrm_if_id)
555*2f2c4c7aSAndroid Build Coastguard Worker
556*2f2c4c7aSAndroid Build Coastguard Worker  def Migrate(self, new_underlying_netid, new_local, new_remote):
557*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.MigrateTunnel(xfrm.XFRM_POLICY_IN, None, self.remote, self.local,
558*2f2c4c7aSAndroid Build Coastguard Worker                            new_remote, new_local, self.in_sa.spi,
559*2f2c4c7aSAndroid Build Coastguard Worker                            self.crypt, self.auth, None, None,
560*2f2c4c7aSAndroid Build Coastguard Worker                            new_underlying_netid, self.xfrm_if_id)
561*2f2c4c7aSAndroid Build Coastguard Worker
562*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.MigrateTunnel(xfrm.XFRM_POLICY_OUT, None, self.local, self.remote,
563*2f2c4c7aSAndroid Build Coastguard Worker                            new_local, new_remote, self.out_sa.spi,
564*2f2c4c7aSAndroid Build Coastguard Worker                            self.crypt, self.auth, None, None,
565*2f2c4c7aSAndroid Build Coastguard Worker                            new_underlying_netid, self.xfrm_if_id)
566*2f2c4c7aSAndroid Build Coastguard Worker
567*2f2c4c7aSAndroid Build Coastguard Worker    self.local = new_local
568*2f2c4c7aSAndroid Build Coastguard Worker    self.remote = new_remote
569*2f2c4c7aSAndroid Build Coastguard Worker    self.version = net_test.GetAddressVersion(new_local)
570*2f2c4c7aSAndroid Build Coastguard Worker    self.underlying_netid = new_underlying_netid
571*2f2c4c7aSAndroid Build Coastguard Worker
572*2f2c4c7aSAndroid Build Coastguard Worker
573*2f2c4c7aSAndroid Build Coastguard Workerclass XfrmTunnelBase(xfrm_base.XfrmBaseTest):
574*2f2c4c7aSAndroid Build Coastguard Worker
575*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
576*2f2c4c7aSAndroid Build Coastguard Worker  def setUpClass(cls):
577*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.XfrmBaseTest.setUpClass()
578*2f2c4c7aSAndroid Build Coastguard Worker    # Tunnel interfaces use marks extensively, so configure realistic packet
579*2f2c4c7aSAndroid Build Coastguard Worker    # marking rules to make the test representative, make PMTUD work, etc.
580*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetInboundMarks(True)
581*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetMarkReflectSysctls(1)
582*2f2c4c7aSAndroid Build Coastguard Worker
583*2f2c4c7aSAndroid Build Coastguard Worker    # Group by tunnel version to ensure that we test at least one IPv4 and one
584*2f2c4c7aSAndroid Build Coastguard Worker    # IPv6 tunnel
585*2f2c4c7aSAndroid Build Coastguard Worker    cls.tunnelsV4 = {}
586*2f2c4c7aSAndroid Build Coastguard Worker    cls.tunnelsV6 = {}
587*2f2c4c7aSAndroid Build Coastguard Worker
588*2f2c4c7aSAndroid Build Coastguard Worker    for i, underlying_netid in enumerate(cls.tuns):
589*2f2c4c7aSAndroid Build Coastguard Worker      for version in 4, 6:
590*2f2c4c7aSAndroid Build Coastguard Worker        netid = _BASE_TUNNEL_NETID[version] + _TUNNEL_NETID_OFFSET + i
591*2f2c4c7aSAndroid Build Coastguard Worker        iface = "ipsec%s" % netid
592*2f2c4c7aSAndroid Build Coastguard Worker        local = cls.MyAddress(version, underlying_netid)
593*2f2c4c7aSAndroid Build Coastguard Worker        if version == 4:
594*2f2c4c7aSAndroid Build Coastguard Worker          remote = (net_test.IPV4_ADDR if (i % 2) else net_test.IPV4_ADDR2)
595*2f2c4c7aSAndroid Build Coastguard Worker        else:
596*2f2c4c7aSAndroid Build Coastguard Worker          remote = (net_test.IPV6_ADDR if (i % 2) else net_test.IPV6_ADDR2)
597*2f2c4c7aSAndroid Build Coastguard Worker
598*2f2c4c7aSAndroid Build Coastguard Worker        ifindex = cls.ifindices[underlying_netid]
599*2f2c4c7aSAndroid Build Coastguard Worker        tunnel = cls.INTERFACE_CLASS(iface, netid, underlying_netid, ifindex,
600*2f2c4c7aSAndroid Build Coastguard Worker                                   local, remote, version)
601*2f2c4c7aSAndroid Build Coastguard Worker        cls._SetInboundMarking(netid, iface, True)
602*2f2c4c7aSAndroid Build Coastguard Worker        cls._SetupTunnelNetwork(tunnel, True)
603*2f2c4c7aSAndroid Build Coastguard Worker
604*2f2c4c7aSAndroid Build Coastguard Worker        if version == 4:
605*2f2c4c7aSAndroid Build Coastguard Worker          cls.tunnelsV4[netid] = tunnel
606*2f2c4c7aSAndroid Build Coastguard Worker        else:
607*2f2c4c7aSAndroid Build Coastguard Worker          cls.tunnelsV6[netid] = tunnel
608*2f2c4c7aSAndroid Build Coastguard Worker
609*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
610*2f2c4c7aSAndroid Build Coastguard Worker  def tearDownClass(cls):
611*2f2c4c7aSAndroid Build Coastguard Worker    # The sysctls are restored by MultinetworkBaseTest.tearDownClass.
612*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetInboundMarks(False)
613*2f2c4c7aSAndroid Build Coastguard Worker    for tunnel in list(cls.tunnelsV4.values()) + list(cls.tunnelsV6.values()):
614*2f2c4c7aSAndroid Build Coastguard Worker      cls._SetInboundMarking(tunnel.netid, tunnel.iface, False)
615*2f2c4c7aSAndroid Build Coastguard Worker      cls._SetupTunnelNetwork(tunnel, False)
616*2f2c4c7aSAndroid Build Coastguard Worker      tunnel.Teardown()
617*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.XfrmBaseTest.tearDownClass()
618*2f2c4c7aSAndroid Build Coastguard Worker
619*2f2c4c7aSAndroid Build Coastguard Worker  def randomTunnel(self, outer_version):
620*2f2c4c7aSAndroid Build Coastguard Worker    version_dict = self.tunnelsV4 if outer_version == 4 else self.tunnelsV6
621*2f2c4c7aSAndroid Build Coastguard Worker    return random.choice(list(version_dict.values()))
622*2f2c4c7aSAndroid Build Coastguard Worker
623*2f2c4c7aSAndroid Build Coastguard Worker  def setUp(self):
624*2f2c4c7aSAndroid Build Coastguard Worker    multinetwork_base.MultiNetworkBaseTest.setUp(self)
625*2f2c4c7aSAndroid Build Coastguard Worker    self.iproute = iproute.IPRoute()
626*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm = xfrm.Xfrm()
627*2f2c4c7aSAndroid Build Coastguard Worker
628*2f2c4c7aSAndroid Build Coastguard Worker  def tearDown(self):
629*2f2c4c7aSAndroid Build Coastguard Worker    multinetwork_base.MultiNetworkBaseTest.tearDown(self)
630*2f2c4c7aSAndroid Build Coastguard Worker
631*2f2c4c7aSAndroid Build Coastguard Worker  def _SwapInterfaceAddress(self, ifname, old_addr, new_addr):
632*2f2c4c7aSAndroid Build Coastguard Worker    """Exchange two addresses on a given interface.
633*2f2c4c7aSAndroid Build Coastguard Worker
634*2f2c4c7aSAndroid Build Coastguard Worker    Args:
635*2f2c4c7aSAndroid Build Coastguard Worker      ifname: Name of the interface
636*2f2c4c7aSAndroid Build Coastguard Worker      old_addr: An address to be removed from the interface
637*2f2c4c7aSAndroid Build Coastguard Worker      new_addr: An address to be added to an interface
638*2f2c4c7aSAndroid Build Coastguard Worker    """
639*2f2c4c7aSAndroid Build Coastguard Worker    version = 6 if ":" in new_addr else 4
640*2f2c4c7aSAndroid Build Coastguard Worker    ifindex = net_test.GetInterfaceIndex(ifname)
641*2f2c4c7aSAndroid Build Coastguard Worker    self.iproute.AddAddress(new_addr,
642*2f2c4c7aSAndroid Build Coastguard Worker                            net_test.AddressLengthBits(version), ifindex)
643*2f2c4c7aSAndroid Build Coastguard Worker    self.iproute.DelAddress(old_addr,
644*2f2c4c7aSAndroid Build Coastguard Worker                            net_test.AddressLengthBits(version), ifindex)
645*2f2c4c7aSAndroid Build Coastguard Worker
646*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
647*2f2c4c7aSAndroid Build Coastguard Worker  def _GetLocalAddress(cls, version, netid):
648*2f2c4c7aSAndroid Build Coastguard Worker    if version == 4:
649*2f2c4c7aSAndroid Build Coastguard Worker      return cls._MyIPv4Address(netid - _TUNNEL_NETID_OFFSET)
650*2f2c4c7aSAndroid Build Coastguard Worker    else:
651*2f2c4c7aSAndroid Build Coastguard Worker      return cls.OnlinkPrefix(6, netid - _TUNNEL_NETID_OFFSET) + "1"
652*2f2c4c7aSAndroid Build Coastguard Worker
653*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
654*2f2c4c7aSAndroid Build Coastguard Worker  def UidRangeForTunnelNetId(cls, netid):
655*2f2c4c7aSAndroid Build Coastguard Worker    if netid < _TUNNEL_NETID_OFFSET:
656*2f2c4c7aSAndroid Build Coastguard Worker      raise ValueError("Tunnel netid outside tunnel range")
657*2f2c4c7aSAndroid Build Coastguard Worker    netid -= _TUNNEL_NETID_OFFSET
658*2f2c4c7aSAndroid Build Coastguard Worker    return (500 + 50 * netid, 500 + 50 * (netid + 1) - 1)
659*2f2c4c7aSAndroid Build Coastguard Worker
660*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
661*2f2c4c7aSAndroid Build Coastguard Worker  def _SetupTunnelNetwork(cls, tunnel, is_add):
662*2f2c4c7aSAndroid Build Coastguard Worker    """Setup rules and routes for a tunnel Network.
663*2f2c4c7aSAndroid Build Coastguard Worker
664*2f2c4c7aSAndroid Build Coastguard Worker    Takes an interface and depending on the boolean
665*2f2c4c7aSAndroid Build Coastguard Worker    value of is_add, either adds or removes the rules
666*2f2c4c7aSAndroid Build Coastguard Worker    and routes for a tunnel interface to behave like an
667*2f2c4c7aSAndroid Build Coastguard Worker    Android Network for purposes of testing.
668*2f2c4c7aSAndroid Build Coastguard Worker
669*2f2c4c7aSAndroid Build Coastguard Worker    Args:
670*2f2c4c7aSAndroid Build Coastguard Worker      tunnel: A VtiInterface or XfrmInterface, the tunnel to set up.
671*2f2c4c7aSAndroid Build Coastguard Worker      is_add: Boolean that causes this method to perform setup if True or
672*2f2c4c7aSAndroid Build Coastguard Worker        teardown if False
673*2f2c4c7aSAndroid Build Coastguard Worker    """
674*2f2c4c7aSAndroid Build Coastguard Worker    if is_add:
675*2f2c4c7aSAndroid Build Coastguard Worker      # Disable router solicitations to avoid occasional spurious packets
676*2f2c4c7aSAndroid Build Coastguard Worker      # arriving on the underlying network; there are two possible behaviors
677*2f2c4c7aSAndroid Build Coastguard Worker      # when that occurred: either only the RA packet is read, and when it
678*2f2c4c7aSAndroid Build Coastguard Worker      # is echoed back to the tunnel, it causes the test to fail by not
679*2f2c4c7aSAndroid Build Coastguard Worker      # receiving # the UDP_PAYLOAD; or, two packets may arrive on the
680*2f2c4c7aSAndroid Build Coastguard Worker      # underlying # network which fails the assertion that only one ESP packet
681*2f2c4c7aSAndroid Build Coastguard Worker      # is received.
682*2f2c4c7aSAndroid Build Coastguard Worker      cls.SetSysctl(
683*2f2c4c7aSAndroid Build Coastguard Worker          "/proc/sys/net/ipv6/conf/%s/router_solicitations" % tunnel.iface, 0)
684*2f2c4c7aSAndroid Build Coastguard Worker      net_test.SetInterfaceUp(tunnel.iface)
685*2f2c4c7aSAndroid Build Coastguard Worker
686*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 6]:
687*2f2c4c7aSAndroid Build Coastguard Worker      ifindex = net_test.GetInterfaceIndex(tunnel.iface)
688*2f2c4c7aSAndroid Build Coastguard Worker      table = tunnel.netid
689*2f2c4c7aSAndroid Build Coastguard Worker
690*2f2c4c7aSAndroid Build Coastguard Worker      # Set up routing rules.
691*2f2c4c7aSAndroid Build Coastguard Worker      start, end = cls.UidRangeForTunnelNetId(tunnel.netid)
692*2f2c4c7aSAndroid Build Coastguard Worker      cls.iproute.UidRangeRule(version, is_add, start, end, table,
693*2f2c4c7aSAndroid Build Coastguard Worker                                cls.PRIORITY_UID)
694*2f2c4c7aSAndroid Build Coastguard Worker      cls.iproute.OifRule(version, is_add, tunnel.iface, table, cls.PRIORITY_OIF)
695*2f2c4c7aSAndroid Build Coastguard Worker      cls.iproute.FwmarkRule(version, is_add, tunnel.netid, cls.NETID_FWMASK,
696*2f2c4c7aSAndroid Build Coastguard Worker                              table, cls.PRIORITY_FWMARK)
697*2f2c4c7aSAndroid Build Coastguard Worker
698*2f2c4c7aSAndroid Build Coastguard Worker      # Configure IP addresses.
699*2f2c4c7aSAndroid Build Coastguard Worker      addr = cls._GetLocalAddress(version, tunnel.netid)
700*2f2c4c7aSAndroid Build Coastguard Worker      prefixlen = net_test.AddressLengthBits(version)
701*2f2c4c7aSAndroid Build Coastguard Worker      tunnel.addrs[version] = addr
702*2f2c4c7aSAndroid Build Coastguard Worker      if is_add:
703*2f2c4c7aSAndroid Build Coastguard Worker        cls.iproute.AddAddress(addr, prefixlen, ifindex)
704*2f2c4c7aSAndroid Build Coastguard Worker        cls.iproute.AddRoute(version, table, "default", 0, None, ifindex)
705*2f2c4c7aSAndroid Build Coastguard Worker      else:
706*2f2c4c7aSAndroid Build Coastguard Worker        cls.iproute.DelRoute(version, table, "default", 0, None, ifindex)
707*2f2c4c7aSAndroid Build Coastguard Worker        cls.iproute.DelAddress(addr, prefixlen, ifindex)
708*2f2c4c7aSAndroid Build Coastguard Worker
709*2f2c4c7aSAndroid Build Coastguard Worker  def assertReceivedPacket(self, tunnel, sa_info):
710*2f2c4c7aSAndroid Build Coastguard Worker    tunnel.rx += 1
711*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual((tunnel.rx, tunnel.tx),
712*2f2c4c7aSAndroid Build Coastguard Worker                      self.iproute.GetRxTxPackets(tunnel.iface))
713*2f2c4c7aSAndroid Build Coastguard Worker    sa_info.seq_num += 1
714*2f2c4c7aSAndroid Build Coastguard Worker
715*2f2c4c7aSAndroid Build Coastguard Worker  def assertSentPacket(self, tunnel, sa_info):
716*2f2c4c7aSAndroid Build Coastguard Worker    tunnel.tx += 1
717*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual((tunnel.rx, tunnel.tx),
718*2f2c4c7aSAndroid Build Coastguard Worker                      self.iproute.GetRxTxPackets(tunnel.iface))
719*2f2c4c7aSAndroid Build Coastguard Worker    sa_info.seq_num += 1
720*2f2c4c7aSAndroid Build Coastguard Worker
721*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckTunnelInput(self, tunnel, inner_version, local_inner, remote_inner,
722*2f2c4c7aSAndroid Build Coastguard Worker                        sa_info=None, expect_fail=False):
723*2f2c4c7aSAndroid Build Coastguard Worker    """Test null-crypt input path over an IPsec interface."""
724*2f2c4c7aSAndroid Build Coastguard Worker    if sa_info is None:
725*2f2c4c7aSAndroid Build Coastguard Worker      sa_info = tunnel.in_sa
726*2f2c4c7aSAndroid Build Coastguard Worker    read_sock, local_port = _CreateReceiveSock(inner_version)
727*2f2c4c7aSAndroid Build Coastguard Worker
728*2f2c4c7aSAndroid Build Coastguard Worker    input_pkt = _GetNullAuthCryptTunnelModePkt(
729*2f2c4c7aSAndroid Build Coastguard Worker        inner_version, remote_inner, tunnel.remote, _TEST_REMOTE_PORT,
730*2f2c4c7aSAndroid Build Coastguard Worker        local_inner, tunnel.local, local_port, sa_info.spi, sa_info.seq_num)
731*2f2c4c7aSAndroid Build Coastguard Worker    self.ReceivePacketOn(tunnel.underlying_netid, input_pkt)
732*2f2c4c7aSAndroid Build Coastguard Worker
733*2f2c4c7aSAndroid Build Coastguard Worker    try:
734*2f2c4c7aSAndroid Build Coastguard Worker      if expect_fail:
735*2f2c4c7aSAndroid Build Coastguard Worker        self.assertRaisesErrno(EAGAIN, read_sock.recv, 4096)
736*2f2c4c7aSAndroid Build Coastguard Worker      else:
737*2f2c4c7aSAndroid Build Coastguard Worker        # Verify that the packet data and src are correct
738*2f2c4c7aSAndroid Build Coastguard Worker        data, src = read_sock.recvfrom(4096)
739*2f2c4c7aSAndroid Build Coastguard Worker        self.assertReceivedPacket(tunnel, sa_info)
740*2f2c4c7aSAndroid Build Coastguard Worker        self.assertEqual(net_test.UDP_PAYLOAD, data)
741*2f2c4c7aSAndroid Build Coastguard Worker        self.assertEqual((remote_inner, _TEST_REMOTE_PORT), src[:2])
742*2f2c4c7aSAndroid Build Coastguard Worker    finally:
743*2f2c4c7aSAndroid Build Coastguard Worker      read_sock.close()
744*2f2c4c7aSAndroid Build Coastguard Worker
745*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckTunnelOutput(self, tunnel, inner_version, local_inner,
746*2f2c4c7aSAndroid Build Coastguard Worker                         remote_inner, sa_info=None):
747*2f2c4c7aSAndroid Build Coastguard Worker    """Test null-crypt output path over an IPsec interface."""
748*2f2c4c7aSAndroid Build Coastguard Worker    if sa_info is None:
749*2f2c4c7aSAndroid Build Coastguard Worker      sa_info = tunnel.out_sa
750*2f2c4c7aSAndroid Build Coastguard Worker    local_port = _SendPacket(self, tunnel.netid, inner_version, remote_inner,
751*2f2c4c7aSAndroid Build Coastguard Worker                             _TEST_REMOTE_PORT)
752*2f2c4c7aSAndroid Build Coastguard Worker
753*2f2c4c7aSAndroid Build Coastguard Worker    # Read a tunneled IP packet on the underlying (outbound) network
754*2f2c4c7aSAndroid Build Coastguard Worker    # verifying that it is an ESP packet.
755*2f2c4c7aSAndroid Build Coastguard Worker    pkt = self._ExpectEspPacketOn(tunnel.underlying_netid, sa_info.spi,
756*2f2c4c7aSAndroid Build Coastguard Worker                                  sa_info.seq_num, None, tunnel.local,
757*2f2c4c7aSAndroid Build Coastguard Worker                                  tunnel.remote)
758*2f2c4c7aSAndroid Build Coastguard Worker
759*2f2c4c7aSAndroid Build Coastguard Worker    # Get and update the IP headers on the inner payload so that we can do a simple
760*2f2c4c7aSAndroid Build Coastguard Worker    # comparison of byte data. Unfortunately, due to the scapy version this runs on,
761*2f2c4c7aSAndroid Build Coastguard Worker    # we cannot parse past the ESP header to the inner IP header, and thus have to
762*2f2c4c7aSAndroid Build Coastguard Worker    # workaround in this manner
763*2f2c4c7aSAndroid Build Coastguard Worker    if inner_version == 4:
764*2f2c4c7aSAndroid Build Coastguard Worker      ip_hdr_options = {
765*2f2c4c7aSAndroid Build Coastguard Worker        'id': scapy.IP(bytes(pkt.payload)[8:]).id,
766*2f2c4c7aSAndroid Build Coastguard Worker        'flags': scapy.IP(bytes(pkt.payload)[8:]).flags
767*2f2c4c7aSAndroid Build Coastguard Worker      }
768*2f2c4c7aSAndroid Build Coastguard Worker    else:
769*2f2c4c7aSAndroid Build Coastguard Worker      ip_hdr_options = {'fl': scapy.IPv6(bytes(pkt.payload)[8:]).fl}
770*2f2c4c7aSAndroid Build Coastguard Worker
771*2f2c4c7aSAndroid Build Coastguard Worker    expected = _GetNullAuthCryptTunnelModePkt(
772*2f2c4c7aSAndroid Build Coastguard Worker        inner_version, local_inner, tunnel.local, local_port, remote_inner,
773*2f2c4c7aSAndroid Build Coastguard Worker        tunnel.remote, _TEST_REMOTE_PORT, sa_info.spi, sa_info.seq_num,
774*2f2c4c7aSAndroid Build Coastguard Worker        ip_hdr_options)
775*2f2c4c7aSAndroid Build Coastguard Worker
776*2f2c4c7aSAndroid Build Coastguard Worker    # Check outer header manually (Avoids having to overwrite outer header's
777*2f2c4c7aSAndroid Build Coastguard Worker    # id, flags or flow label)
778*2f2c4c7aSAndroid Build Coastguard Worker    self.assertSentPacket(tunnel, sa_info)
779*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected.src, pkt.src)
780*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected.dst, pkt.dst)
781*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(len(expected), len(pkt))
782*2f2c4c7aSAndroid Build Coastguard Worker
783*2f2c4c7aSAndroid Build Coastguard Worker    # Check everything else
784*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(bytes(expected.payload), bytes(pkt.payload))
785*2f2c4c7aSAndroid Build Coastguard Worker
786*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckTunnelEncryption(self, tunnel, inner_version, local_inner,
787*2f2c4c7aSAndroid Build Coastguard Worker                             remote_inner):
788*2f2c4c7aSAndroid Build Coastguard Worker    """Test both input and output paths over an encrypted IPsec interface.
789*2f2c4c7aSAndroid Build Coastguard Worker
790*2f2c4c7aSAndroid Build Coastguard Worker    This tests specifically makes sure that the both encryption and decryption
791*2f2c4c7aSAndroid Build Coastguard Worker    work together, as opposed to the _CheckTunnel(Input|Output) where the
792*2f2c4c7aSAndroid Build Coastguard Worker    input and output paths are tested separately, and using null encryption.
793*2f2c4c7aSAndroid Build Coastguard Worker    """
794*2f2c4c7aSAndroid Build Coastguard Worker    src_port = _SendPacket(self, tunnel.netid, inner_version, remote_inner,
795*2f2c4c7aSAndroid Build Coastguard Worker                           _TEST_REMOTE_PORT)
796*2f2c4c7aSAndroid Build Coastguard Worker
797*2f2c4c7aSAndroid Build Coastguard Worker    # Make sure it appeared on the underlying interface
798*2f2c4c7aSAndroid Build Coastguard Worker    pkt = self._ExpectEspPacketOn(tunnel.underlying_netid, tunnel.out_sa.spi,
799*2f2c4c7aSAndroid Build Coastguard Worker                                  tunnel.out_sa.seq_num, None, tunnel.local,
800*2f2c4c7aSAndroid Build Coastguard Worker                                  tunnel.remote)
801*2f2c4c7aSAndroid Build Coastguard Worker
802*2f2c4c7aSAndroid Build Coastguard Worker    # Check that packet is not sent in plaintext
803*2f2c4c7aSAndroid Build Coastguard Worker    self.assertTrue(bytes(net_test.UDP_PAYLOAD) not in bytes(pkt))
804*2f2c4c7aSAndroid Build Coastguard Worker
805*2f2c4c7aSAndroid Build Coastguard Worker    # Check src/dst
806*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(tunnel.local, pkt.src)
807*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(tunnel.remote, pkt.dst)
808*2f2c4c7aSAndroid Build Coastguard Worker
809*2f2c4c7aSAndroid Build Coastguard Worker    # Check that the interface statistics recorded the outbound packet
810*2f2c4c7aSAndroid Build Coastguard Worker    self.assertSentPacket(tunnel, tunnel.out_sa)
811*2f2c4c7aSAndroid Build Coastguard Worker
812*2f2c4c7aSAndroid Build Coastguard Worker    try:
813*2f2c4c7aSAndroid Build Coastguard Worker      # Swap the interface addresses to pretend we are the remote
814*2f2c4c7aSAndroid Build Coastguard Worker      self._SwapInterfaceAddress(
815*2f2c4c7aSAndroid Build Coastguard Worker          tunnel.iface, new_addr=remote_inner, old_addr=local_inner)
816*2f2c4c7aSAndroid Build Coastguard Worker
817*2f2c4c7aSAndroid Build Coastguard Worker      # Swap the packet's IP headers and write it back to the underlying
818*2f2c4c7aSAndroid Build Coastguard Worker      # network.
819*2f2c4c7aSAndroid Build Coastguard Worker      pkt = TunTwister.TwistPacket(pkt)
820*2f2c4c7aSAndroid Build Coastguard Worker      read_sock, local_port = _CreateReceiveSock(inner_version,
821*2f2c4c7aSAndroid Build Coastguard Worker                                                 _TEST_REMOTE_PORT)
822*2f2c4c7aSAndroid Build Coastguard Worker      self.ReceivePacketOn(tunnel.underlying_netid, pkt)
823*2f2c4c7aSAndroid Build Coastguard Worker
824*2f2c4c7aSAndroid Build Coastguard Worker      # Verify that the packet data and src are correct
825*2f2c4c7aSAndroid Build Coastguard Worker      data, src = read_sock.recvfrom(4096)
826*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(net_test.UDP_PAYLOAD, data)
827*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual((local_inner, src_port), src[:2])
828*2f2c4c7aSAndroid Build Coastguard Worker
829*2f2c4c7aSAndroid Build Coastguard Worker      # Check that the interface statistics recorded the inbound packet
830*2f2c4c7aSAndroid Build Coastguard Worker      self.assertReceivedPacket(tunnel, tunnel.in_sa)
831*2f2c4c7aSAndroid Build Coastguard Worker
832*2f2c4c7aSAndroid Build Coastguard Worker      read_sock.close()
833*2f2c4c7aSAndroid Build Coastguard Worker    finally:
834*2f2c4c7aSAndroid Build Coastguard Worker      # Swap the interface addresses to pretend we are the remote
835*2f2c4c7aSAndroid Build Coastguard Worker      self._SwapInterfaceAddress(
836*2f2c4c7aSAndroid Build Coastguard Worker          tunnel.iface, new_addr=local_inner, old_addr=remote_inner)
837*2f2c4c7aSAndroid Build Coastguard Worker
838*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckTunnelIcmp(self, tunnel, inner_version, local_inner, remote_inner,
839*2f2c4c7aSAndroid Build Coastguard Worker                       sa_info=None):
840*2f2c4c7aSAndroid Build Coastguard Worker    """Test ICMP error path over an IPsec interface."""
841*2f2c4c7aSAndroid Build Coastguard Worker    if sa_info is None:
842*2f2c4c7aSAndroid Build Coastguard Worker      sa_info = tunnel.out_sa
843*2f2c4c7aSAndroid Build Coastguard Worker    # Now attempt to provoke an ICMP error.
844*2f2c4c7aSAndroid Build Coastguard Worker    # TODO: deduplicate with multinetwork_test.py.
845*2f2c4c7aSAndroid Build Coastguard Worker    dst_prefix, intermediate = {
846*2f2c4c7aSAndroid Build Coastguard Worker        4: ("172.19.", "172.16.9.12"),
847*2f2c4c7aSAndroid Build Coastguard Worker        6: ("2001:db8::", "2001:db8::1")
848*2f2c4c7aSAndroid Build Coastguard Worker    }[tunnel.version]
849*2f2c4c7aSAndroid Build Coastguard Worker
850*2f2c4c7aSAndroid Build Coastguard Worker    local_port = _SendPacket(self, tunnel.netid, inner_version, remote_inner,
851*2f2c4c7aSAndroid Build Coastguard Worker                             _TEST_REMOTE_PORT)
852*2f2c4c7aSAndroid Build Coastguard Worker    pkt = self._ExpectEspPacketOn(tunnel.underlying_netid, sa_info.spi,
853*2f2c4c7aSAndroid Build Coastguard Worker                                  sa_info.seq_num, None, tunnel.local,
854*2f2c4c7aSAndroid Build Coastguard Worker                                  tunnel.remote)
855*2f2c4c7aSAndroid Build Coastguard Worker    self.assertSentPacket(tunnel, sa_info)
856*2f2c4c7aSAndroid Build Coastguard Worker
857*2f2c4c7aSAndroid Build Coastguard Worker    myaddr = self.MyAddress(tunnel.version, tunnel.underlying_netid)
858*2f2c4c7aSAndroid Build Coastguard Worker    _, toobig = packets.ICMPPacketTooBig(tunnel.version, intermediate, myaddr,
859*2f2c4c7aSAndroid Build Coastguard Worker                                         pkt)
860*2f2c4c7aSAndroid Build Coastguard Worker    self.ReceivePacketOn(tunnel.underlying_netid, toobig)
861*2f2c4c7aSAndroid Build Coastguard Worker
862*2f2c4c7aSAndroid Build Coastguard Worker    # Check that the packet too big reduced the MTU.
863*2f2c4c7aSAndroid Build Coastguard Worker    routes = self.iproute.GetRoutes(tunnel.remote, 0, tunnel.underlying_netid, None)
864*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(1, len(routes))
865*2f2c4c7aSAndroid Build Coastguard Worker    rtmsg, attributes = routes[0]
866*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(iproute.RTN_UNICAST, rtmsg.type)
867*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(packets.PTB_MTU, attributes["RTA_METRICS"]["RTAX_MTU"])
868*2f2c4c7aSAndroid Build Coastguard Worker
869*2f2c4c7aSAndroid Build Coastguard Worker    # Clear PMTU information so that future tests don't have to worry about it.
870*2f2c4c7aSAndroid Build Coastguard Worker    self.InvalidateDstCache(tunnel.version, tunnel.underlying_netid)
871*2f2c4c7aSAndroid Build Coastguard Worker
872*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckTunnelEncryptionWithIcmp(self, tunnel, inner_version, local_inner,
873*2f2c4c7aSAndroid Build Coastguard Worker                                     remote_inner):
874*2f2c4c7aSAndroid Build Coastguard Worker    """Test combined encryption path with ICMP errors over an IPsec tunnel"""
875*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelEncryption(tunnel, inner_version, local_inner,
876*2f2c4c7aSAndroid Build Coastguard Worker                                remote_inner)
877*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelIcmp(tunnel, inner_version, local_inner, remote_inner)
878*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelEncryption(tunnel, inner_version, local_inner,
879*2f2c4c7aSAndroid Build Coastguard Worker                                remote_inner)
880*2f2c4c7aSAndroid Build Coastguard Worker
881*2f2c4c7aSAndroid Build Coastguard Worker  def  _RebuildTunnel(self, tunnel, use_null_crypt):
882*2f2c4c7aSAndroid Build Coastguard Worker    # Some tests require that the out_seq_num and in_seq_num are the same
883*2f2c4c7aSAndroid Build Coastguard Worker    # (Specifically encrypted tests), rebuild SAs to ensure seq_num is 1
884*2f2c4c7aSAndroid Build Coastguard Worker    #
885*2f2c4c7aSAndroid Build Coastguard Worker    # Until we get better scapy support, the only way we can build an
886*2f2c4c7aSAndroid Build Coastguard Worker    # encrypted packet is to send it out, and read the packet from the wire.
887*2f2c4c7aSAndroid Build Coastguard Worker    # We then generally use this as the "inbound" encrypted packet, injecting
888*2f2c4c7aSAndroid Build Coastguard Worker    # it into the interface for which it is expected on.
889*2f2c4c7aSAndroid Build Coastguard Worker    #
890*2f2c4c7aSAndroid Build Coastguard Worker    # As such, this is required to ensure that encrypted packets (which we
891*2f2c4c7aSAndroid Build Coastguard Worker    # currently have no way to easily modify) are not considered replay
892*2f2c4c7aSAndroid Build Coastguard Worker    # attacks by the inbound SA.  (eg: received 3 packets, seq_num_in = 3,
893*2f2c4c7aSAndroid Build Coastguard Worker    # sent only 1, # seq_num_out = 1, inbound SA would consider this a replay
894*2f2c4c7aSAndroid Build Coastguard Worker    # attack)
895*2f2c4c7aSAndroid Build Coastguard Worker    tunnel.TeardownXfrm()
896*2f2c4c7aSAndroid Build Coastguard Worker    tunnel.SetupXfrm(use_null_crypt)
897*2f2c4c7aSAndroid Build Coastguard Worker
898*2f2c4c7aSAndroid Build Coastguard Worker  def _TestTunnel(self, inner_version, outer_version, func, use_null_crypt):
899*2f2c4c7aSAndroid Build Coastguard Worker    """Bootstrap method to setup and run tests for the given parameters."""
900*2f2c4c7aSAndroid Build Coastguard Worker    tunnel = self.randomTunnel(outer_version)
901*2f2c4c7aSAndroid Build Coastguard Worker
902*2f2c4c7aSAndroid Build Coastguard Worker    try:
903*2f2c4c7aSAndroid Build Coastguard Worker      self._RebuildTunnel(tunnel, use_null_crypt)
904*2f2c4c7aSAndroid Build Coastguard Worker
905*2f2c4c7aSAndroid Build Coastguard Worker      local_inner = tunnel.addrs[inner_version]
906*2f2c4c7aSAndroid Build Coastguard Worker      remote_inner = _GetRemoteInnerAddress(inner_version)
907*2f2c4c7aSAndroid Build Coastguard Worker
908*2f2c4c7aSAndroid Build Coastguard Worker      for i in range(2):
909*2f2c4c7aSAndroid Build Coastguard Worker        func(tunnel, inner_version, local_inner, remote_inner)
910*2f2c4c7aSAndroid Build Coastguard Worker    finally:
911*2f2c4c7aSAndroid Build Coastguard Worker      if use_null_crypt:
912*2f2c4c7aSAndroid Build Coastguard Worker        tunnel.TeardownXfrm()
913*2f2c4c7aSAndroid Build Coastguard Worker        tunnel.SetupXfrm(False)
914*2f2c4c7aSAndroid Build Coastguard Worker
915*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckTunnelRekey(self, tunnel, inner_version, local_inner, remote_inner):
916*2f2c4c7aSAndroid Build Coastguard Worker    old_out_sa = tunnel.out_sa
917*2f2c4c7aSAndroid Build Coastguard Worker    old_in_sa = tunnel.in_sa
918*2f2c4c7aSAndroid Build Coastguard Worker
919*2f2c4c7aSAndroid Build Coastguard Worker    # Check to make sure that both directions work before rekey
920*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelInput(tunnel, inner_version, local_inner, remote_inner,
921*2f2c4c7aSAndroid Build Coastguard Worker                           old_in_sa)
922*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelOutput(tunnel, inner_version, local_inner, remote_inner,
923*2f2c4c7aSAndroid Build Coastguard Worker                            old_out_sa)
924*2f2c4c7aSAndroid Build Coastguard Worker
925*2f2c4c7aSAndroid Build Coastguard Worker    # Rekey
926*2f2c4c7aSAndroid Build Coastguard Worker    outer_family = net_test.GetAddressFamily(tunnel.version)
927*2f2c4c7aSAndroid Build Coastguard Worker
928*2f2c4c7aSAndroid Build Coastguard Worker    # Create new SA
929*2f2c4c7aSAndroid Build Coastguard Worker    # Distinguish the new SAs with new SPIs.
930*2f2c4c7aSAndroid Build Coastguard Worker    new_out_sa = SaInfo(old_out_sa.spi + 1)
931*2f2c4c7aSAndroid Build Coastguard Worker    new_in_sa = SaInfo(old_in_sa.spi + 1)
932*2f2c4c7aSAndroid Build Coastguard Worker
933*2f2c4c7aSAndroid Build Coastguard Worker    # Perform Rekey
934*2f2c4c7aSAndroid Build Coastguard Worker    tunnel.Rekey(outer_family, new_out_sa, new_in_sa)
935*2f2c4c7aSAndroid Build Coastguard Worker
936*2f2c4c7aSAndroid Build Coastguard Worker    # Expect that the old SPI still works for inbound packets
937*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelInput(tunnel, inner_version, local_inner, remote_inner,
938*2f2c4c7aSAndroid Build Coastguard Worker                           old_in_sa)
939*2f2c4c7aSAndroid Build Coastguard Worker
940*2f2c4c7aSAndroid Build Coastguard Worker    # Test both paths with new SPIs, expect outbound to use new SPI
941*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelInput(tunnel, inner_version, local_inner, remote_inner,
942*2f2c4c7aSAndroid Build Coastguard Worker                           new_in_sa)
943*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelOutput(tunnel, inner_version, local_inner, remote_inner,
944*2f2c4c7aSAndroid Build Coastguard Worker                            new_out_sa)
945*2f2c4c7aSAndroid Build Coastguard Worker
946*2f2c4c7aSAndroid Build Coastguard Worker    # Delete old SAs
947*2f2c4c7aSAndroid Build Coastguard Worker    tunnel.DeleteOldSaInfo(outer_family, old_in_sa.spi, old_out_sa.spi)
948*2f2c4c7aSAndroid Build Coastguard Worker
949*2f2c4c7aSAndroid Build Coastguard Worker    # Test both paths with new SPIs; should still work
950*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelInput(tunnel, inner_version, local_inner, remote_inner,
951*2f2c4c7aSAndroid Build Coastguard Worker                           new_in_sa)
952*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelOutput(tunnel, inner_version, local_inner, remote_inner,
953*2f2c4c7aSAndroid Build Coastguard Worker                            new_out_sa)
954*2f2c4c7aSAndroid Build Coastguard Worker
955*2f2c4c7aSAndroid Build Coastguard Worker    # Expect failure upon trying to receive a packet with the deleted SPI
956*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelInput(tunnel, inner_version, local_inner, remote_inner,
957*2f2c4c7aSAndroid Build Coastguard Worker                           old_in_sa, True)
958*2f2c4c7aSAndroid Build Coastguard Worker
959*2f2c4c7aSAndroid Build Coastguard Worker  def _TestTunnelRekey(self, inner_version, outer_version):
960*2f2c4c7aSAndroid Build Coastguard Worker    """Test packet input and output over a Virtual Tunnel Interface."""
961*2f2c4c7aSAndroid Build Coastguard Worker    tunnel = self.randomTunnel(outer_version)
962*2f2c4c7aSAndroid Build Coastguard Worker
963*2f2c4c7aSAndroid Build Coastguard Worker    try:
964*2f2c4c7aSAndroid Build Coastguard Worker      # Always use null_crypt, so we can check input and output separately
965*2f2c4c7aSAndroid Build Coastguard Worker      tunnel.TeardownXfrm()
966*2f2c4c7aSAndroid Build Coastguard Worker      tunnel.SetupXfrm(True)
967*2f2c4c7aSAndroid Build Coastguard Worker
968*2f2c4c7aSAndroid Build Coastguard Worker      local_inner = tunnel.addrs[inner_version]
969*2f2c4c7aSAndroid Build Coastguard Worker      remote_inner = _GetRemoteInnerAddress(inner_version)
970*2f2c4c7aSAndroid Build Coastguard Worker
971*2f2c4c7aSAndroid Build Coastguard Worker      self._CheckTunnelRekey(tunnel, inner_version, local_inner, remote_inner)
972*2f2c4c7aSAndroid Build Coastguard Worker    finally:
973*2f2c4c7aSAndroid Build Coastguard Worker      tunnel.TeardownXfrm()
974*2f2c4c7aSAndroid Build Coastguard Worker      tunnel.SetupXfrm(False)
975*2f2c4c7aSAndroid Build Coastguard Worker
976*2f2c4c7aSAndroid Build Coastguard Worker
977*2f2c4c7aSAndroid Build Coastguard Workerclass XfrmVtiTest(XfrmTunnelBase):
978*2f2c4c7aSAndroid Build Coastguard Worker
979*2f2c4c7aSAndroid Build Coastguard Worker  INTERFACE_CLASS = VtiInterface
980*2f2c4c7aSAndroid Build Coastguard Worker
981*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestVtiInput(self, inner_version, outer_version):
982*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, self._CheckTunnelInput, True)
983*2f2c4c7aSAndroid Build Coastguard Worker
984*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestVtiOutput(self, inner_version, outer_version):
985*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, self._CheckTunnelOutput,
986*2f2c4c7aSAndroid Build Coastguard Worker                     True)
987*2f2c4c7aSAndroid Build Coastguard Worker
988*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestVtiInOutEncrypted(self, inner_version, outer_version):
989*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, self._CheckTunnelEncryption,
990*2f2c4c7aSAndroid Build Coastguard Worker                     False)
991*2f2c4c7aSAndroid Build Coastguard Worker
992*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestVtiIcmp(self, inner_version, outer_version):
993*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, self._CheckTunnelIcmp, False)
994*2f2c4c7aSAndroid Build Coastguard Worker
995*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestVtiEncryptionWithIcmp(self, inner_version, outer_version):
996*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version,
997*2f2c4c7aSAndroid Build Coastguard Worker                     self._CheckTunnelEncryptionWithIcmp, False)
998*2f2c4c7aSAndroid Build Coastguard Worker
999*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestVtiRekey(self, inner_version, outer_version):
1000*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnelRekey(inner_version, outer_version)
1001*2f2c4c7aSAndroid Build Coastguard Worker
1002*2f2c4c7aSAndroid Build Coastguard Worker
1003*2f2c4c7aSAndroid Build Coastguard Workerclass XfrmInterfaceTest(XfrmTunnelBase):
1004*2f2c4c7aSAndroid Build Coastguard Worker
1005*2f2c4c7aSAndroid Build Coastguard Worker  INTERFACE_CLASS = XfrmInterface
1006*2f2c4c7aSAndroid Build Coastguard Worker
1007*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestXfrmIntfInput(self, inner_version, outer_version):
1008*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, self._CheckTunnelInput, True)
1009*2f2c4c7aSAndroid Build Coastguard Worker
1010*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestXfrmIntfOutput(self, inner_version, outer_version):
1011*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, self._CheckTunnelOutput,
1012*2f2c4c7aSAndroid Build Coastguard Worker                     True)
1013*2f2c4c7aSAndroid Build Coastguard Worker
1014*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestXfrmIntfInOutEncrypted(self, inner_version, outer_version):
1015*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, self._CheckTunnelEncryption,
1016*2f2c4c7aSAndroid Build Coastguard Worker                     False)
1017*2f2c4c7aSAndroid Build Coastguard Worker
1018*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestXfrmIntfIcmp(self, inner_version, outer_version):
1019*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, self._CheckTunnelIcmp, False)
1020*2f2c4c7aSAndroid Build Coastguard Worker
1021*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestXfrmIntfEncryptionWithIcmp(self, inner_version, outer_version):
1022*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version,
1023*2f2c4c7aSAndroid Build Coastguard Worker                     self._CheckTunnelEncryptionWithIcmp, False)
1024*2f2c4c7aSAndroid Build Coastguard Worker
1025*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestXfrmIntfRekey(self, inner_version, outer_version):
1026*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnelRekey(inner_version, outer_version)
1027*2f2c4c7aSAndroid Build Coastguard Worker
1028*2f2c4c7aSAndroid Build Coastguard Worker##############################################################################
1029*2f2c4c7aSAndroid Build Coastguard Worker#
1030*2f2c4c7aSAndroid Build Coastguard Worker# Test for presence of CONFIG_XFRM_MIGRATE and kernel patches
1031*2f2c4c7aSAndroid Build Coastguard Worker#
1032*2f2c4c7aSAndroid Build Coastguard Worker#   xfrm: Check if_id in xfrm_migrate
1033*2f2c4c7aSAndroid Build Coastguard Worker#   Upstream commit: c1aca3080e382886e2e58e809787441984a2f89b
1034*2f2c4c7aSAndroid Build Coastguard Worker#
1035*2f2c4c7aSAndroid Build Coastguard Worker#   xfrm: Fix xfrm migrate issues when address family changes
1036*2f2c4c7aSAndroid Build Coastguard Worker#   Upstream commit: e03c3bba351f99ad932e8f06baa9da1afc418e02
1037*2f2c4c7aSAndroid Build Coastguard Worker#
1038*2f2c4c7aSAndroid Build Coastguard Worker# Those two upstream 5.17 fixes above were pulled in to LTS in kernel versions
1039*2f2c4c7aSAndroid Build Coastguard Worker# 4.14.273, 4.19.236, 5.4.186, 5.10.107, 5.15.30.
1040*2f2c4c7aSAndroid Build Coastguard Worker#
1041*2f2c4c7aSAndroid Build Coastguard Worker# Note: the 'Check if_id in xfrm_migrate' fix did not land in 4.14 LTS,
1042*2f2c4c7aSAndroid Build Coastguard Worker# and instead landed in android-4.14-stable after 4.14.320 LTS merge.
1043*2f2c4c7aSAndroid Build Coastguard Worker#
1044*2f2c4c7aSAndroid Build Coastguard Worker@unittest.skipUnless(SUPPORTS_XFRM_MIGRATE,
1045*2f2c4c7aSAndroid Build Coastguard Worker                     "XFRM migration unsupported or fixes not included")
1046*2f2c4c7aSAndroid Build Coastguard Workerclass XfrmInterfaceMigrateTest(XfrmTunnelBase):
1047*2f2c4c7aSAndroid Build Coastguard Worker  INTERFACE_CLASS = XfrmInterface
1048*2f2c4c7aSAndroid Build Coastguard Worker
1049*2f2c4c7aSAndroid Build Coastguard Worker  def setUpTunnel(self, outer_version, use_null_crypt):
1050*2f2c4c7aSAndroid Build Coastguard Worker    underlying_netid = self.RandomNetid()
1051*2f2c4c7aSAndroid Build Coastguard Worker    netid = _BASE_TUNNEL_NETID[outer_version] + _TUNNEL_NETID_OFFSET
1052*2f2c4c7aSAndroid Build Coastguard Worker    iface = "ipsec%s" % netid
1053*2f2c4c7aSAndroid Build Coastguard Worker    ifindex = self.ifindices[underlying_netid]
1054*2f2c4c7aSAndroid Build Coastguard Worker
1055*2f2c4c7aSAndroid Build Coastguard Worker    local = self.MyAddress(outer_version, underlying_netid)
1056*2f2c4c7aSAndroid Build Coastguard Worker    remote = net_test.IPV4_ADDR if outer_version == 4 else net_test.IPV6_ADDR
1057*2f2c4c7aSAndroid Build Coastguard Worker
1058*2f2c4c7aSAndroid Build Coastguard Worker    tunnel = XfrmInterface(iface, netid, underlying_netid, ifindex,
1059*2f2c4c7aSAndroid Build Coastguard Worker                           local, remote, outer_version, use_null_crypt)
1060*2f2c4c7aSAndroid Build Coastguard Worker    self._SetInboundMarking(netid, iface, True)
1061*2f2c4c7aSAndroid Build Coastguard Worker    self._SetupTunnelNetwork(tunnel, True)
1062*2f2c4c7aSAndroid Build Coastguard Worker
1063*2f2c4c7aSAndroid Build Coastguard Worker    return tunnel
1064*2f2c4c7aSAndroid Build Coastguard Worker
1065*2f2c4c7aSAndroid Build Coastguard Worker  def tearDownTunnel(self, tunnel):
1066*2f2c4c7aSAndroid Build Coastguard Worker    self._SetInboundMarking(tunnel.netid, tunnel.iface, False)
1067*2f2c4c7aSAndroid Build Coastguard Worker    self._SetupTunnelNetwork(tunnel, False)
1068*2f2c4c7aSAndroid Build Coastguard Worker    tunnel.Teardown()
1069*2f2c4c7aSAndroid Build Coastguard Worker
1070*2f2c4c7aSAndroid Build Coastguard Worker  def _TestTunnel(self, inner_version, outer_version, new_outer_version, func,
1071*2f2c4c7aSAndroid Build Coastguard Worker                  use_null_crypt):
1072*2f2c4c7aSAndroid Build Coastguard Worker    tunnel = self.randomTunnel(outer_version)
1073*2f2c4c7aSAndroid Build Coastguard Worker
1074*2f2c4c7aSAndroid Build Coastguard Worker    old_underlying_netid = tunnel.underlying_netid
1075*2f2c4c7aSAndroid Build Coastguard Worker    old_local = tunnel.local
1076*2f2c4c7aSAndroid Build Coastguard Worker    old_remote = tunnel.remote
1077*2f2c4c7aSAndroid Build Coastguard Worker
1078*2f2c4c7aSAndroid Build Coastguard Worker
1079*2f2c4c7aSAndroid Build Coastguard Worker    try:
1080*2f2c4c7aSAndroid Build Coastguard Worker      self._RebuildTunnel(tunnel, use_null_crypt)
1081*2f2c4c7aSAndroid Build Coastguard Worker
1082*2f2c4c7aSAndroid Build Coastguard Worker      # Verify functionality before migration
1083*2f2c4c7aSAndroid Build Coastguard Worker      local_inner = tunnel.addrs[inner_version]
1084*2f2c4c7aSAndroid Build Coastguard Worker      remote_inner = _GetRemoteInnerAddress(inner_version)
1085*2f2c4c7aSAndroid Build Coastguard Worker      func(tunnel, inner_version, local_inner, remote_inner)
1086*2f2c4c7aSAndroid Build Coastguard Worker
1087*2f2c4c7aSAndroid Build Coastguard Worker      # Migrate tunnel
1088*2f2c4c7aSAndroid Build Coastguard Worker      new_underlying_netid = self.RandomNetid(exclude=tunnel.underlying_netid)
1089*2f2c4c7aSAndroid Build Coastguard Worker      new_version = new_outer_version
1090*2f2c4c7aSAndroid Build Coastguard Worker      new_local = self.MyAddress(new_version, new_underlying_netid)
1091*2f2c4c7aSAndroid Build Coastguard Worker      new_remote = net_test.IPV4_ADDR2 if new_version == 4 else net_test.IPV6_ADDR2
1092*2f2c4c7aSAndroid Build Coastguard Worker
1093*2f2c4c7aSAndroid Build Coastguard Worker      tunnel.Migrate(new_underlying_netid, new_local, new_remote)
1094*2f2c4c7aSAndroid Build Coastguard Worker
1095*2f2c4c7aSAndroid Build Coastguard Worker      # Verify functionality after migration
1096*2f2c4c7aSAndroid Build Coastguard Worker      func(tunnel, inner_version, local_inner, remote_inner)
1097*2f2c4c7aSAndroid Build Coastguard Worker    finally:
1098*2f2c4c7aSAndroid Build Coastguard Worker      # Reset the tunnel to the original configuration
1099*2f2c4c7aSAndroid Build Coastguard Worker      tunnel.TeardownXfrm()
1100*2f2c4c7aSAndroid Build Coastguard Worker
1101*2f2c4c7aSAndroid Build Coastguard Worker      self.local = old_local
1102*2f2c4c7aSAndroid Build Coastguard Worker      self.remote = old_remote
1103*2f2c4c7aSAndroid Build Coastguard Worker      self.underlying_netid = old_underlying_netid
1104*2f2c4c7aSAndroid Build Coastguard Worker      tunnel.SetupXfrm(False)
1105*2f2c4c7aSAndroid Build Coastguard Worker
1106*2f2c4c7aSAndroid Build Coastguard Worker
1107*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestMigrateXfrmIntfInput(self, inner_version, outer_version,
1108*2f2c4c7aSAndroid Build Coastguard Worker                                    new_outer_version):
1109*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, new_outer_version,
1110*2f2c4c7aSAndroid Build Coastguard Worker                     self._CheckTunnelInput, True)
1111*2f2c4c7aSAndroid Build Coastguard Worker
1112*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestMigrateXfrmIntfOutput(self, inner_version, outer_version,
1113*2f2c4c7aSAndroid Build Coastguard Worker                                     new_outer_version):
1114*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, new_outer_version,
1115*2f2c4c7aSAndroid Build Coastguard Worker                     self._CheckTunnelOutput, True)
1116*2f2c4c7aSAndroid Build Coastguard Worker
1117*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestMigrateXfrmIntfInOutEncrypted(self, inner_version, outer_version,
1118*2f2c4c7aSAndroid Build Coastguard Worker                                             new_outer_version):
1119*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, new_outer_version,
1120*2f2c4c7aSAndroid Build Coastguard Worker                     self._CheckTunnelEncryption, False)
1121*2f2c4c7aSAndroid Build Coastguard Worker
1122*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestMigrateXfrmIntfIcmp(self, inner_version, outer_version,
1123*2f2c4c7aSAndroid Build Coastguard Worker                                   new_outer_version):
1124*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, new_outer_version,
1125*2f2c4c7aSAndroid Build Coastguard Worker                     self._CheckTunnelIcmp, False)
1126*2f2c4c7aSAndroid Build Coastguard Worker
1127*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestMigrateXfrmIntfEncryptionWithIcmp(self, inner_version, outer_version,
1128*2f2c4c7aSAndroid Build Coastguard Worker                                                 new_outer_version):
1129*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, new_outer_version,
1130*2f2c4c7aSAndroid Build Coastguard Worker                     self._CheckTunnelEncryptionWithIcmp, False)
1131*2f2c4c7aSAndroid Build Coastguard Worker
1132*2f2c4c7aSAndroid Build Coastguard Worker  def ParamTestMigrateXfrmIntfRekey(self, inner_version, outer_version,
1133*2f2c4c7aSAndroid Build Coastguard Worker                                    new_outer_version):
1134*2f2c4c7aSAndroid Build Coastguard Worker    self._TestTunnel(inner_version, outer_version, new_outer_version,
1135*2f2c4c7aSAndroid Build Coastguard Worker                     self._CheckTunnelRekey, True)
1136*2f2c4c7aSAndroid Build Coastguard Worker
1137*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__":
1138*2f2c4c7aSAndroid Build Coastguard Worker  InjectTests()
1139*2f2c4c7aSAndroid Build Coastguard Worker  unittest.main()
1140