xref: /aosp_15_r20/kernel/tests/net/test/xfrm_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 scapy import all as scapy
20*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import *  # pylint: disable=wildcard-import
21*2f2c4c7aSAndroid Build Coastguard Workerimport binascii
22*2f2c4c7aSAndroid Build Coastguard Workerimport struct
23*2f2c4c7aSAndroid Build Coastguard Workerimport subprocess
24*2f2c4c7aSAndroid Build Coastguard Workerimport threading
25*2f2c4c7aSAndroid Build Coastguard Workerimport unittest
26*2f2c4c7aSAndroid Build Coastguard Worker
27*2f2c4c7aSAndroid Build Coastguard Workerimport csocket
28*2f2c4c7aSAndroid Build Coastguard Workerimport cstruct
29*2f2c4c7aSAndroid Build Coastguard Workerimport multinetwork_base
30*2f2c4c7aSAndroid Build Coastguard Workerimport net_test
31*2f2c4c7aSAndroid Build Coastguard Workerimport packets
32*2f2c4c7aSAndroid Build Coastguard Workerimport xfrm
33*2f2c4c7aSAndroid Build Coastguard Workerimport xfrm_base
34*2f2c4c7aSAndroid Build Coastguard Worker
35*2f2c4c7aSAndroid Build Coastguard WorkerENCRYPTED_PAYLOAD = ("b1c74998efd6326faebe2061f00f2c750e90e76001664a80c287b150"
36*2f2c4c7aSAndroid Build Coastguard Worker                     "59e74bf949769cc6af71e51b539e7de3a2a14cb05a231b969e035174"
37*2f2c4c7aSAndroid Build Coastguard Worker                     "d98c5aa0cef1937db98889ec0d08fa408fecf616")
38*2f2c4c7aSAndroid Build Coastguard Worker
39*2f2c4c7aSAndroid Build Coastguard WorkerTEST_ADDR1 = "2001:4860:4860::8888"
40*2f2c4c7aSAndroid Build Coastguard WorkerTEST_ADDR2 = "2001:4860:4860::8844"
41*2f2c4c7aSAndroid Build Coastguard Worker
42*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_STATS_PROCFILE = "/proc/net/xfrm_stat"
43*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_STATS_OUT_NO_STATES = "XfrmOutNoStates"
44*2f2c4c7aSAndroid Build Coastguard Worker
45*2f2c4c7aSAndroid Build Coastguard Worker# IP addresses to use for tunnel endpoints. For generality, these should be
46*2f2c4c7aSAndroid Build Coastguard Worker# different from the addresses we send packets to.
47*2f2c4c7aSAndroid Build Coastguard WorkerTUNNEL_ENDPOINTS = {4: "8.8.4.4", 6: TEST_ADDR2}
48*2f2c4c7aSAndroid Build Coastguard Worker
49*2f2c4c7aSAndroid Build Coastguard WorkerTEST_SPI = 0x1234
50*2f2c4c7aSAndroid Build Coastguard WorkerTEST_SPI2 = 0x1235
51*2f2c4c7aSAndroid Build Coastguard Worker
52*2f2c4c7aSAndroid Build Coastguard Worker
53*2f2c4c7aSAndroid Build Coastguard Worker
54*2f2c4c7aSAndroid Build Coastguard Workerclass XfrmFunctionalTest(xfrm_base.XfrmLazyTest):
55*2f2c4c7aSAndroid Build Coastguard Worker
56*2f2c4c7aSAndroid Build Coastguard Worker  def assertIsUdpEncapEsp(self, packet, spi, seq, length):
57*2f2c4c7aSAndroid Build Coastguard Worker    protocol = packet.nh if packet.version == 6 else packet.proto
58*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(IPPROTO_UDP, protocol)
59*2f2c4c7aSAndroid Build Coastguard Worker    udp_hdr = packet[scapy.UDP]
60*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(4500, udp_hdr.dport)
61*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(length, len(udp_hdr))
62*2f2c4c7aSAndroid Build Coastguard Worker    esp_hdr, _ = cstruct.Read(bytes(udp_hdr.payload), xfrm.EspHdr)
63*2f2c4c7aSAndroid Build Coastguard Worker    # FIXME: this file currently swaps SPI byte order manually, so SPI needs to
64*2f2c4c7aSAndroid Build Coastguard Worker    # be double-swapped here.
65*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(xfrm.EspHdr((spi, seq)), esp_hdr)
66*2f2c4c7aSAndroid Build Coastguard Worker
67*2f2c4c7aSAndroid Build Coastguard Worker  def CreateNewSa(self, localAddr, remoteAddr, spi, reqId, encap_tmpl,
68*2f2c4c7aSAndroid Build Coastguard Worker                  null_auth=False):
69*2f2c4c7aSAndroid Build Coastguard Worker    auth_algo = (
70*2f2c4c7aSAndroid Build Coastguard Worker        xfrm_base._ALGO_AUTH_NULL if null_auth else xfrm_base._ALGO_HMAC_SHA1)
71*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddSaInfo(localAddr, remoteAddr, spi, xfrm.XFRM_MODE_TRANSPORT,
72*2f2c4c7aSAndroid Build Coastguard Worker                    reqId, xfrm_base._ALGO_CBC_AES_256, auth_algo, None,
73*2f2c4c7aSAndroid Build Coastguard Worker                    encap_tmpl, None, None)
74*2f2c4c7aSAndroid Build Coastguard Worker
75*2f2c4c7aSAndroid Build Coastguard Worker  def testAddSa(self):
76*2f2c4c7aSAndroid Build Coastguard Worker    self.CreateNewSa("::", TEST_ADDR1, TEST_SPI, 3320, None)
77*2f2c4c7aSAndroid Build Coastguard Worker    expected = (
78*2f2c4c7aSAndroid Build Coastguard Worker        "src :: dst 2001:4860:4860::8888\n"
79*2f2c4c7aSAndroid Build Coastguard Worker        "\tproto esp spi 0x00001234 reqid 3320 mode transport\n"
80*2f2c4c7aSAndroid Build Coastguard Worker        "\treplay-window 32 \n"
81*2f2c4c7aSAndroid Build Coastguard Worker        "\tauth-trunc hmac(sha1) 0x%s 96\n"
82*2f2c4c7aSAndroid Build Coastguard Worker        "\tenc cbc(aes) 0x%s\n"
83*2f2c4c7aSAndroid Build Coastguard Worker        "\tsel src ::/0 dst ::/0 \n" % (
84*2f2c4c7aSAndroid Build Coastguard Worker            binascii.hexlify(xfrm_base._AUTHENTICATION_KEY_128).decode("utf-8"),
85*2f2c4c7aSAndroid Build Coastguard Worker            binascii.hexlify(xfrm_base._ENCRYPTION_KEY_256).decode("utf-8")))
86*2f2c4c7aSAndroid Build Coastguard Worker
87*2f2c4c7aSAndroid Build Coastguard Worker    actual = subprocess.check_output("ip xfrm state".split()).decode("utf-8")
88*2f2c4c7aSAndroid Build Coastguard Worker    # Newer versions of IP also show anti-replay context. Don't choke if it's
89*2f2c4c7aSAndroid Build Coastguard Worker    # missing.
90*2f2c4c7aSAndroid Build Coastguard Worker    actual = actual.replace(
91*2f2c4c7aSAndroid Build Coastguard Worker        "\tanti-replay context: seq 0x0, oseq 0x0, bitmap 0x00000000\n", "")
92*2f2c4c7aSAndroid Build Coastguard Worker    try:
93*2f2c4c7aSAndroid Build Coastguard Worker      self.assertMultiLineEqual(expected, actual)
94*2f2c4c7aSAndroid Build Coastguard Worker    finally:
95*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.DeleteSaInfo(TEST_ADDR1, TEST_SPI, IPPROTO_ESP)
96*2f2c4c7aSAndroid Build Coastguard Worker
97*2f2c4c7aSAndroid Build Coastguard Worker  def testFlush(self):
98*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0, len(self.xfrm.DumpSaInfo()))
99*2f2c4c7aSAndroid Build Coastguard Worker    self.CreateNewSa("::", "2000::", TEST_SPI, 1234, None)
100*2f2c4c7aSAndroid Build Coastguard Worker    self.CreateNewSa("0.0.0.0", "192.0.2.1", TEST_SPI, 4321, None)
101*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(2, len(self.xfrm.DumpSaInfo()))
102*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.FlushSaInfo()
103*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0, len(self.xfrm.DumpSaInfo()))
104*2f2c4c7aSAndroid Build Coastguard Worker
105*2f2c4c7aSAndroid Build Coastguard Worker  def _TestSocketPolicy(self, version):
106*2f2c4c7aSAndroid Build Coastguard Worker    # Open a UDP socket and connect it.
107*2f2c4c7aSAndroid Build Coastguard Worker    family = net_test.GetAddressFamily(version)
108*2f2c4c7aSAndroid Build Coastguard Worker    s = socket(family, SOCK_DGRAM, 0)
109*2f2c4c7aSAndroid Build Coastguard Worker    netid = self.RandomNetid()
110*2f2c4c7aSAndroid Build Coastguard Worker    self.SelectInterface(s, netid, "mark")
111*2f2c4c7aSAndroid Build Coastguard Worker
112*2f2c4c7aSAndroid Build Coastguard Worker    remotesockaddr = self.GetRemoteSocketAddress(version)
113*2f2c4c7aSAndroid Build Coastguard Worker    s.connect((remotesockaddr, 53))
114*2f2c4c7aSAndroid Build Coastguard Worker    saddr, sport = s.getsockname()[:2]
115*2f2c4c7aSAndroid Build Coastguard Worker    daddr, dport = s.getpeername()[:2]
116*2f2c4c7aSAndroid Build Coastguard Worker    if version == 5:
117*2f2c4c7aSAndroid Build Coastguard Worker      saddr = saddr.replace("::ffff:", "")
118*2f2c4c7aSAndroid Build Coastguard Worker      daddr = daddr.replace("::ffff:", "")
119*2f2c4c7aSAndroid Build Coastguard Worker
120*2f2c4c7aSAndroid Build Coastguard Worker    reqid = 0
121*2f2c4c7aSAndroid Build Coastguard Worker
122*2f2c4c7aSAndroid Build Coastguard Worker    desc, pkt = packets.UDP(version, saddr, daddr, sport=sport)
123*2f2c4c7aSAndroid Build Coastguard Worker    s.sendto(net_test.UDP_PAYLOAD, (remotesockaddr, 53))
124*2f2c4c7aSAndroid Build Coastguard Worker    self.ExpectPacketOn(netid, "Send after socket, expected %s" % desc, pkt)
125*2f2c4c7aSAndroid Build Coastguard Worker
126*2f2c4c7aSAndroid Build Coastguard Worker    # Using IPv4 XFRM on a dual-stack socket requires setting an AF_INET policy
127*2f2c4c7aSAndroid Build Coastguard Worker    # that's written in terms of IPv4 addresses.
128*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_version = 4 if version == 5 else version
129*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_family = net_test.GetAddressFamily(xfrm_version)
130*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.ApplySocketPolicy(s, xfrm_family, xfrm.XFRM_POLICY_OUT,
131*2f2c4c7aSAndroid Build Coastguard Worker                                TEST_SPI, reqid, None)
132*2f2c4c7aSAndroid Build Coastguard Worker
133*2f2c4c7aSAndroid Build Coastguard Worker    # Because the policy has level set to "require" (the default), attempting
134*2f2c4c7aSAndroid Build Coastguard Worker    # to send a packet results in an error, because there is no SA that
135*2f2c4c7aSAndroid Build Coastguard Worker    # matches the socket policy we set.
136*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(
137*2f2c4c7aSAndroid Build Coastguard Worker        EAGAIN,
138*2f2c4c7aSAndroid Build Coastguard Worker        s.sendto, net_test.UDP_PAYLOAD, (remotesockaddr, 53))
139*2f2c4c7aSAndroid Build Coastguard Worker
140*2f2c4c7aSAndroid Build Coastguard Worker    # If there is a user space key manager, calling sendto() after applying the socket policy
141*2f2c4c7aSAndroid Build Coastguard Worker    # creates an SA whose state is XFRM_STATE_ACQ. So this just deletes it.
142*2f2c4c7aSAndroid Build Coastguard Worker    # If there is no user space key manager, deleting SA returns ESRCH as the error code.
143*2f2c4c7aSAndroid Build Coastguard Worker    try:
144*2f2c4c7aSAndroid Build Coastguard Worker        self.xfrm.DeleteSaInfo(self.GetRemoteAddress(xfrm_version), TEST_SPI, IPPROTO_ESP)
145*2f2c4c7aSAndroid Build Coastguard Worker    except IOError as e:
146*2f2c4c7aSAndroid Build Coastguard Worker        self.assertEqual(ESRCH, e.errno, "Unexpected error when deleting ACQ SA")
147*2f2c4c7aSAndroid Build Coastguard Worker
148*2f2c4c7aSAndroid Build Coastguard Worker    # Adding a matching SA causes the packet to go out encrypted. The SA's
149*2f2c4c7aSAndroid Build Coastguard Worker    # SPI must match the one in our template, and the destination address must
150*2f2c4c7aSAndroid Build Coastguard Worker    # match the packet's destination address (in tunnel mode, it has to match
151*2f2c4c7aSAndroid Build Coastguard Worker    # the tunnel destination).
152*2f2c4c7aSAndroid Build Coastguard Worker    self.CreateNewSa(
153*2f2c4c7aSAndroid Build Coastguard Worker        net_test.GetWildcardAddress(xfrm_version),
154*2f2c4c7aSAndroid Build Coastguard Worker        self.GetRemoteAddress(xfrm_version), TEST_SPI, reqid, None)
155*2f2c4c7aSAndroid Build Coastguard Worker
156*2f2c4c7aSAndroid Build Coastguard Worker    s.sendto(net_test.UDP_PAYLOAD, (remotesockaddr, 53))
157*2f2c4c7aSAndroid Build Coastguard Worker    expected_length = xfrm_base.GetEspPacketLength(xfrm.XFRM_MODE_TRANSPORT,
158*2f2c4c7aSAndroid Build Coastguard Worker                                                version, False,
159*2f2c4c7aSAndroid Build Coastguard Worker                                                net_test.UDP_PAYLOAD,
160*2f2c4c7aSAndroid Build Coastguard Worker                                                xfrm_base._ALGO_HMAC_SHA1,
161*2f2c4c7aSAndroid Build Coastguard Worker                                                xfrm_base._ALGO_CBC_AES_256)
162*2f2c4c7aSAndroid Build Coastguard Worker    self._ExpectEspPacketOn(netid, TEST_SPI, 1, expected_length, None, None)
163*2f2c4c7aSAndroid Build Coastguard Worker
164*2f2c4c7aSAndroid Build Coastguard Worker    # Sending to another destination doesn't work: again, no matching SA.
165*2f2c4c7aSAndroid Build Coastguard Worker    remoteaddr2 = self.GetOtherRemoteSocketAddress(version)
166*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(
167*2f2c4c7aSAndroid Build Coastguard Worker        EAGAIN,
168*2f2c4c7aSAndroid Build Coastguard Worker        s.sendto, net_test.UDP_PAYLOAD, (remoteaddr2, 53))
169*2f2c4c7aSAndroid Build Coastguard Worker
170*2f2c4c7aSAndroid Build Coastguard Worker    # Sending on another socket without the policy applied results in an
171*2f2c4c7aSAndroid Build Coastguard Worker    # unencrypted packet going out.
172*2f2c4c7aSAndroid Build Coastguard Worker    s2 = socket(family, SOCK_DGRAM, 0)
173*2f2c4c7aSAndroid Build Coastguard Worker    self.SelectInterface(s2, netid, "mark")
174*2f2c4c7aSAndroid Build Coastguard Worker    s2.sendto(net_test.UDP_PAYLOAD, (remotesockaddr, 53))
175*2f2c4c7aSAndroid Build Coastguard Worker    pkts = self.ReadAllPacketsOn(netid)
176*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(1, len(pkts))
177*2f2c4c7aSAndroid Build Coastguard Worker    packet = pkts[0]
178*2f2c4c7aSAndroid Build Coastguard Worker
179*2f2c4c7aSAndroid Build Coastguard Worker    protocol = packet.nh if version == 6 else packet.proto
180*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(IPPROTO_UDP, protocol)
181*2f2c4c7aSAndroid Build Coastguard Worker
182*2f2c4c7aSAndroid Build Coastguard Worker    # Deleting the SA causes the first socket to return errors again.
183*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeleteSaInfo(self.GetRemoteAddress(xfrm_version), TEST_SPI,
184*2f2c4c7aSAndroid Build Coastguard Worker                           IPPROTO_ESP)
185*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(
186*2f2c4c7aSAndroid Build Coastguard Worker        EAGAIN,
187*2f2c4c7aSAndroid Build Coastguard Worker        s.sendto, net_test.UDP_PAYLOAD, (remotesockaddr, 53))
188*2f2c4c7aSAndroid Build Coastguard Worker
189*2f2c4c7aSAndroid Build Coastguard Worker    # Clear the socket policy and expect a cleartext packet.
190*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.SetPolicySockopt(s, family, None)
191*2f2c4c7aSAndroid Build Coastguard Worker    s.sendto(net_test.UDP_PAYLOAD, (remotesockaddr, 53))
192*2f2c4c7aSAndroid Build Coastguard Worker    self.ExpectPacketOn(netid, "Send after clear, expected %s" % desc, pkt)
193*2f2c4c7aSAndroid Build Coastguard Worker
194*2f2c4c7aSAndroid Build Coastguard Worker    # Clearing the policy twice is safe.
195*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.SetPolicySockopt(s, family, None)
196*2f2c4c7aSAndroid Build Coastguard Worker    s.sendto(net_test.UDP_PAYLOAD, (remotesockaddr, 53))
197*2f2c4c7aSAndroid Build Coastguard Worker    self.ExpectPacketOn(netid, "Send after clear 2, expected %s" % desc, pkt)
198*2f2c4c7aSAndroid Build Coastguard Worker    s.close()
199*2f2c4c7aSAndroid Build Coastguard Worker
200*2f2c4c7aSAndroid Build Coastguard Worker    # Clearing if a policy was never set is safe.
201*2f2c4c7aSAndroid Build Coastguard Worker    s = socket(AF_INET6, SOCK_DGRAM, 0)
202*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.SetPolicySockopt(s, family, None)
203*2f2c4c7aSAndroid Build Coastguard Worker
204*2f2c4c7aSAndroid Build Coastguard Worker    s.close()
205*2f2c4c7aSAndroid Build Coastguard Worker    s2.close()
206*2f2c4c7aSAndroid Build Coastguard Worker
207*2f2c4c7aSAndroid Build Coastguard Worker  def testSocketPolicyIPv4(self):
208*2f2c4c7aSAndroid Build Coastguard Worker    self._TestSocketPolicy(4)
209*2f2c4c7aSAndroid Build Coastguard Worker
210*2f2c4c7aSAndroid Build Coastguard Worker  def testSocketPolicyIPv6(self):
211*2f2c4c7aSAndroid Build Coastguard Worker    self._TestSocketPolicy(6)
212*2f2c4c7aSAndroid Build Coastguard Worker
213*2f2c4c7aSAndroid Build Coastguard Worker  def testSocketPolicyMapped(self):
214*2f2c4c7aSAndroid Build Coastguard Worker    self._TestSocketPolicy(5)
215*2f2c4c7aSAndroid Build Coastguard Worker
216*2f2c4c7aSAndroid Build Coastguard Worker  # Sets up sockets and marks to correct netid
217*2f2c4c7aSAndroid Build Coastguard Worker  def _SetupUdpEncapSockets(self, version):
218*2f2c4c7aSAndroid Build Coastguard Worker    netid = self.RandomNetid()
219*2f2c4c7aSAndroid Build Coastguard Worker    myaddr = self.MyAddress(version, netid)
220*2f2c4c7aSAndroid Build Coastguard Worker    remoteaddr = self.GetRemoteAddress(version)
221*2f2c4c7aSAndroid Build Coastguard Worker    family = net_test.GetAddressFamily(version)
222*2f2c4c7aSAndroid Build Coastguard Worker
223*2f2c4c7aSAndroid Build Coastguard Worker    # Reserve a port on which to receive UDP encapsulated packets. Sending
224*2f2c4c7aSAndroid Build Coastguard Worker    # packets works without this (and potentially can send packets with a source
225*2f2c4c7aSAndroid Build Coastguard Worker    # port belonging to another application), but receiving requires the port to
226*2f2c4c7aSAndroid Build Coastguard Worker    # be bound and the encapsulation socket option enabled.
227*2f2c4c7aSAndroid Build Coastguard Worker    encap_sock = net_test.Socket(family, SOCK_DGRAM, 0)
228*2f2c4c7aSAndroid Build Coastguard Worker    encap_sock.bind((myaddr, 0))
229*2f2c4c7aSAndroid Build Coastguard Worker    encap_port = encap_sock.getsockname()[1]
230*2f2c4c7aSAndroid Build Coastguard Worker    encap_sock.setsockopt(IPPROTO_UDP, xfrm.UDP_ENCAP, xfrm.UDP_ENCAP_ESPINUDP)
231*2f2c4c7aSAndroid Build Coastguard Worker
232*2f2c4c7aSAndroid Build Coastguard Worker    # Open a socket to send traffic.
233*2f2c4c7aSAndroid Build Coastguard Worker    # TODO: test with a different family than the encap socket.
234*2f2c4c7aSAndroid Build Coastguard Worker    s = socket(family, SOCK_DGRAM, 0)
235*2f2c4c7aSAndroid Build Coastguard Worker    self.SelectInterface(s, netid, "mark")
236*2f2c4c7aSAndroid Build Coastguard Worker    s.connect((remoteaddr, 53))
237*2f2c4c7aSAndroid Build Coastguard Worker
238*2f2c4c7aSAndroid Build Coastguard Worker    return netid, myaddr, remoteaddr, encap_sock, encap_port, s
239*2f2c4c7aSAndroid Build Coastguard Worker
240*2f2c4c7aSAndroid Build Coastguard Worker  # Sets up SAs and applies socket policy to given socket
241*2f2c4c7aSAndroid Build Coastguard Worker  def _SetupUdpEncapSaPair(self, version, myaddr, remoteaddr, in_spi, out_spi,
242*2f2c4c7aSAndroid Build Coastguard Worker                           encap_port, s, use_null_auth):
243*2f2c4c7aSAndroid Build Coastguard Worker    in_reqid = 123
244*2f2c4c7aSAndroid Build Coastguard Worker    out_reqid = 456
245*2f2c4c7aSAndroid Build Coastguard Worker
246*2f2c4c7aSAndroid Build Coastguard Worker    # Create inbound and outbound SAs that specify UDP encapsulation.
247*2f2c4c7aSAndroid Build Coastguard Worker    encaptmpl = xfrm.XfrmEncapTmpl((xfrm.UDP_ENCAP_ESPINUDP, htons(encap_port),
248*2f2c4c7aSAndroid Build Coastguard Worker                                    htons(4500), 16 * b"\x00"))
249*2f2c4c7aSAndroid Build Coastguard Worker    self.CreateNewSa(myaddr, remoteaddr, out_spi, out_reqid, encaptmpl,
250*2f2c4c7aSAndroid Build Coastguard Worker                     use_null_auth)
251*2f2c4c7aSAndroid Build Coastguard Worker
252*2f2c4c7aSAndroid Build Coastguard Worker    # Add an encap template that's the mirror of the outbound one.
253*2f2c4c7aSAndroid Build Coastguard Worker    encaptmpl.sport, encaptmpl.dport = encaptmpl.dport, encaptmpl.sport
254*2f2c4c7aSAndroid Build Coastguard Worker    self.CreateNewSa(remoteaddr, myaddr, in_spi, in_reqid, encaptmpl,
255*2f2c4c7aSAndroid Build Coastguard Worker                     use_null_auth)
256*2f2c4c7aSAndroid Build Coastguard Worker
257*2f2c4c7aSAndroid Build Coastguard Worker    # Apply socket policies to s.
258*2f2c4c7aSAndroid Build Coastguard Worker    family = net_test.GetAddressFamily(version)
259*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.ApplySocketPolicy(s, family, xfrm.XFRM_POLICY_OUT, out_spi,
260*2f2c4c7aSAndroid Build Coastguard Worker                                out_reqid, None)
261*2f2c4c7aSAndroid Build Coastguard Worker
262*2f2c4c7aSAndroid Build Coastguard Worker    # TODO: why does this work without a per-socket policy applied?
263*2f2c4c7aSAndroid Build Coastguard Worker    # The received  packet obviously matches an SA, but don't inbound packets
264*2f2c4c7aSAndroid Build Coastguard Worker    # need to match a policy as well? (b/71541609)
265*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.ApplySocketPolicy(s, family, xfrm.XFRM_POLICY_IN, in_spi,
266*2f2c4c7aSAndroid Build Coastguard Worker                                in_reqid, None)
267*2f2c4c7aSAndroid Build Coastguard Worker
268*2f2c4c7aSAndroid Build Coastguard Worker    # Uncomment for debugging.
269*2f2c4c7aSAndroid Build Coastguard Worker    # subprocess.call("ip xfrm state".split())
270*2f2c4c7aSAndroid Build Coastguard Worker
271*2f2c4c7aSAndroid Build Coastguard Worker  # Check that packets can be sent and received.
272*2f2c4c7aSAndroid Build Coastguard Worker  def _VerifyUdpEncapSocket(self, version, netid, remoteaddr, myaddr, encap_port,
273*2f2c4c7aSAndroid Build Coastguard Worker                           sock, in_spi, out_spi, null_auth, seq_num):
274*2f2c4c7aSAndroid Build Coastguard Worker    # Now send a packet.
275*2f2c4c7aSAndroid Build Coastguard Worker    sock.sendto(net_test.UDP_PAYLOAD, (remoteaddr, 53))
276*2f2c4c7aSAndroid Build Coastguard Worker    srcport = sock.getsockname()[1]
277*2f2c4c7aSAndroid Build Coastguard Worker
278*2f2c4c7aSAndroid Build Coastguard Worker    # Expect to see an UDP encapsulated packet.
279*2f2c4c7aSAndroid Build Coastguard Worker    pkts = self.ReadAllPacketsOn(netid)
280*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(1, len(pkts))
281*2f2c4c7aSAndroid Build Coastguard Worker    packet = pkts[0]
282*2f2c4c7aSAndroid Build Coastguard Worker
283*2f2c4c7aSAndroid Build Coastguard Worker    auth_algo = (
284*2f2c4c7aSAndroid Build Coastguard Worker        xfrm_base._ALGO_AUTH_NULL if null_auth else xfrm_base._ALGO_HMAC_SHA1)
285*2f2c4c7aSAndroid Build Coastguard Worker    expected_len = xfrm_base.GetEspPacketLength(
286*2f2c4c7aSAndroid Build Coastguard Worker        xfrm.XFRM_MODE_TRANSPORT, version, True, net_test.UDP_PAYLOAD,
287*2f2c4c7aSAndroid Build Coastguard Worker        auth_algo, xfrm_base._ALGO_CBC_AES_256)
288*2f2c4c7aSAndroid Build Coastguard Worker    self.assertIsUdpEncapEsp(packet, out_spi, seq_num, expected_len)
289*2f2c4c7aSAndroid Build Coastguard Worker
290*2f2c4c7aSAndroid Build Coastguard Worker    # Now test the receive path. Because we don't know how to decrypt packets,
291*2f2c4c7aSAndroid Build Coastguard Worker    # we just play back the encrypted packet that kernel sent earlier. We swap
292*2f2c4c7aSAndroid Build Coastguard Worker    # the addresses in the IP header to make the packet look like it's bound for
293*2f2c4c7aSAndroid Build Coastguard Worker    # us, but we can't do that for the port numbers because the UDP header is
294*2f2c4c7aSAndroid Build Coastguard Worker    # part of the integrity protected payload, which we can only replay as is.
295*2f2c4c7aSAndroid Build Coastguard Worker    # So the source and destination ports are swapped and the packet appears to
296*2f2c4c7aSAndroid Build Coastguard Worker    # be sent from srcport to port 53. Open another socket on that port, and
297*2f2c4c7aSAndroid Build Coastguard Worker    # apply the inbound policy to it.
298*2f2c4c7aSAndroid Build Coastguard Worker    family = net_test.GetAddressFamily(version)
299*2f2c4c7aSAndroid Build Coastguard Worker    twisted_socket = socket(family, SOCK_DGRAM, 0)
300*2f2c4c7aSAndroid Build Coastguard Worker    csocket.SetSocketTimeout(twisted_socket, 100)
301*2f2c4c7aSAndroid Build Coastguard Worker    twisted_socket.bind((net_test.GetWildcardAddress(version), 53))
302*2f2c4c7aSAndroid Build Coastguard Worker
303*2f2c4c7aSAndroid Build Coastguard Worker    # Save the payload of the packet so we can replay it back to ourselves, and
304*2f2c4c7aSAndroid Build Coastguard Worker    # replace the SPI with our inbound SPI.
305*2f2c4c7aSAndroid Build Coastguard Worker    payload = bytes(packet.payload)[8:]
306*2f2c4c7aSAndroid Build Coastguard Worker    spi_seq = xfrm.EspHdr((in_spi, seq_num)).Pack()
307*2f2c4c7aSAndroid Build Coastguard Worker    payload = spi_seq + payload[len(spi_seq):]
308*2f2c4c7aSAndroid Build Coastguard Worker
309*2f2c4c7aSAndroid Build Coastguard Worker    sainfo = self.xfrm.FindSaInfo(in_spi)
310*2f2c4c7aSAndroid Build Coastguard Worker    start_integrity_failures = sainfo.stats.integrity_failed
311*2f2c4c7aSAndroid Build Coastguard Worker
312*2f2c4c7aSAndroid Build Coastguard Worker    # Now play back the valid packet and check that we receive it.
313*2f2c4c7aSAndroid Build Coastguard Worker    ip = {4: scapy.IP, 6: scapy.IPv6}[version]
314*2f2c4c7aSAndroid Build Coastguard Worker    incoming = (ip(src=remoteaddr, dst=myaddr) /
315*2f2c4c7aSAndroid Build Coastguard Worker                scapy.UDP(sport=4500, dport=encap_port) / payload)
316*2f2c4c7aSAndroid Build Coastguard Worker    incoming = ip(bytes(incoming))
317*2f2c4c7aSAndroid Build Coastguard Worker    self.ReceivePacketOn(netid, incoming)
318*2f2c4c7aSAndroid Build Coastguard Worker
319*2f2c4c7aSAndroid Build Coastguard Worker    sainfo = self.xfrm.FindSaInfo(in_spi)
320*2f2c4c7aSAndroid Build Coastguard Worker
321*2f2c4c7aSAndroid Build Coastguard Worker    # TODO: break this out into a separate test
322*2f2c4c7aSAndroid Build Coastguard Worker    # If our SPIs are different, and we aren't using null authentication,
323*2f2c4c7aSAndroid Build Coastguard Worker    # we expect the packet to be dropped. We also expect that the integrity
324*2f2c4c7aSAndroid Build Coastguard Worker    # failure counter to increase, as SPIs are part of the authenticated or
325*2f2c4c7aSAndroid Build Coastguard Worker    # integrity-verified portion of the packet.
326*2f2c4c7aSAndroid Build Coastguard Worker    if not null_auth and in_spi != out_spi:
327*2f2c4c7aSAndroid Build Coastguard Worker      self.assertRaisesErrno(EAGAIN, twisted_socket.recv, 4096)
328*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(start_integrity_failures + 1,
329*2f2c4c7aSAndroid Build Coastguard Worker                        sainfo.stats.integrity_failed)
330*2f2c4c7aSAndroid Build Coastguard Worker    else:
331*2f2c4c7aSAndroid Build Coastguard Worker      data, src = twisted_socket.recvfrom(4096)
332*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(net_test.UDP_PAYLOAD, data)
333*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual((remoteaddr, srcport), src[:2])
334*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(start_integrity_failures, sainfo.stats.integrity_failed)
335*2f2c4c7aSAndroid Build Coastguard Worker
336*2f2c4c7aSAndroid Build Coastguard Worker    # Check that unencrypted packets on twisted_socket are not received.
337*2f2c4c7aSAndroid Build Coastguard Worker    unencrypted = (
338*2f2c4c7aSAndroid Build Coastguard Worker        ip(src=remoteaddr, dst=myaddr) / scapy.UDP(
339*2f2c4c7aSAndroid Build Coastguard Worker            sport=srcport, dport=53) / net_test.UDP_PAYLOAD)
340*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(EAGAIN, twisted_socket.recv, 4096)
341*2f2c4c7aSAndroid Build Coastguard Worker
342*2f2c4c7aSAndroid Build Coastguard Worker    twisted_socket.close()
343*2f2c4c7aSAndroid Build Coastguard Worker
344*2f2c4c7aSAndroid Build Coastguard Worker  def _RunEncapSocketPolicyTest(self, version, in_spi, out_spi, use_null_auth):
345*2f2c4c7aSAndroid Build Coastguard Worker    netid, myaddr, remoteaddr, encap_sock, encap_port, s = \
346*2f2c4c7aSAndroid Build Coastguard Worker        self._SetupUdpEncapSockets(version)
347*2f2c4c7aSAndroid Build Coastguard Worker
348*2f2c4c7aSAndroid Build Coastguard Worker    self._SetupUdpEncapSaPair(version, myaddr, remoteaddr, in_spi, out_spi,
349*2f2c4c7aSAndroid Build Coastguard Worker                              encap_port, s, use_null_auth)
350*2f2c4c7aSAndroid Build Coastguard Worker
351*2f2c4c7aSAndroid Build Coastguard Worker    # Check that UDP encap sockets work with socket policy and given SAs
352*2f2c4c7aSAndroid Build Coastguard Worker    self._VerifyUdpEncapSocket(version, netid, remoteaddr, myaddr, encap_port,
353*2f2c4c7aSAndroid Build Coastguard Worker                               s, in_spi, out_spi, use_null_auth, 1)
354*2f2c4c7aSAndroid Build Coastguard Worker    encap_sock.close()
355*2f2c4c7aSAndroid Build Coastguard Worker    s.close()
356*2f2c4c7aSAndroid Build Coastguard Worker
357*2f2c4c7aSAndroid Build Coastguard Worker  # TODO: Add tests for ESP (non-encap) sockets.
358*2f2c4c7aSAndroid Build Coastguard Worker  def testUdpEncapSameSpisNullAuth(self):
359*2f2c4c7aSAndroid Build Coastguard Worker    # Use the same SPI both inbound and outbound because this lets us receive
360*2f2c4c7aSAndroid Build Coastguard Worker    # encrypted packets by simply replaying the packets the kernel sends
361*2f2c4c7aSAndroid Build Coastguard Worker    # without having to disable authentication
362*2f2c4c7aSAndroid Build Coastguard Worker    self._RunEncapSocketPolicyTest(4, TEST_SPI, TEST_SPI, True)
363*2f2c4c7aSAndroid Build Coastguard Worker
364*2f2c4c7aSAndroid Build Coastguard Worker  def testUdpEncapSameSpis(self):
365*2f2c4c7aSAndroid Build Coastguard Worker    self._RunEncapSocketPolicyTest(4, TEST_SPI, TEST_SPI, False)
366*2f2c4c7aSAndroid Build Coastguard Worker
367*2f2c4c7aSAndroid Build Coastguard Worker  def testUdpEncapDifferentSpisNullAuth(self):
368*2f2c4c7aSAndroid Build Coastguard Worker    self._RunEncapSocketPolicyTest(4, TEST_SPI, TEST_SPI2, True)
369*2f2c4c7aSAndroid Build Coastguard Worker
370*2f2c4c7aSAndroid Build Coastguard Worker  def testUdpEncapDifferentSpis(self):
371*2f2c4c7aSAndroid Build Coastguard Worker    self._RunEncapSocketPolicyTest(4, TEST_SPI, TEST_SPI2, False)
372*2f2c4c7aSAndroid Build Coastguard Worker
373*2f2c4c7aSAndroid Build Coastguard Worker  def testUdpEncapRekey(self):
374*2f2c4c7aSAndroid Build Coastguard Worker    # Select the two SPIs that will be used
375*2f2c4c7aSAndroid Build Coastguard Worker    start_spi = TEST_SPI
376*2f2c4c7aSAndroid Build Coastguard Worker    rekey_spi = TEST_SPI2
377*2f2c4c7aSAndroid Build Coastguard Worker
378*2f2c4c7aSAndroid Build Coastguard Worker    # Setup sockets
379*2f2c4c7aSAndroid Build Coastguard Worker    netid, myaddr, remoteaddr, encap_sock, encap_port, s = \
380*2f2c4c7aSAndroid Build Coastguard Worker        self._SetupUdpEncapSockets(4)
381*2f2c4c7aSAndroid Build Coastguard Worker
382*2f2c4c7aSAndroid Build Coastguard Worker    # The SAs must use null authentication, since we change SPIs on the fly
383*2f2c4c7aSAndroid Build Coastguard Worker    # Without null authentication, this would result in an ESP authentication
384*2f2c4c7aSAndroid Build Coastguard Worker    # error since the SPI is part of the authenticated section. The packet
385*2f2c4c7aSAndroid Build Coastguard Worker    # would then be dropped
386*2f2c4c7aSAndroid Build Coastguard Worker    self._SetupUdpEncapSaPair(4, myaddr, remoteaddr, start_spi, start_spi,
387*2f2c4c7aSAndroid Build Coastguard Worker                              encap_port, s, True)
388*2f2c4c7aSAndroid Build Coastguard Worker
389*2f2c4c7aSAndroid Build Coastguard Worker    # Check that UDP encap sockets work with socket policy and given SAs
390*2f2c4c7aSAndroid Build Coastguard Worker    self._VerifyUdpEncapSocket(4, netid, remoteaddr, myaddr, encap_port, s,
391*2f2c4c7aSAndroid Build Coastguard Worker                               start_spi, start_spi, True, 1)
392*2f2c4c7aSAndroid Build Coastguard Worker
393*2f2c4c7aSAndroid Build Coastguard Worker    # Rekey this socket using the make-before-break paradigm. First we create
394*2f2c4c7aSAndroid Build Coastguard Worker    # new SAs, update the per-socket policies, and only then remove the old SAs
395*2f2c4c7aSAndroid Build Coastguard Worker    #
396*2f2c4c7aSAndroid Build Coastguard Worker    # This allows us to switch to the new SA without breaking the outbound path.
397*2f2c4c7aSAndroid Build Coastguard Worker    self._SetupUdpEncapSaPair(4, myaddr, remoteaddr, rekey_spi, rekey_spi,
398*2f2c4c7aSAndroid Build Coastguard Worker                              encap_port, s, True)
399*2f2c4c7aSAndroid Build Coastguard Worker
400*2f2c4c7aSAndroid Build Coastguard Worker    # Check that UDP encap socket works with updated socket policy, sending
401*2f2c4c7aSAndroid Build Coastguard Worker    # using new SA, but receiving on both old and new SAs
402*2f2c4c7aSAndroid Build Coastguard Worker    self._VerifyUdpEncapSocket(4, netid, remoteaddr, myaddr, encap_port, s,
403*2f2c4c7aSAndroid Build Coastguard Worker                               rekey_spi, rekey_spi, True, 1)
404*2f2c4c7aSAndroid Build Coastguard Worker    self._VerifyUdpEncapSocket(4, netid, remoteaddr, myaddr, encap_port, s,
405*2f2c4c7aSAndroid Build Coastguard Worker                               start_spi, rekey_spi, True, 2)
406*2f2c4c7aSAndroid Build Coastguard Worker
407*2f2c4c7aSAndroid Build Coastguard Worker    # Delete old SAs
408*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeleteSaInfo(remoteaddr, start_spi, IPPROTO_ESP)
409*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeleteSaInfo(myaddr, start_spi, IPPROTO_ESP)
410*2f2c4c7aSAndroid Build Coastguard Worker
411*2f2c4c7aSAndroid Build Coastguard Worker    # Check that UDP encap socket works with updated socket policy and new SAs
412*2f2c4c7aSAndroid Build Coastguard Worker    self._VerifyUdpEncapSocket(4, netid, remoteaddr, myaddr, encap_port, s,
413*2f2c4c7aSAndroid Build Coastguard Worker                               rekey_spi, rekey_spi, True, 3)
414*2f2c4c7aSAndroid Build Coastguard Worker    encap_sock.close()
415*2f2c4c7aSAndroid Build Coastguard Worker    s.close()
416*2f2c4c7aSAndroid Build Coastguard Worker
417*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckUDPEncapRecv(self, version, mode):
418*2f2c4c7aSAndroid Build Coastguard Worker    netid, myaddr, remoteaddr, encap_sock, encap_port, s = \
419*2f2c4c7aSAndroid Build Coastguard Worker        self._SetupUdpEncapSockets(version)
420*2f2c4c7aSAndroid Build Coastguard Worker
421*2f2c4c7aSAndroid Build Coastguard Worker    # Create inbound and outbound SAs that specify UDP encapsulation.
422*2f2c4c7aSAndroid Build Coastguard Worker    reqid = 123
423*2f2c4c7aSAndroid Build Coastguard Worker    encaptmpl = xfrm.XfrmEncapTmpl((xfrm.UDP_ENCAP_ESPINUDP, htons(encap_port),
424*2f2c4c7aSAndroid Build Coastguard Worker                                    htons(4500), 16 * b"\x00"))
425*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddSaInfo(remoteaddr, myaddr, TEST_SPI, mode, reqid,
426*2f2c4c7aSAndroid Build Coastguard Worker                    xfrm_base._ALGO_CRYPT_NULL, xfrm_base._ALGO_AUTH_NULL, None,
427*2f2c4c7aSAndroid Build Coastguard Worker                    encaptmpl, None, None)
428*2f2c4c7aSAndroid Build Coastguard Worker
429*2f2c4c7aSAndroid Build Coastguard Worker    sainfo = self.xfrm.FindSaInfo(TEST_SPI)
430*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0, sainfo.curlft.packets)
431*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0, sainfo.curlft.bytes)
432*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0, sainfo.stats.integrity_failed)
433*2f2c4c7aSAndroid Build Coastguard Worker
434*2f2c4c7aSAndroid Build Coastguard Worker    IpType = {4: scapy.IP, 6: scapy.IPv6}[version]
435*2f2c4c7aSAndroid Build Coastguard Worker    if mode == xfrm.XFRM_MODE_TRANSPORT:
436*2f2c4c7aSAndroid Build Coastguard Worker      # Due to a bug in the IPv6 UDP encap code, there must be at least 32
437*2f2c4c7aSAndroid Build Coastguard Worker      # bytes after the ESP header or the packet will be dropped.
438*2f2c4c7aSAndroid Build Coastguard Worker      # 8 (UDP header) + 18 (payload) + 2 (ESP trailer) = 28, dropped
439*2f2c4c7aSAndroid Build Coastguard Worker      # 8 (UDP header) + 19 (payload) + 4 (ESP trailer) = 32, received
440*2f2c4c7aSAndroid Build Coastguard Worker      # There is a similar bug in IPv4 encap, but the minimum is only 12 bytes,
441*2f2c4c7aSAndroid Build Coastguard Worker      # which is much less likely to occur. This doesn't affect tunnel mode
442*2f2c4c7aSAndroid Build Coastguard Worker      # because IP headers are always at least 20 bytes long.
443*2f2c4c7aSAndroid Build Coastguard Worker      data = 19 * b"a"
444*2f2c4c7aSAndroid Build Coastguard Worker      datalen = len(data)
445*2f2c4c7aSAndroid Build Coastguard Worker      # TODO: update scapy and use scapy.ESP instead of manually generating ESP header.
446*2f2c4c7aSAndroid Build Coastguard Worker      inner_pkt = xfrm.EspHdr(spi=TEST_SPI, seqnum=1).Pack() + bytes(
447*2f2c4c7aSAndroid Build Coastguard Worker          scapy.UDP(sport=443, dport=32123) / data) + bytes(
448*2f2c4c7aSAndroid Build Coastguard Worker          xfrm_base.GetEspTrailer(len(data), IPPROTO_UDP))
449*2f2c4c7aSAndroid Build Coastguard Worker      input_pkt = (IpType(src=remoteaddr, dst=myaddr) /
450*2f2c4c7aSAndroid Build Coastguard Worker                   scapy.UDP(sport=4500, dport=encap_port) /
451*2f2c4c7aSAndroid Build Coastguard Worker                   inner_pkt)
452*2f2c4c7aSAndroid Build Coastguard Worker    else:
453*2f2c4c7aSAndroid Build Coastguard Worker      # TODO: test IPv4 in IPv6 encap and vice versa.
454*2f2c4c7aSAndroid Build Coastguard Worker      data = b""  # Empty UDP payload
455*2f2c4c7aSAndroid Build Coastguard Worker      datalen = {4: 20, 6: 40}[version] + len(data)
456*2f2c4c7aSAndroid Build Coastguard Worker      # TODO: update scapy and use scapy.ESP instead of manually generating ESP header.
457*2f2c4c7aSAndroid Build Coastguard Worker      inner_pkt = xfrm.EspHdr(spi=TEST_SPI, seqnum=1).Pack() + bytes(
458*2f2c4c7aSAndroid Build Coastguard Worker          IpType(src=remoteaddr, dst=myaddr) /
459*2f2c4c7aSAndroid Build Coastguard Worker          scapy.UDP(sport=443, dport=32123) / data) + bytes(
460*2f2c4c7aSAndroid Build Coastguard Worker          xfrm_base.GetEspTrailer(len(data), {4: IPPROTO_IPIP, 6: IPPROTO_IPV6}[version]))
461*2f2c4c7aSAndroid Build Coastguard Worker      input_pkt = (IpType(src=remoteaddr, dst=myaddr) /
462*2f2c4c7aSAndroid Build Coastguard Worker                   scapy.UDP(sport=4500, dport=encap_port) /
463*2f2c4c7aSAndroid Build Coastguard Worker                   inner_pkt)
464*2f2c4c7aSAndroid Build Coastguard Worker
465*2f2c4c7aSAndroid Build Coastguard Worker    # input_pkt.show2()
466*2f2c4c7aSAndroid Build Coastguard Worker    self.ReceivePacketOn(netid, input_pkt)
467*2f2c4c7aSAndroid Build Coastguard Worker
468*2f2c4c7aSAndroid Build Coastguard Worker    sainfo = self.xfrm.FindSaInfo(TEST_SPI)
469*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(1, sainfo.curlft.packets)
470*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(datalen + 8, sainfo.curlft.bytes)
471*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0, sainfo.stats.integrity_failed)
472*2f2c4c7aSAndroid Build Coastguard Worker
473*2f2c4c7aSAndroid Build Coastguard Worker    # Uncomment for debugging.
474*2f2c4c7aSAndroid Build Coastguard Worker    # subprocess.call("ip -s xfrm state".split())
475*2f2c4c7aSAndroid Build Coastguard Worker
476*2f2c4c7aSAndroid Build Coastguard Worker    encap_sock.close()
477*2f2c4c7aSAndroid Build Coastguard Worker    s.close()
478*2f2c4c7aSAndroid Build Coastguard Worker
479*2f2c4c7aSAndroid Build Coastguard Worker  def testIPv4UDPEncapRecvTransport(self):
480*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckUDPEncapRecv(4, xfrm.XFRM_MODE_TRANSPORT)
481*2f2c4c7aSAndroid Build Coastguard Worker
482*2f2c4c7aSAndroid Build Coastguard Worker  def testIPv4UDPEncapRecvTunnel(self):
483*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckUDPEncapRecv(4, xfrm.XFRM_MODE_TUNNEL)
484*2f2c4c7aSAndroid Build Coastguard Worker
485*2f2c4c7aSAndroid Build Coastguard Worker  # IPv6 UDP encap is broken between:
486*2f2c4c7aSAndroid Build Coastguard Worker  # 4db4075f92af ("esp6: fix check on ipv6_skip_exthdr's return value") and
487*2f2c4c7aSAndroid Build Coastguard Worker  # 5f9c55c8066b ("ipv6: check return value of ipv6_skip_exthdr")
488*2f2c4c7aSAndroid Build Coastguard Worker  @unittest.skipUnless(net_test.KernelAtLeast([(5, 10, 108), (5, 15, 31)]) or
489*2f2c4c7aSAndroid Build Coastguard Worker                       net_test.NonGXI(5, 10),
490*2f2c4c7aSAndroid Build Coastguard Worker                       reason="Unsupported or broken on current kernel")
491*2f2c4c7aSAndroid Build Coastguard Worker  def testIPv6UDPEncapRecvTransport(self):
492*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckUDPEncapRecv(6, xfrm.XFRM_MODE_TRANSPORT)
493*2f2c4c7aSAndroid Build Coastguard Worker
494*2f2c4c7aSAndroid Build Coastguard Worker  @unittest.skipUnless(net_test.KernelAtLeast([(5, 10, 108), (5, 15, 31)]) or
495*2f2c4c7aSAndroid Build Coastguard Worker                       net_test.NonGXI(5, 10),
496*2f2c4c7aSAndroid Build Coastguard Worker                       reason="Unsupported or broken on current kernel")
497*2f2c4c7aSAndroid Build Coastguard Worker  def testIPv6UDPEncapRecvTunnel(self):
498*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckUDPEncapRecv(6, xfrm.XFRM_MODE_TUNNEL)
499*2f2c4c7aSAndroid Build Coastguard Worker
500*2f2c4c7aSAndroid Build Coastguard Worker  def testAllocSpecificSpi(self):
501*2f2c4c7aSAndroid Build Coastguard Worker    spi = 0xABCD
502*2f2c4c7aSAndroid Build Coastguard Worker    new_sa = self.xfrm.AllocSpi("::", IPPROTO_ESP, spi, spi)
503*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(spi, new_sa.id.spi)
504*2f2c4c7aSAndroid Build Coastguard Worker
505*2f2c4c7aSAndroid Build Coastguard Worker  def testAllocSpecificSpiUnavailable(self):
506*2f2c4c7aSAndroid Build Coastguard Worker    """Attempt to allocate the same SPI twice."""
507*2f2c4c7aSAndroid Build Coastguard Worker    spi = 0xABCD
508*2f2c4c7aSAndroid Build Coastguard Worker    new_sa = self.xfrm.AllocSpi("::", IPPROTO_ESP, spi, spi)
509*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(spi, new_sa.id.spi)
510*2f2c4c7aSAndroid Build Coastguard Worker    with self.assertRaisesErrno(ENOENT):
511*2f2c4c7aSAndroid Build Coastguard Worker      new_sa = self.xfrm.AllocSpi("::", IPPROTO_ESP, spi, spi)
512*2f2c4c7aSAndroid Build Coastguard Worker
513*2f2c4c7aSAndroid Build Coastguard Worker  def testAllocRangeSpi(self):
514*2f2c4c7aSAndroid Build Coastguard Worker    start, end = 0xABCD0, 0xABCDF
515*2f2c4c7aSAndroid Build Coastguard Worker    new_sa = self.xfrm.AllocSpi("::", IPPROTO_ESP, start, end)
516*2f2c4c7aSAndroid Build Coastguard Worker    spi = new_sa.id.spi
517*2f2c4c7aSAndroid Build Coastguard Worker    self.assertGreaterEqual(spi, start)
518*2f2c4c7aSAndroid Build Coastguard Worker    self.assertLessEqual(spi, end)
519*2f2c4c7aSAndroid Build Coastguard Worker
520*2f2c4c7aSAndroid Build Coastguard Worker  def testAllocRangeSpiUnavailable(self):
521*2f2c4c7aSAndroid Build Coastguard Worker    """Attempt to allocate N+1 SPIs from a range of size N."""
522*2f2c4c7aSAndroid Build Coastguard Worker    start, end = 0xABCD0, 0xABCDF
523*2f2c4c7aSAndroid Build Coastguard Worker    range_size = end - start + 1
524*2f2c4c7aSAndroid Build Coastguard Worker    spis = set()
525*2f2c4c7aSAndroid Build Coastguard Worker    # Assert that allocating SPI fails when none are available.
526*2f2c4c7aSAndroid Build Coastguard Worker    with self.assertRaisesErrno(ENOENT):
527*2f2c4c7aSAndroid Build Coastguard Worker      # Allocating range_size + 1 SPIs is guaranteed to fail.  Due to the way
528*2f2c4c7aSAndroid Build Coastguard Worker      # kernel picks random SPIs, this has a high probability of failing before
529*2f2c4c7aSAndroid Build Coastguard Worker      # reaching that limit.
530*2f2c4c7aSAndroid Build Coastguard Worker      for i in range(range_size + 1):
531*2f2c4c7aSAndroid Build Coastguard Worker        new_sa = self.xfrm.AllocSpi("::", IPPROTO_ESP, start, end)
532*2f2c4c7aSAndroid Build Coastguard Worker        spi = new_sa.id.spi
533*2f2c4c7aSAndroid Build Coastguard Worker        self.assertNotIn(spi, spis)
534*2f2c4c7aSAndroid Build Coastguard Worker        spis.add(spi)
535*2f2c4c7aSAndroid Build Coastguard Worker
536*2f2c4c7aSAndroid Build Coastguard Worker  def testSocketPolicyDstCacheV6(self):
537*2f2c4c7aSAndroid Build Coastguard Worker    self._TestSocketPolicyDstCache(6)
538*2f2c4c7aSAndroid Build Coastguard Worker
539*2f2c4c7aSAndroid Build Coastguard Worker  def testSocketPolicyDstCacheV4(self):
540*2f2c4c7aSAndroid Build Coastguard Worker    self._TestSocketPolicyDstCache(4)
541*2f2c4c7aSAndroid Build Coastguard Worker
542*2f2c4c7aSAndroid Build Coastguard Worker  def _TestSocketPolicyDstCache(self, version):
543*2f2c4c7aSAndroid Build Coastguard Worker    """Test that destination cache is cleared with socket policy.
544*2f2c4c7aSAndroid Build Coastguard Worker
545*2f2c4c7aSAndroid Build Coastguard Worker    This relies on the fact that connect() on a UDP socket populates the
546*2f2c4c7aSAndroid Build Coastguard Worker    destination cache.
547*2f2c4c7aSAndroid Build Coastguard Worker    """
548*2f2c4c7aSAndroid Build Coastguard Worker
549*2f2c4c7aSAndroid Build Coastguard Worker    # Create UDP socket.
550*2f2c4c7aSAndroid Build Coastguard Worker    family = net_test.GetAddressFamily(version)
551*2f2c4c7aSAndroid Build Coastguard Worker    netid = self.RandomNetid()
552*2f2c4c7aSAndroid Build Coastguard Worker    s = socket(family, SOCK_DGRAM, 0)
553*2f2c4c7aSAndroid Build Coastguard Worker    self.SelectInterface(s, netid, "mark")
554*2f2c4c7aSAndroid Build Coastguard Worker
555*2f2c4c7aSAndroid Build Coastguard Worker    # Populate the socket's destination cache.
556*2f2c4c7aSAndroid Build Coastguard Worker    remote = self.GetRemoteAddress(version)
557*2f2c4c7aSAndroid Build Coastguard Worker    s.connect((remote, 53))
558*2f2c4c7aSAndroid Build Coastguard Worker
559*2f2c4c7aSAndroid Build Coastguard Worker    # Apply a policy to the socket. Should clear dst cache.
560*2f2c4c7aSAndroid Build Coastguard Worker    reqid = 123
561*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.ApplySocketPolicy(s, family, xfrm.XFRM_POLICY_OUT,
562*2f2c4c7aSAndroid Build Coastguard Worker                                TEST_SPI, reqid, None)
563*2f2c4c7aSAndroid Build Coastguard Worker
564*2f2c4c7aSAndroid Build Coastguard Worker    # Policy with no matching SA should result in EAGAIN. If destination cache
565*2f2c4c7aSAndroid Build Coastguard Worker    # failed to clear, then the UDP packet will be sent normally.
566*2f2c4c7aSAndroid Build Coastguard Worker    with self.assertRaisesErrno(EAGAIN):
567*2f2c4c7aSAndroid Build Coastguard Worker      s.send(net_test.UDP_PAYLOAD)
568*2f2c4c7aSAndroid Build Coastguard Worker    self.ExpectNoPacketsOn(netid, "Packet not blocked by policy")
569*2f2c4c7aSAndroid Build Coastguard Worker    s.close()
570*2f2c4c7aSAndroid Build Coastguard Worker
571*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckNullEncryptionTunnelMode(self, version):
572*2f2c4c7aSAndroid Build Coastguard Worker    family = net_test.GetAddressFamily(version)
573*2f2c4c7aSAndroid Build Coastguard Worker    netid = self.RandomNetid()
574*2f2c4c7aSAndroid Build Coastguard Worker    local_addr = self.MyAddress(version, netid)
575*2f2c4c7aSAndroid Build Coastguard Worker    remote_addr = self.GetRemoteAddress(version)
576*2f2c4c7aSAndroid Build Coastguard Worker
577*2f2c4c7aSAndroid Build Coastguard Worker    # Borrow the address of another netId as the source address of the tunnel
578*2f2c4c7aSAndroid Build Coastguard Worker    tun_local = self.MyAddress(version, self.RandomNetid(netid))
579*2f2c4c7aSAndroid Build Coastguard Worker    # For generality, pick a tunnel endpoint that's not the address we
580*2f2c4c7aSAndroid Build Coastguard Worker    # connect the socket to.
581*2f2c4c7aSAndroid Build Coastguard Worker    tun_remote = TUNNEL_ENDPOINTS[version]
582*2f2c4c7aSAndroid Build Coastguard Worker
583*2f2c4c7aSAndroid Build Coastguard Worker    # Output
584*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddSaInfo(
585*2f2c4c7aSAndroid Build Coastguard Worker        tun_local, tun_remote, 0xABCD, xfrm.XFRM_MODE_TUNNEL, 123,
586*2f2c4c7aSAndroid Build Coastguard Worker        xfrm_base._ALGO_CRYPT_NULL, xfrm_base._ALGO_AUTH_NULL,
587*2f2c4c7aSAndroid Build Coastguard Worker        None, None, None, netid)
588*2f2c4c7aSAndroid Build Coastguard Worker    # Input
589*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddSaInfo(
590*2f2c4c7aSAndroid Build Coastguard Worker        tun_remote, tun_local, 0x9876, xfrm.XFRM_MODE_TUNNEL, 456,
591*2f2c4c7aSAndroid Build Coastguard Worker        xfrm_base._ALGO_CRYPT_NULL, xfrm_base._ALGO_AUTH_NULL,
592*2f2c4c7aSAndroid Build Coastguard Worker        None, None, None, None)
593*2f2c4c7aSAndroid Build Coastguard Worker
594*2f2c4c7aSAndroid Build Coastguard Worker    sock = net_test.UDPSocket(family)
595*2f2c4c7aSAndroid Build Coastguard Worker    self.SelectInterface(sock, netid, "mark")
596*2f2c4c7aSAndroid Build Coastguard Worker    sock.bind((local_addr, 0))
597*2f2c4c7aSAndroid Build Coastguard Worker    local_port = sock.getsockname()[1]
598*2f2c4c7aSAndroid Build Coastguard Worker    remote_port = 5555
599*2f2c4c7aSAndroid Build Coastguard Worker
600*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.ApplySocketPolicy(
601*2f2c4c7aSAndroid Build Coastguard Worker        sock, family, xfrm.XFRM_POLICY_OUT, 0xABCD, 123,
602*2f2c4c7aSAndroid Build Coastguard Worker        (tun_local, tun_remote))
603*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.ApplySocketPolicy(
604*2f2c4c7aSAndroid Build Coastguard Worker        sock, family, xfrm.XFRM_POLICY_IN, 0x9876, 456,
605*2f2c4c7aSAndroid Build Coastguard Worker        (tun_remote, tun_local))
606*2f2c4c7aSAndroid Build Coastguard Worker
607*2f2c4c7aSAndroid Build Coastguard Worker    # Create and receive an ESP packet.
608*2f2c4c7aSAndroid Build Coastguard Worker    IpType = {4: scapy.IP, 6: scapy.IPv6}[version]
609*2f2c4c7aSAndroid Build Coastguard Worker    input_pkt = (IpType(src=remote_addr, dst=local_addr) /
610*2f2c4c7aSAndroid Build Coastguard Worker                 scapy.UDP(sport=remote_port, dport=local_port) /
611*2f2c4c7aSAndroid Build Coastguard Worker                 b"input hello")
612*2f2c4c7aSAndroid Build Coastguard Worker    input_pkt = IpType(bytes(input_pkt)) # Compute length, checksum.
613*2f2c4c7aSAndroid Build Coastguard Worker    input_pkt = xfrm_base.EncryptPacketWithNull(input_pkt, 0x9876,
614*2f2c4c7aSAndroid Build Coastguard Worker                                                1, (tun_remote, tun_local))
615*2f2c4c7aSAndroid Build Coastguard Worker
616*2f2c4c7aSAndroid Build Coastguard Worker    self.ReceivePacketOn(netid, input_pkt)
617*2f2c4c7aSAndroid Build Coastguard Worker    msg, addr = sock.recvfrom(1024)
618*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(b"input hello", msg)
619*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual((remote_addr, remote_port), addr[:2])
620*2f2c4c7aSAndroid Build Coastguard Worker
621*2f2c4c7aSAndroid Build Coastguard Worker    # Send and capture a packet.
622*2f2c4c7aSAndroid Build Coastguard Worker    sock.sendto(b"output hello", (remote_addr, remote_port))
623*2f2c4c7aSAndroid Build Coastguard Worker    packets = self.ReadAllPacketsOn(netid)
624*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(1, len(packets))
625*2f2c4c7aSAndroid Build Coastguard Worker    output_pkt = packets[0]
626*2f2c4c7aSAndroid Build Coastguard Worker    output_pkt, esp_hdr = xfrm_base.DecryptPacketWithNull(output_pkt)
627*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(output_pkt[scapy.UDP].len, len(b"output_hello") + 8)
628*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(remote_addr, output_pkt.dst)
629*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(remote_port, output_pkt[scapy.UDP].dport)
630*2f2c4c7aSAndroid Build Coastguard Worker    # length of the payload plus the UDP header
631*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(b"output hello", bytes(output_pkt[scapy.UDP].payload))
632*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0xABCD, esp_hdr.spi)
633*2f2c4c7aSAndroid Build Coastguard Worker    sock.close()
634*2f2c4c7aSAndroid Build Coastguard Worker
635*2f2c4c7aSAndroid Build Coastguard Worker  def testNullEncryptionTunnelMode(self):
636*2f2c4c7aSAndroid Build Coastguard Worker    """Verify null encryption in tunnel mode.
637*2f2c4c7aSAndroid Build Coastguard Worker
638*2f2c4c7aSAndroid Build Coastguard Worker    This test verifies both manual assembly and disassembly of UDP packets
639*2f2c4c7aSAndroid Build Coastguard Worker    with ESP in IPsec tunnel mode.
640*2f2c4c7aSAndroid Build Coastguard Worker    """
641*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 6]:
642*2f2c4c7aSAndroid Build Coastguard Worker      self._CheckNullEncryptionTunnelMode(version)
643*2f2c4c7aSAndroid Build Coastguard Worker
644*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckNullEncryptionTransportMode(self, version):
645*2f2c4c7aSAndroid Build Coastguard Worker    family = net_test.GetAddressFamily(version)
646*2f2c4c7aSAndroid Build Coastguard Worker    netid = self.RandomNetid()
647*2f2c4c7aSAndroid Build Coastguard Worker    local_addr = self.MyAddress(version, netid)
648*2f2c4c7aSAndroid Build Coastguard Worker    remote_addr = self.GetRemoteAddress(version)
649*2f2c4c7aSAndroid Build Coastguard Worker
650*2f2c4c7aSAndroid Build Coastguard Worker    # Output
651*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddSaInfo(
652*2f2c4c7aSAndroid Build Coastguard Worker        local_addr, remote_addr, 0xABCD, xfrm.XFRM_MODE_TRANSPORT, 123,
653*2f2c4c7aSAndroid Build Coastguard Worker        xfrm_base._ALGO_CRYPT_NULL, xfrm_base._ALGO_AUTH_NULL,
654*2f2c4c7aSAndroid Build Coastguard Worker        None, None, None, None)
655*2f2c4c7aSAndroid Build Coastguard Worker    # Input
656*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddSaInfo(
657*2f2c4c7aSAndroid Build Coastguard Worker        remote_addr, local_addr, 0x9876, xfrm.XFRM_MODE_TRANSPORT, 456,
658*2f2c4c7aSAndroid Build Coastguard Worker        xfrm_base._ALGO_CRYPT_NULL, xfrm_base._ALGO_AUTH_NULL,
659*2f2c4c7aSAndroid Build Coastguard Worker        None, None, None, None)
660*2f2c4c7aSAndroid Build Coastguard Worker
661*2f2c4c7aSAndroid Build Coastguard Worker    sock = net_test.UDPSocket(family)
662*2f2c4c7aSAndroid Build Coastguard Worker    self.SelectInterface(sock, netid, "mark")
663*2f2c4c7aSAndroid Build Coastguard Worker    sock.bind((local_addr, 0))
664*2f2c4c7aSAndroid Build Coastguard Worker    local_port = sock.getsockname()[1]
665*2f2c4c7aSAndroid Build Coastguard Worker    remote_port = 5555
666*2f2c4c7aSAndroid Build Coastguard Worker
667*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.ApplySocketPolicy(
668*2f2c4c7aSAndroid Build Coastguard Worker        sock, family, xfrm.XFRM_POLICY_OUT, 0xABCD, 123, None)
669*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.ApplySocketPolicy(
670*2f2c4c7aSAndroid Build Coastguard Worker        sock, family, xfrm.XFRM_POLICY_IN, 0x9876, 456, None)
671*2f2c4c7aSAndroid Build Coastguard Worker
672*2f2c4c7aSAndroid Build Coastguard Worker    # Create and receive an ESP packet.
673*2f2c4c7aSAndroid Build Coastguard Worker    IpType = {4: scapy.IP, 6: scapy.IPv6}[version]
674*2f2c4c7aSAndroid Build Coastguard Worker    input_pkt = (IpType(src=remote_addr, dst=local_addr) /
675*2f2c4c7aSAndroid Build Coastguard Worker                 scapy.UDP(sport=remote_port, dport=local_port) /
676*2f2c4c7aSAndroid Build Coastguard Worker                 b"input hello")
677*2f2c4c7aSAndroid Build Coastguard Worker    input_pkt = IpType(bytes(input_pkt)) # Compute length, checksum.
678*2f2c4c7aSAndroid Build Coastguard Worker    input_pkt = xfrm_base.EncryptPacketWithNull(input_pkt, 0x9876, 1, None)
679*2f2c4c7aSAndroid Build Coastguard Worker
680*2f2c4c7aSAndroid Build Coastguard Worker    self.ReceivePacketOn(netid, input_pkt)
681*2f2c4c7aSAndroid Build Coastguard Worker    msg, addr = sock.recvfrom(1024)
682*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(b"input hello", msg)
683*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual((remote_addr, remote_port), addr[:2])
684*2f2c4c7aSAndroid Build Coastguard Worker
685*2f2c4c7aSAndroid Build Coastguard Worker    # Send and capture a packet.
686*2f2c4c7aSAndroid Build Coastguard Worker    sock.sendto(b"output hello", (remote_addr, remote_port))
687*2f2c4c7aSAndroid Build Coastguard Worker    packets = self.ReadAllPacketsOn(netid)
688*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(1, len(packets))
689*2f2c4c7aSAndroid Build Coastguard Worker    output_pkt = packets[0]
690*2f2c4c7aSAndroid Build Coastguard Worker    output_pkt, esp_hdr = xfrm_base.DecryptPacketWithNull(output_pkt)
691*2f2c4c7aSAndroid Build Coastguard Worker    # length of the payload plus the UDP header
692*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(output_pkt[scapy.UDP].len, len(b"output_hello") + 8)
693*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(remote_addr, output_pkt.dst)
694*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(remote_port, output_pkt[scapy.UDP].dport)
695*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(b"output hello", bytes(output_pkt[scapy.UDP].payload))
696*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0xABCD, esp_hdr.spi)
697*2f2c4c7aSAndroid Build Coastguard Worker    sock.close()
698*2f2c4c7aSAndroid Build Coastguard Worker
699*2f2c4c7aSAndroid Build Coastguard Worker  def testNullEncryptionTransportMode(self):
700*2f2c4c7aSAndroid Build Coastguard Worker    """Verify null encryption in transport mode.
701*2f2c4c7aSAndroid Build Coastguard Worker
702*2f2c4c7aSAndroid Build Coastguard Worker    This test verifies both manual assembly and disassembly of UDP packets
703*2f2c4c7aSAndroid Build Coastguard Worker    with ESP in IPsec transport mode.
704*2f2c4c7aSAndroid Build Coastguard Worker    """
705*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 6]:
706*2f2c4c7aSAndroid Build Coastguard Worker      self._CheckNullEncryptionTransportMode(version)
707*2f2c4c7aSAndroid Build Coastguard Worker
708*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckGlobalPoliciesByMark(self, version):
709*2f2c4c7aSAndroid Build Coastguard Worker    """Tests that global policies may differ by only the mark."""
710*2f2c4c7aSAndroid Build Coastguard Worker    family = net_test.GetAddressFamily(version)
711*2f2c4c7aSAndroid Build Coastguard Worker    sel = xfrm.EmptySelector(family)
712*2f2c4c7aSAndroid Build Coastguard Worker    # Pick 2 arbitrary mark values.
713*2f2c4c7aSAndroid Build Coastguard Worker    mark1 = xfrm.XfrmMark(mark=0xf00, mask=xfrm_base.MARK_MASK_ALL)
714*2f2c4c7aSAndroid Build Coastguard Worker    mark2 = xfrm.XfrmMark(mark=0xf00d, mask=xfrm_base.MARK_MASK_ALL)
715*2f2c4c7aSAndroid Build Coastguard Worker    # Create a global policy.
716*2f2c4c7aSAndroid Build Coastguard Worker    policy = xfrm.UserPolicy(xfrm.XFRM_POLICY_OUT, sel)
717*2f2c4c7aSAndroid Build Coastguard Worker    tmpl = xfrm.UserTemplate(AF_UNSPEC, 0xfeed, 0, None)
718*2f2c4c7aSAndroid Build Coastguard Worker    # Create the policy with the first mark.
719*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddPolicyInfo(policy, tmpl, mark1)
720*2f2c4c7aSAndroid Build Coastguard Worker    # Create the same policy but with the second (different) mark.
721*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddPolicyInfo(policy, tmpl, mark2)
722*2f2c4c7aSAndroid Build Coastguard Worker    # Delete the policies individually
723*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeletePolicyInfo(sel, xfrm.XFRM_POLICY_OUT, mark1)
724*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.DeletePolicyInfo(sel, xfrm.XFRM_POLICY_OUT, mark2)
725*2f2c4c7aSAndroid Build Coastguard Worker
726*2f2c4c7aSAndroid Build Coastguard Worker  def testGlobalPoliciesByMarkV4(self):
727*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckGlobalPoliciesByMark(4)
728*2f2c4c7aSAndroid Build Coastguard Worker
729*2f2c4c7aSAndroid Build Coastguard Worker  def testGlobalPoliciesByMarkV6(self):
730*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckGlobalPoliciesByMark(6)
731*2f2c4c7aSAndroid Build Coastguard Worker
732*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckUpdatePolicy(self, version):
733*2f2c4c7aSAndroid Build Coastguard Worker    """Tests that we can can update the template on a policy."""
734*2f2c4c7aSAndroid Build Coastguard Worker    family = net_test.GetAddressFamily(version)
735*2f2c4c7aSAndroid Build Coastguard Worker    tmpl1 = xfrm.UserTemplate(family, 0xdead, 0, None)
736*2f2c4c7aSAndroid Build Coastguard Worker    tmpl2 = xfrm.UserTemplate(family, 0xbeef, 0, None)
737*2f2c4c7aSAndroid Build Coastguard Worker    sel = xfrm.EmptySelector(family)
738*2f2c4c7aSAndroid Build Coastguard Worker    policy = xfrm.UserPolicy(xfrm.XFRM_POLICY_OUT, sel)
739*2f2c4c7aSAndroid Build Coastguard Worker    mark = xfrm.XfrmMark(mark=0xf00, mask=xfrm_base.MARK_MASK_ALL)
740*2f2c4c7aSAndroid Build Coastguard Worker
741*2f2c4c7aSAndroid Build Coastguard Worker    def _CheckTemplateMatch(tmpl):
742*2f2c4c7aSAndroid Build Coastguard Worker      """Dump the SPD and match a single template on a single policy."""
743*2f2c4c7aSAndroid Build Coastguard Worker      dump = self.xfrm.DumpPolicyInfo()
744*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(1, len(dump))
745*2f2c4c7aSAndroid Build Coastguard Worker      _, attributes = dump[0]
746*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(attributes['XFRMA_TMPL'], tmpl)
747*2f2c4c7aSAndroid Build Coastguard Worker
748*2f2c4c7aSAndroid Build Coastguard Worker    # Create a new policy using update.
749*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.UpdatePolicyInfo(policy, tmpl1, mark, None)
750*2f2c4c7aSAndroid Build Coastguard Worker    # NEWPOLICY will not update the existing policy. This checks both that
751*2f2c4c7aSAndroid Build Coastguard Worker    # UPDPOLICY created a policy and that NEWPOLICY will not perform updates.
752*2f2c4c7aSAndroid Build Coastguard Worker    _CheckTemplateMatch(tmpl1)
753*2f2c4c7aSAndroid Build Coastguard Worker    with self.assertRaisesErrno(EEXIST):
754*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.AddPolicyInfo(policy, tmpl2, mark, None)
755*2f2c4c7aSAndroid Build Coastguard Worker    # Update the policy using UPDPOLICY.
756*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.UpdatePolicyInfo(policy, tmpl2, mark, None)
757*2f2c4c7aSAndroid Build Coastguard Worker    # There should only be one policy after update, and it should have the
758*2f2c4c7aSAndroid Build Coastguard Worker    # updated template.
759*2f2c4c7aSAndroid Build Coastguard Worker    _CheckTemplateMatch(tmpl2)
760*2f2c4c7aSAndroid Build Coastguard Worker
761*2f2c4c7aSAndroid Build Coastguard Worker  def testUpdatePolicyV4(self):
762*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckUpdatePolicy(4)
763*2f2c4c7aSAndroid Build Coastguard Worker
764*2f2c4c7aSAndroid Build Coastguard Worker  def testUpdatePolicyV6(self):
765*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckUpdatePolicy(6)
766*2f2c4c7aSAndroid Build Coastguard Worker
767*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckPolicyDifferByDirection(self,version):
768*2f2c4c7aSAndroid Build Coastguard Worker    """Tests that policies can differ only by direction."""
769*2f2c4c7aSAndroid Build Coastguard Worker    family = net_test.GetAddressFamily(version)
770*2f2c4c7aSAndroid Build Coastguard Worker    tmpl = xfrm.UserTemplate(family, 0xdead, 0, None)
771*2f2c4c7aSAndroid Build Coastguard Worker    sel = xfrm.EmptySelector(family)
772*2f2c4c7aSAndroid Build Coastguard Worker    mark = xfrm.XfrmMark(mark=0xf00, mask=xfrm_base.MARK_MASK_ALL)
773*2f2c4c7aSAndroid Build Coastguard Worker    policy = xfrm.UserPolicy(xfrm.XFRM_POLICY_OUT, sel)
774*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddPolicyInfo(policy, tmpl, mark)
775*2f2c4c7aSAndroid Build Coastguard Worker    policy = xfrm.UserPolicy(xfrm.XFRM_POLICY_IN, sel)
776*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddPolicyInfo(policy, tmpl, mark)
777*2f2c4c7aSAndroid Build Coastguard Worker
778*2f2c4c7aSAndroid Build Coastguard Worker  def testPolicyDifferByDirectionV4(self):
779*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckPolicyDifferByDirection(4)
780*2f2c4c7aSAndroid Build Coastguard Worker
781*2f2c4c7aSAndroid Build Coastguard Worker  def testPolicyDifferByDirectionV6(self):
782*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckPolicyDifferByDirection(6)
783*2f2c4c7aSAndroid Build Coastguard Worker
784*2f2c4c7aSAndroid Build Coastguard Workerclass XfrmOutputMarkTest(xfrm_base.XfrmLazyTest):
785*2f2c4c7aSAndroid Build Coastguard Worker
786*2f2c4c7aSAndroid Build Coastguard Worker  def _CheckTunnelModeOutputMark(self, version, tunsrc, mark, expected_netid):
787*2f2c4c7aSAndroid Build Coastguard Worker    """Tests sending UDP packets to tunnel mode SAs with output marks.
788*2f2c4c7aSAndroid Build Coastguard Worker
789*2f2c4c7aSAndroid Build Coastguard Worker    Opens a UDP socket and binds it to a random netid, then sets up tunnel mode
790*2f2c4c7aSAndroid Build Coastguard Worker    SAs with an output_mark of mark and sets a socket policy to use the SA.
791*2f2c4c7aSAndroid Build Coastguard Worker    Then checks that sending on those SAs sends a packet on expected_netid,
792*2f2c4c7aSAndroid Build Coastguard Worker    or, if expected_netid is zero, checks that sending returns ENETUNREACH.
793*2f2c4c7aSAndroid Build Coastguard Worker
794*2f2c4c7aSAndroid Build Coastguard Worker    Args:
795*2f2c4c7aSAndroid Build Coastguard Worker      version: 4 or 6.
796*2f2c4c7aSAndroid Build Coastguard Worker      tunsrc: A string, the source address of the tunnel.
797*2f2c4c7aSAndroid Build Coastguard Worker      mark: An integer, the output_mark to set in the SA.
798*2f2c4c7aSAndroid Build Coastguard Worker      expected_netid: An integer, the netid to expect the kernel to send the
799*2f2c4c7aSAndroid Build Coastguard Worker          packet on. If None, expect that sendto will fail with ENETUNREACH.
800*2f2c4c7aSAndroid Build Coastguard Worker    """
801*2f2c4c7aSAndroid Build Coastguard Worker    # Open a UDP socket and bind it to a random netid.
802*2f2c4c7aSAndroid Build Coastguard Worker    family = net_test.GetAddressFamily(version)
803*2f2c4c7aSAndroid Build Coastguard Worker    s = socket(family, SOCK_DGRAM, 0)
804*2f2c4c7aSAndroid Build Coastguard Worker    self.SelectInterface(s, self.RandomNetid(), "mark")
805*2f2c4c7aSAndroid Build Coastguard Worker
806*2f2c4c7aSAndroid Build Coastguard Worker    # For generality, pick a tunnel endpoint that's not the address we
807*2f2c4c7aSAndroid Build Coastguard Worker    # connect the socket to.
808*2f2c4c7aSAndroid Build Coastguard Worker    tundst = TUNNEL_ENDPOINTS[version]
809*2f2c4c7aSAndroid Build Coastguard Worker    tun_addrs = (tunsrc, tundst)
810*2f2c4c7aSAndroid Build Coastguard Worker
811*2f2c4c7aSAndroid Build Coastguard Worker    # Create a tunnel mode SA and use XFRM_OUTPUT_MARK to bind it to netid.
812*2f2c4c7aSAndroid Build Coastguard Worker    spi = TEST_SPI * mark
813*2f2c4c7aSAndroid Build Coastguard Worker    reqid = 100 + spi
814*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddSaInfo(tunsrc, tundst, spi, xfrm.XFRM_MODE_TUNNEL, reqid,
815*2f2c4c7aSAndroid Build Coastguard Worker                        xfrm_base._ALGO_CBC_AES_256, xfrm_base._ALGO_HMAC_SHA1,
816*2f2c4c7aSAndroid Build Coastguard Worker                        None, None, None, mark)
817*2f2c4c7aSAndroid Build Coastguard Worker
818*2f2c4c7aSAndroid Build Coastguard Worker    # Set a socket policy to use it.
819*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_base.ApplySocketPolicy(s, family, xfrm.XFRM_POLICY_OUT, spi, reqid,
820*2f2c4c7aSAndroid Build Coastguard Worker                                tun_addrs)
821*2f2c4c7aSAndroid Build Coastguard Worker
822*2f2c4c7aSAndroid Build Coastguard Worker    # Send a packet and check that we see it on the wire.
823*2f2c4c7aSAndroid Build Coastguard Worker    remoteaddr = self.GetRemoteAddress(version)
824*2f2c4c7aSAndroid Build Coastguard Worker
825*2f2c4c7aSAndroid Build Coastguard Worker    packetlen = xfrm_base.GetEspPacketLength(xfrm.XFRM_MODE_TUNNEL, version,
826*2f2c4c7aSAndroid Build Coastguard Worker                                             False, net_test.UDP_PAYLOAD,
827*2f2c4c7aSAndroid Build Coastguard Worker                                             xfrm_base._ALGO_HMAC_SHA1,
828*2f2c4c7aSAndroid Build Coastguard Worker                                             xfrm_base._ALGO_CBC_AES_256)
829*2f2c4c7aSAndroid Build Coastguard Worker
830*2f2c4c7aSAndroid Build Coastguard Worker    if expected_netid is not None:
831*2f2c4c7aSAndroid Build Coastguard Worker      s.sendto(net_test.UDP_PAYLOAD, (remoteaddr, 53))
832*2f2c4c7aSAndroid Build Coastguard Worker      self._ExpectEspPacketOn(expected_netid, spi, 1, packetlen, tunsrc, tundst)
833*2f2c4c7aSAndroid Build Coastguard Worker    else:
834*2f2c4c7aSAndroid Build Coastguard Worker      with self.assertRaisesErrno(ENETUNREACH):
835*2f2c4c7aSAndroid Build Coastguard Worker        s.sendto(net_test.UDP_PAYLOAD, (remoteaddr, 53))
836*2f2c4c7aSAndroid Build Coastguard Worker
837*2f2c4c7aSAndroid Build Coastguard Worker    s.close()
838*2f2c4c7aSAndroid Build Coastguard Worker
839*2f2c4c7aSAndroid Build Coastguard Worker  def testTunnelModeOutputMarkIPv4(self):
840*2f2c4c7aSAndroid Build Coastguard Worker    for netid in self.NETIDS:
841*2f2c4c7aSAndroid Build Coastguard Worker      tunsrc = self.MyAddress(4, netid)
842*2f2c4c7aSAndroid Build Coastguard Worker      self._CheckTunnelModeOutputMark(4, tunsrc, netid, netid)
843*2f2c4c7aSAndroid Build Coastguard Worker
844*2f2c4c7aSAndroid Build Coastguard Worker  def testTunnelModeOutputMarkIPv6(self):
845*2f2c4c7aSAndroid Build Coastguard Worker    for netid in self.NETIDS:
846*2f2c4c7aSAndroid Build Coastguard Worker      tunsrc = self.MyAddress(6, netid)
847*2f2c4c7aSAndroid Build Coastguard Worker      self._CheckTunnelModeOutputMark(6, tunsrc, netid, netid)
848*2f2c4c7aSAndroid Build Coastguard Worker
849*2f2c4c7aSAndroid Build Coastguard Worker  def testTunnelModeOutputNoMarkIPv4(self):
850*2f2c4c7aSAndroid Build Coastguard Worker    tunsrc = self.MyAddress(4, self.RandomNetid())
851*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelModeOutputMark(4, tunsrc, 0, None)
852*2f2c4c7aSAndroid Build Coastguard Worker
853*2f2c4c7aSAndroid Build Coastguard Worker  def testTunnelModeOutputNoMarkIPv6(self):
854*2f2c4c7aSAndroid Build Coastguard Worker    tunsrc = self.MyAddress(6, self.RandomNetid())
855*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelModeOutputMark(6, tunsrc, 0, None)
856*2f2c4c7aSAndroid Build Coastguard Worker
857*2f2c4c7aSAndroid Build Coastguard Worker  def testTunnelModeOutputInvalidMarkIPv4(self):
858*2f2c4c7aSAndroid Build Coastguard Worker    tunsrc = self.MyAddress(4, self.RandomNetid())
859*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelModeOutputMark(4, tunsrc, 9999, None)
860*2f2c4c7aSAndroid Build Coastguard Worker
861*2f2c4c7aSAndroid Build Coastguard Worker  def testTunnelModeOutputInvalidMarkIPv6(self):
862*2f2c4c7aSAndroid Build Coastguard Worker    tunsrc = self.MyAddress(6, self.RandomNetid())
863*2f2c4c7aSAndroid Build Coastguard Worker    self._CheckTunnelModeOutputMark(6, tunsrc, 9999, None)
864*2f2c4c7aSAndroid Build Coastguard Worker
865*2f2c4c7aSAndroid Build Coastguard Worker  def testTunnelModeOutputMarkAttributes(self):
866*2f2c4c7aSAndroid Build Coastguard Worker    mark = 1234567
867*2f2c4c7aSAndroid Build Coastguard Worker    self.xfrm.AddSaInfo(TEST_ADDR1, TUNNEL_ENDPOINTS[6], 0x1234,
868*2f2c4c7aSAndroid Build Coastguard Worker                        xfrm.XFRM_MODE_TUNNEL, 100, xfrm_base._ALGO_CBC_AES_256,
869*2f2c4c7aSAndroid Build Coastguard Worker                        xfrm_base._ALGO_HMAC_SHA1, None, None, None, mark)
870*2f2c4c7aSAndroid Build Coastguard Worker    dump = self.xfrm.DumpSaInfo()
871*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(1, len(dump))
872*2f2c4c7aSAndroid Build Coastguard Worker    sainfo, attributes = dump[0]
873*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(mark, attributes["XFRMA_OUTPUT_MARK"])
874*2f2c4c7aSAndroid Build Coastguard Worker
875*2f2c4c7aSAndroid Build Coastguard Worker  def testInvalidAlgorithms(self):
876*2f2c4c7aSAndroid Build Coastguard Worker    key = binascii.unhexlify("af442892cdcd0ef650e9c299f9a8436a")
877*2f2c4c7aSAndroid Build Coastguard Worker    invalid_auth = (xfrm.XfrmAlgoAuth((b"invalid(algo)", 128, 96)), key)
878*2f2c4c7aSAndroid Build Coastguard Worker    invalid_crypt = (xfrm.XfrmAlgo((b"invalid(algo)", 128)), key)
879*2f2c4c7aSAndroid Build Coastguard Worker    with self.assertRaisesErrno(ENOSYS):
880*2f2c4c7aSAndroid Build Coastguard Worker        self.xfrm.AddSaInfo(TEST_ADDR1, TEST_ADDR2, 0x1234,
881*2f2c4c7aSAndroid Build Coastguard Worker            xfrm.XFRM_MODE_TRANSPORT, 0, xfrm_base._ALGO_CBC_AES_256,
882*2f2c4c7aSAndroid Build Coastguard Worker            invalid_auth, None, None, None, 0)
883*2f2c4c7aSAndroid Build Coastguard Worker    with self.assertRaisesErrno(ENOSYS):
884*2f2c4c7aSAndroid Build Coastguard Worker        self.xfrm.AddSaInfo(TEST_ADDR1, TEST_ADDR2, 0x1234,
885*2f2c4c7aSAndroid Build Coastguard Worker            xfrm.XFRM_MODE_TRANSPORT, 0, invalid_crypt,
886*2f2c4c7aSAndroid Build Coastguard Worker            xfrm_base._ALGO_HMAC_SHA1, None, None, None, 0)
887*2f2c4c7aSAndroid Build Coastguard Worker
888*2f2c4c7aSAndroid Build Coastguard Worker  def testUpdateSaAddMark(self):
889*2f2c4c7aSAndroid Build Coastguard Worker    """Test that an embryonic SA can be updated to add a mark."""
890*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 6]:
891*2f2c4c7aSAndroid Build Coastguard Worker      spi = 0xABCD
892*2f2c4c7aSAndroid Build Coastguard Worker      # Test that an SA created with ALLOCSPI can be updated with the mark.
893*2f2c4c7aSAndroid Build Coastguard Worker      new_sa = self.xfrm.AllocSpi(net_test.GetWildcardAddress(version),
894*2f2c4c7aSAndroid Build Coastguard Worker                                  IPPROTO_ESP, spi, spi)
895*2f2c4c7aSAndroid Build Coastguard Worker      mark = xfrm.ExactMatchMark(0xf00d)
896*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.AddSaInfo(net_test.GetWildcardAddress(version),
897*2f2c4c7aSAndroid Build Coastguard Worker                          net_test.GetWildcardAddress(version),
898*2f2c4c7aSAndroid Build Coastguard Worker                          spi, xfrm.XFRM_MODE_TUNNEL, 0,
899*2f2c4c7aSAndroid Build Coastguard Worker                          xfrm_base._ALGO_CBC_AES_256,
900*2f2c4c7aSAndroid Build Coastguard Worker                          xfrm_base._ALGO_HMAC_SHA1,
901*2f2c4c7aSAndroid Build Coastguard Worker                          None, None, mark, 0, is_update=True)
902*2f2c4c7aSAndroid Build Coastguard Worker      dump = self.xfrm.DumpSaInfo()
903*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(1, len(dump)) # check that update updated
904*2f2c4c7aSAndroid Build Coastguard Worker      sainfo, attributes = dump[0]
905*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(mark, attributes["XFRMA_MARK"])
906*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.DeleteSaInfo(net_test.GetWildcardAddress(version),
907*2f2c4c7aSAndroid Build Coastguard Worker                             spi, IPPROTO_ESP, mark)
908*2f2c4c7aSAndroid Build Coastguard Worker
909*2f2c4c7aSAndroid Build Coastguard Worker  def getXfrmStat(self, statName):
910*2f2c4c7aSAndroid Build Coastguard Worker    stateVal = 0
911*2f2c4c7aSAndroid Build Coastguard Worker    with open(XFRM_STATS_PROCFILE, 'r') as f:
912*2f2c4c7aSAndroid Build Coastguard Worker      for line in f:
913*2f2c4c7aSAndroid Build Coastguard Worker          if statName in line:
914*2f2c4c7aSAndroid Build Coastguard Worker            stateVal = int(line.split()[1])
915*2f2c4c7aSAndroid Build Coastguard Worker            break
916*2f2c4c7aSAndroid Build Coastguard Worker      f.close()
917*2f2c4c7aSAndroid Build Coastguard Worker    return stateVal
918*2f2c4c7aSAndroid Build Coastguard Worker
919*2f2c4c7aSAndroid Build Coastguard Worker  def testUpdateActiveSaMarks(self):
920*2f2c4c7aSAndroid Build Coastguard Worker    """Test that the OUTPUT_MARK can be updated on an ACTIVE SA."""
921*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 6]:
922*2f2c4c7aSAndroid Build Coastguard Worker      family = net_test.GetAddressFamily(version)
923*2f2c4c7aSAndroid Build Coastguard Worker      netid = self.RandomNetid()
924*2f2c4c7aSAndroid Build Coastguard Worker      remote = self.GetRemoteAddress(version)
925*2f2c4c7aSAndroid Build Coastguard Worker      local = self.MyAddress(version, netid)
926*2f2c4c7aSAndroid Build Coastguard Worker      s = socket(family, SOCK_DGRAM, 0)
927*2f2c4c7aSAndroid Build Coastguard Worker      self.SelectInterface(s, netid, "mark")
928*2f2c4c7aSAndroid Build Coastguard Worker      # Create a mark that we will apply to the policy and later the SA
929*2f2c4c7aSAndroid Build Coastguard Worker      mark = xfrm.ExactMatchMark(netid)
930*2f2c4c7aSAndroid Build Coastguard Worker
931*2f2c4c7aSAndroid Build Coastguard Worker      # Create a global policy that selects using the mark.
932*2f2c4c7aSAndroid Build Coastguard Worker      sel = xfrm.EmptySelector(family)
933*2f2c4c7aSAndroid Build Coastguard Worker      policy = xfrm.UserPolicy(xfrm.XFRM_POLICY_OUT, sel)
934*2f2c4c7aSAndroid Build Coastguard Worker      tmpl = xfrm.UserTemplate(family, 0, 0, (local, remote))
935*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.AddPolicyInfo(policy, tmpl, mark)
936*2f2c4c7aSAndroid Build Coastguard Worker
937*2f2c4c7aSAndroid Build Coastguard Worker      # Pull /proc/net/xfrm_stats for baseline
938*2f2c4c7aSAndroid Build Coastguard Worker      outNoStateCount = self.getXfrmStat(XFRM_STATS_OUT_NO_STATES);
939*2f2c4c7aSAndroid Build Coastguard Worker
940*2f2c4c7aSAndroid Build Coastguard Worker      # should increment XfrmOutNoStates
941*2f2c4c7aSAndroid Build Coastguard Worker      s.sendto(net_test.UDP_PAYLOAD, (remote, 53))
942*2f2c4c7aSAndroid Build Coastguard Worker
943*2f2c4c7aSAndroid Build Coastguard Worker      # Check to make sure XfrmOutNoStates is incremented by exactly 1
944*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(outNoStateCount + 1,
945*2f2c4c7aSAndroid Build Coastguard Worker                        self.getXfrmStat(XFRM_STATS_OUT_NO_STATES))
946*2f2c4c7aSAndroid Build Coastguard Worker
947*2f2c4c7aSAndroid Build Coastguard Worker      length = xfrm_base.GetEspPacketLength(xfrm.XFRM_MODE_TUNNEL,
948*2f2c4c7aSAndroid Build Coastguard Worker                                            version, False,
949*2f2c4c7aSAndroid Build Coastguard Worker                                            net_test.UDP_PAYLOAD,
950*2f2c4c7aSAndroid Build Coastguard Worker                                            xfrm_base._ALGO_HMAC_SHA1,
951*2f2c4c7aSAndroid Build Coastguard Worker                                            xfrm_base._ALGO_CBC_AES_256)
952*2f2c4c7aSAndroid Build Coastguard Worker
953*2f2c4c7aSAndroid Build Coastguard Worker      # Add a default SA with no mark that routes to nowhere.
954*2f2c4c7aSAndroid Build Coastguard Worker      try:
955*2f2c4c7aSAndroid Build Coastguard Worker          self.xfrm.AddSaInfo(local,
956*2f2c4c7aSAndroid Build Coastguard Worker                              remote,
957*2f2c4c7aSAndroid Build Coastguard Worker                              TEST_SPI, xfrm.XFRM_MODE_TUNNEL, 0,
958*2f2c4c7aSAndroid Build Coastguard Worker                              xfrm_base._ALGO_CBC_AES_256,
959*2f2c4c7aSAndroid Build Coastguard Worker                              xfrm_base._ALGO_HMAC_SHA1,
960*2f2c4c7aSAndroid Build Coastguard Worker                              None, None, mark, 0, is_update=False)
961*2f2c4c7aSAndroid Build Coastguard Worker      except IOError as e:
962*2f2c4c7aSAndroid Build Coastguard Worker          self.assertEqual(EEXIST, e.errno, "SA exists")
963*2f2c4c7aSAndroid Build Coastguard Worker          self.xfrm.AddSaInfo(local,
964*2f2c4c7aSAndroid Build Coastguard Worker                              remote,
965*2f2c4c7aSAndroid Build Coastguard Worker                              TEST_SPI, xfrm.XFRM_MODE_TUNNEL, 0,
966*2f2c4c7aSAndroid Build Coastguard Worker                              xfrm_base._ALGO_CBC_AES_256,
967*2f2c4c7aSAndroid Build Coastguard Worker                              xfrm_base._ALGO_HMAC_SHA1,
968*2f2c4c7aSAndroid Build Coastguard Worker                              None, None, mark, 0, is_update=True)
969*2f2c4c7aSAndroid Build Coastguard Worker
970*2f2c4c7aSAndroid Build Coastguard Worker      self.assertRaisesErrno(
971*2f2c4c7aSAndroid Build Coastguard Worker          ENETUNREACH,
972*2f2c4c7aSAndroid Build Coastguard Worker          s.sendto, net_test.UDP_PAYLOAD, (remote, 53))
973*2f2c4c7aSAndroid Build Coastguard Worker
974*2f2c4c7aSAndroid Build Coastguard Worker      # Update the SA to route to a valid netid.
975*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.AddSaInfo(local,
976*2f2c4c7aSAndroid Build Coastguard Worker                          remote,
977*2f2c4c7aSAndroid Build Coastguard Worker                          TEST_SPI, xfrm.XFRM_MODE_TUNNEL, 0,
978*2f2c4c7aSAndroid Build Coastguard Worker                          xfrm_base._ALGO_CBC_AES_256,
979*2f2c4c7aSAndroid Build Coastguard Worker                          xfrm_base._ALGO_HMAC_SHA1,
980*2f2c4c7aSAndroid Build Coastguard Worker                          None, None, mark, netid, is_update=True)
981*2f2c4c7aSAndroid Build Coastguard Worker
982*2f2c4c7aSAndroid Build Coastguard Worker      # Now the payload routes to the updated netid.
983*2f2c4c7aSAndroid Build Coastguard Worker      s.sendto(net_test.UDP_PAYLOAD, (remote, 53))
984*2f2c4c7aSAndroid Build Coastguard Worker      self._ExpectEspPacketOn(netid, TEST_SPI, 1, length, None, None)
985*2f2c4c7aSAndroid Build Coastguard Worker
986*2f2c4c7aSAndroid Build Coastguard Worker      # Get a new netid and reroute the packets to the new netid.
987*2f2c4c7aSAndroid Build Coastguard Worker      reroute_netid = self.RandomNetid(netid)
988*2f2c4c7aSAndroid Build Coastguard Worker      # Update the SA to change the output mark.
989*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.AddSaInfo(local,
990*2f2c4c7aSAndroid Build Coastguard Worker                         remote,
991*2f2c4c7aSAndroid Build Coastguard Worker                         TEST_SPI, xfrm.XFRM_MODE_TUNNEL, 0,
992*2f2c4c7aSAndroid Build Coastguard Worker                         xfrm_base._ALGO_CBC_AES_256,
993*2f2c4c7aSAndroid Build Coastguard Worker                         xfrm_base._ALGO_HMAC_SHA1,
994*2f2c4c7aSAndroid Build Coastguard Worker                         None, None, mark, reroute_netid, is_update=True)
995*2f2c4c7aSAndroid Build Coastguard Worker
996*2f2c4c7aSAndroid Build Coastguard Worker      s.sendto(net_test.UDP_PAYLOAD, (remote, 53))
997*2f2c4c7aSAndroid Build Coastguard Worker      self._ExpectEspPacketOn(reroute_netid, TEST_SPI, 2, length, None, None)
998*2f2c4c7aSAndroid Build Coastguard Worker
999*2f2c4c7aSAndroid Build Coastguard Worker      dump = self.xfrm.DumpSaInfo()
1000*2f2c4c7aSAndroid Build Coastguard Worker
1001*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(1, len(dump)) # check that update updated
1002*2f2c4c7aSAndroid Build Coastguard Worker      sainfo, attributes = dump[0]
1003*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(reroute_netid, attributes["XFRMA_OUTPUT_MARK"])
1004*2f2c4c7aSAndroid Build Coastguard Worker
1005*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.DeleteSaInfo(remote, TEST_SPI, IPPROTO_ESP, mark)
1006*2f2c4c7aSAndroid Build Coastguard Worker      self.xfrm.DeletePolicyInfo(sel, xfrm.XFRM_POLICY_OUT, mark)
1007*2f2c4c7aSAndroid Build Coastguard Worker
1008*2f2c4c7aSAndroid Build Coastguard Worker      s.close()
1009*2f2c4c7aSAndroid Build Coastguard Worker
1010*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__":
1011*2f2c4c7aSAndroid Build Coastguard Worker  unittest.main()
1012