xref: /aosp_15_r20/kernel/tests/net/test/multinetwork_base.py (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3
2*2f2c4c7aSAndroid Build Coastguard Worker#
3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2014 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"""Base module for multinetwork tests."""
18*2f2c4c7aSAndroid Build Coastguard Worker
19*2f2c4c7aSAndroid Build Coastguard Workerimport errno
20*2f2c4c7aSAndroid Build Coastguard Workerimport fcntl
21*2f2c4c7aSAndroid Build Coastguard Workerimport os
22*2f2c4c7aSAndroid Build Coastguard Workerimport posix
23*2f2c4c7aSAndroid Build Coastguard Workerimport random
24*2f2c4c7aSAndroid Build Coastguard Workerimport re
25*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import *  # pylint: disable=wildcard-import
26*2f2c4c7aSAndroid Build Coastguard Workerimport struct
27*2f2c4c7aSAndroid Build Coastguard Workerimport time
28*2f2c4c7aSAndroid Build Coastguard Worker
29*2f2c4c7aSAndroid Build Coastguard Workerfrom scapy import all as scapy
30*2f2c4c7aSAndroid Build Coastguard Worker
31*2f2c4c7aSAndroid Build Coastguard Workerimport csocket
32*2f2c4c7aSAndroid Build Coastguard Workerimport iproute
33*2f2c4c7aSAndroid Build Coastguard Workerimport net_test
34*2f2c4c7aSAndroid Build Coastguard Worker
35*2f2c4c7aSAndroid Build Coastguard Worker
36*2f2c4c7aSAndroid Build Coastguard WorkerIFF_TUN = 1
37*2f2c4c7aSAndroid Build Coastguard WorkerIFF_TAP = 2
38*2f2c4c7aSAndroid Build Coastguard WorkerIFF_NO_PI = 0x1000
39*2f2c4c7aSAndroid Build Coastguard WorkerTUNSETIFF = 0x400454ca
40*2f2c4c7aSAndroid Build Coastguard Worker
41*2f2c4c7aSAndroid Build Coastguard WorkerSO_BINDTODEVICE = 25
42*2f2c4c7aSAndroid Build Coastguard Worker
43*2f2c4c7aSAndroid Build Coastguard Worker# Setsockopt values.
44*2f2c4c7aSAndroid Build Coastguard WorkerIP_UNICAST_IF = 50
45*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_MULTICAST_IF = 17
46*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_UNICAST_IF = 76
47*2f2c4c7aSAndroid Build Coastguard Worker
48*2f2c4c7aSAndroid Build Coastguard Worker# Cmsg values.
49*2f2c4c7aSAndroid Build Coastguard WorkerIP_TTL = 2
50*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_2292PKTOPTIONS = 6
51*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_FLOWINFO = 11
52*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_HOPLIMIT = 52  # Different from IPV6_UNICAST_HOPS, this is cmsg only.
53*2f2c4c7aSAndroid Build Coastguard Worker
54*2f2c4c7aSAndroid Build Coastguard Worker
55*2f2c4c7aSAndroid Build Coastguard WorkerACCEPT_RA_MIN_LFT_SYSCTL = "/proc/sys/net/ipv6/conf/default/accept_ra_min_lft"
56*2f2c4c7aSAndroid Build Coastguard WorkerAUTOCONF_TABLE_SYSCTL = "/proc/sys/net/ipv6/conf/default/accept_ra_rt_table"
57*2f2c4c7aSAndroid Build Coastguard WorkerIPV4_MARK_REFLECT_SYSCTL = "/proc/sys/net/ipv4/fwmark_reflect"
58*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_MARK_REFLECT_SYSCTL = "/proc/sys/net/ipv6/fwmark_reflect"
59*2f2c4c7aSAndroid Build Coastguard WorkerRA_HONOR_PIO_LIFE_SYSCTL = "/proc/sys/net/ipv6/conf/default/ra_honor_pio_life"
60*2f2c4c7aSAndroid Build Coastguard WorkerRA_HONOR_PIO_PFLAG = "/proc/sys/net/ipv6/conf/default/ra_honor_pio_pflag"
61*2f2c4c7aSAndroid Build Coastguard Worker
62*2f2c4c7aSAndroid Build Coastguard WorkerHAVE_ACCEPT_RA_MIN_LFT = (os.path.isfile(ACCEPT_RA_MIN_LFT_SYSCTL) or
63*2f2c4c7aSAndroid Build Coastguard Worker                          net_test.NonGXI(5, 10) or
64*2f2c4c7aSAndroid Build Coastguard Worker                          net_test.KernelAtLeast([(5, 10, 199), (5, 15, 136),
65*2f2c4c7aSAndroid Build Coastguard Worker                                                  (6, 1, 57), (6, 6, 0)]))
66*2f2c4c7aSAndroid Build Coastguard WorkerHAVE_AUTOCONF_TABLE = os.path.isfile(AUTOCONF_TABLE_SYSCTL)
67*2f2c4c7aSAndroid Build Coastguard WorkerHAVE_RA_HONOR_PIO_LIFE = (os.path.isfile(RA_HONOR_PIO_LIFE_SYSCTL) or
68*2f2c4c7aSAndroid Build Coastguard Worker                          net_test.KernelAtLeast([(6, 7, 0)]))
69*2f2c4c7aSAndroid Build Coastguard WorkerHAVE_RA_HONOR_PIO_PFLAG = (os.path.isfile(RA_HONOR_PIO_PFLAG) or
70*2f2c4c7aSAndroid Build Coastguard Worker                           net_test.KernelAtLeast([(6, 12, 0)]))
71*2f2c4c7aSAndroid Build Coastguard Worker
72*2f2c4c7aSAndroid Build Coastguard WorkerHAVE_USEROPT_PIO_FIX = net_test.KernelAtLeast([(4, 19, 320), (5, 4, 282),
73*2f2c4c7aSAndroid Build Coastguard Worker                                               (5, 10, 224), (5, 15, 165),
74*2f2c4c7aSAndroid Build Coastguard Worker                                               (6, 1, 104), (6, 6, 45),
75*2f2c4c7aSAndroid Build Coastguard Worker                                               (6, 9, 13), (6, 10, 4),
76*2f2c4c7aSAndroid Build Coastguard Worker                                               (6, 11, 0)])
77*2f2c4c7aSAndroid Build Coastguard Worker
78*2f2c4c7aSAndroid Build Coastguard Worker
79*2f2c4c7aSAndroid Build Coastguard Workerclass ConfigurationError(AssertionError):
80*2f2c4c7aSAndroid Build Coastguard Worker  pass
81*2f2c4c7aSAndroid Build Coastguard Worker
82*2f2c4c7aSAndroid Build Coastguard Worker
83*2f2c4c7aSAndroid Build Coastguard Workerclass UnexpectedPacketError(AssertionError):
84*2f2c4c7aSAndroid Build Coastguard Worker  pass
85*2f2c4c7aSAndroid Build Coastguard Worker
86*2f2c4c7aSAndroid Build Coastguard Worker
87*2f2c4c7aSAndroid Build Coastguard Workerdef MakePktInfo(version, addr, ifindex):
88*2f2c4c7aSAndroid Build Coastguard Worker  family = {4: AF_INET, 6: AF_INET6}[version]
89*2f2c4c7aSAndroid Build Coastguard Worker  if not addr:
90*2f2c4c7aSAndroid Build Coastguard Worker    addr = {4: "0.0.0.0", 6: "::"}[version]
91*2f2c4c7aSAndroid Build Coastguard Worker  if addr:
92*2f2c4c7aSAndroid Build Coastguard Worker    addr = inet_pton(family, addr)
93*2f2c4c7aSAndroid Build Coastguard Worker  if version == 6:
94*2f2c4c7aSAndroid Build Coastguard Worker    return csocket.In6Pktinfo((addr, ifindex)).Pack()
95*2f2c4c7aSAndroid Build Coastguard Worker  else:
96*2f2c4c7aSAndroid Build Coastguard Worker    return csocket.InPktinfo((ifindex, addr, b"\x00" * 4)).Pack()
97*2f2c4c7aSAndroid Build Coastguard Worker
98*2f2c4c7aSAndroid Build Coastguard Worker
99*2f2c4c7aSAndroid Build Coastguard Workerclass MultiNetworkBaseTest(net_test.NetworkTest):
100*2f2c4c7aSAndroid Build Coastguard Worker  """Base class for all multinetwork tests.
101*2f2c4c7aSAndroid Build Coastguard Worker
102*2f2c4c7aSAndroid Build Coastguard Worker  This class does not contain any test code, but contains code to set up and
103*2f2c4c7aSAndroid Build Coastguard Worker  tear a multi-network environment using multiple tun interfaces. The
104*2f2c4c7aSAndroid Build Coastguard Worker  environment is designed to be similar to a real Android device in terms of
105*2f2c4c7aSAndroid Build Coastguard Worker  rules and routes, and supports IPv4 and IPv6.
106*2f2c4c7aSAndroid Build Coastguard Worker
107*2f2c4c7aSAndroid Build Coastguard Worker  Tests wishing to use this environment should inherit from this class and
108*2f2c4c7aSAndroid Build Coastguard Worker  ensure that any setupClass, tearDownClass, setUp, and tearDown methods they
109*2f2c4c7aSAndroid Build Coastguard Worker  implement also call the superclass versions.
110*2f2c4c7aSAndroid Build Coastguard Worker  """
111*2f2c4c7aSAndroid Build Coastguard Worker
112*2f2c4c7aSAndroid Build Coastguard Worker  # Must be between 1 and 256, since we put them in MAC addresses and IIDs.
113*2f2c4c7aSAndroid Build Coastguard Worker  NETIDS = [100, 150, 200, 250]
114*2f2c4c7aSAndroid Build Coastguard Worker
115*2f2c4c7aSAndroid Build Coastguard Worker  # Stores sysctl values to write back when the test completes.
116*2f2c4c7aSAndroid Build Coastguard Worker  saved_sysctls = {}
117*2f2c4c7aSAndroid Build Coastguard Worker
118*2f2c4c7aSAndroid Build Coastguard Worker  # Wether to output setup commands.
119*2f2c4c7aSAndroid Build Coastguard Worker  DEBUG = False
120*2f2c4c7aSAndroid Build Coastguard Worker
121*2f2c4c7aSAndroid Build Coastguard Worker  UID_RANGE_START = 2000
122*2f2c4c7aSAndroid Build Coastguard Worker  UID_RANGE_END = 9999
123*2f2c4c7aSAndroid Build Coastguard Worker  UID_RANGE_SIZE = UID_RANGE_END - UID_RANGE_START + 1
124*2f2c4c7aSAndroid Build Coastguard Worker
125*2f2c4c7aSAndroid Build Coastguard Worker  # Rule priorities.
126*2f2c4c7aSAndroid Build Coastguard Worker  PRIORITY_UID = 100
127*2f2c4c7aSAndroid Build Coastguard Worker  PRIORITY_OIF = 200
128*2f2c4c7aSAndroid Build Coastguard Worker  PRIORITY_FWMARK = 300
129*2f2c4c7aSAndroid Build Coastguard Worker  PRIORITY_IIF = 400
130*2f2c4c7aSAndroid Build Coastguard Worker  PRIORITY_DEFAULT = 999
131*2f2c4c7aSAndroid Build Coastguard Worker  PRIORITY_UNREACHABLE = 1000
132*2f2c4c7aSAndroid Build Coastguard Worker
133*2f2c4c7aSAndroid Build Coastguard Worker  # Actual device routing is more complicated, involving more than one rule
134*2f2c4c7aSAndroid Build Coastguard Worker  # per NetId, but here we make do with just one rule that selects the lower
135*2f2c4c7aSAndroid Build Coastguard Worker  # 16 bits.
136*2f2c4c7aSAndroid Build Coastguard Worker  NETID_FWMASK = 0xffff
137*2f2c4c7aSAndroid Build Coastguard Worker
138*2f2c4c7aSAndroid Build Coastguard Worker  # For convenience.
139*2f2c4c7aSAndroid Build Coastguard Worker  IPV4_ADDR = net_test.IPV4_ADDR
140*2f2c4c7aSAndroid Build Coastguard Worker  IPV6_ADDR = net_test.IPV6_ADDR
141*2f2c4c7aSAndroid Build Coastguard Worker  IPV4_ADDR2 = net_test.IPV4_ADDR2
142*2f2c4c7aSAndroid Build Coastguard Worker  IPV6_ADDR2 = net_test.IPV6_ADDR2
143*2f2c4c7aSAndroid Build Coastguard Worker  IPV4_PING = net_test.IPV4_PING
144*2f2c4c7aSAndroid Build Coastguard Worker  IPV6_PING = net_test.IPV6_PING
145*2f2c4c7aSAndroid Build Coastguard Worker
146*2f2c4c7aSAndroid Build Coastguard Worker  RA_VALIDITY = 600 # seconds
147*2f2c4c7aSAndroid Build Coastguard Worker
148*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
149*2f2c4c7aSAndroid Build Coastguard Worker  def UidRangeForNetid(cls, netid):
150*2f2c4c7aSAndroid Build Coastguard Worker    per_netid_range = int(cls.UID_RANGE_SIZE / len(cls.NETIDS))
151*2f2c4c7aSAndroid Build Coastguard Worker    idx = cls.NETIDS.index(netid)
152*2f2c4c7aSAndroid Build Coastguard Worker    return (
153*2f2c4c7aSAndroid Build Coastguard Worker        cls.UID_RANGE_START + per_netid_range * idx,
154*2f2c4c7aSAndroid Build Coastguard Worker        cls.UID_RANGE_START + per_netid_range * (idx + 1) - 1
155*2f2c4c7aSAndroid Build Coastguard Worker    )
156*2f2c4c7aSAndroid Build Coastguard Worker
157*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
158*2f2c4c7aSAndroid Build Coastguard Worker  def UidForNetid(cls, netid):
159*2f2c4c7aSAndroid Build Coastguard Worker    if not netid:
160*2f2c4c7aSAndroid Build Coastguard Worker      return 0
161*2f2c4c7aSAndroid Build Coastguard Worker    return random.randint(*cls.UidRangeForNetid(netid))
162*2f2c4c7aSAndroid Build Coastguard Worker
163*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
164*2f2c4c7aSAndroid Build Coastguard Worker  def _TableForNetid(cls, netid):
165*2f2c4c7aSAndroid Build Coastguard Worker    if cls.AUTOCONF_TABLE_OFFSET and netid in cls.ifindices:
166*2f2c4c7aSAndroid Build Coastguard Worker      return cls.ifindices[netid] + (-cls.AUTOCONF_TABLE_OFFSET)
167*2f2c4c7aSAndroid Build Coastguard Worker    else:
168*2f2c4c7aSAndroid Build Coastguard Worker      return netid
169*2f2c4c7aSAndroid Build Coastguard Worker
170*2f2c4c7aSAndroid Build Coastguard Worker  @staticmethod
171*2f2c4c7aSAndroid Build Coastguard Worker  def GetInterfaceName(netid):
172*2f2c4c7aSAndroid Build Coastguard Worker    return "nettest%d" % netid
173*2f2c4c7aSAndroid Build Coastguard Worker
174*2f2c4c7aSAndroid Build Coastguard Worker  @staticmethod
175*2f2c4c7aSAndroid Build Coastguard Worker  def RouterMacAddress(netid):
176*2f2c4c7aSAndroid Build Coastguard Worker    return "02:00:00:00:%02x:00" % netid
177*2f2c4c7aSAndroid Build Coastguard Worker
178*2f2c4c7aSAndroid Build Coastguard Worker  @staticmethod
179*2f2c4c7aSAndroid Build Coastguard Worker  def MyMacAddress(netid):
180*2f2c4c7aSAndroid Build Coastguard Worker    return "02:00:00:00:%02x:01" % netid
181*2f2c4c7aSAndroid Build Coastguard Worker
182*2f2c4c7aSAndroid Build Coastguard Worker  @staticmethod
183*2f2c4c7aSAndroid Build Coastguard Worker  def _RouterAddress(netid, version):
184*2f2c4c7aSAndroid Build Coastguard Worker    if version == 6:
185*2f2c4c7aSAndroid Build Coastguard Worker      return "fe80::%02x00" % netid
186*2f2c4c7aSAndroid Build Coastguard Worker    elif version == 4:
187*2f2c4c7aSAndroid Build Coastguard Worker      return "10.0.%d.1" % netid
188*2f2c4c7aSAndroid Build Coastguard Worker    else:
189*2f2c4c7aSAndroid Build Coastguard Worker      raise ValueError("Don't support IPv%s" % version)
190*2f2c4c7aSAndroid Build Coastguard Worker
191*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
192*2f2c4c7aSAndroid Build Coastguard Worker  def _MyIPv4Address(cls, netid):
193*2f2c4c7aSAndroid Build Coastguard Worker    return "10.0.%d.2" % netid
194*2f2c4c7aSAndroid Build Coastguard Worker
195*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
196*2f2c4c7aSAndroid Build Coastguard Worker  def _MyIPv6Address(cls, netid):
197*2f2c4c7aSAndroid Build Coastguard Worker    return net_test.GetLinkAddress(cls.GetInterfaceName(netid), False)
198*2f2c4c7aSAndroid Build Coastguard Worker
199*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
200*2f2c4c7aSAndroid Build Coastguard Worker  def MyAddress(cls, version, netid):
201*2f2c4c7aSAndroid Build Coastguard Worker    return {4: cls._MyIPv4Address(netid),
202*2f2c4c7aSAndroid Build Coastguard Worker            5: cls._MyIPv4Address(netid),
203*2f2c4c7aSAndroid Build Coastguard Worker            6: cls._MyIPv6Address(netid)}[version]
204*2f2c4c7aSAndroid Build Coastguard Worker
205*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
206*2f2c4c7aSAndroid Build Coastguard Worker  def MySocketAddress(cls, version, netid):
207*2f2c4c7aSAndroid Build Coastguard Worker    addr = cls.MyAddress(version, netid)
208*2f2c4c7aSAndroid Build Coastguard Worker    return "::ffff:" + addr if version == 5 else addr
209*2f2c4c7aSAndroid Build Coastguard Worker
210*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
211*2f2c4c7aSAndroid Build Coastguard Worker  def MyLinkLocalAddress(cls, netid):
212*2f2c4c7aSAndroid Build Coastguard Worker    return net_test.GetLinkAddress(cls.GetInterfaceName(netid), True)
213*2f2c4c7aSAndroid Build Coastguard Worker
214*2f2c4c7aSAndroid Build Coastguard Worker  @staticmethod
215*2f2c4c7aSAndroid Build Coastguard Worker  def OnlinkPrefixLen(version):
216*2f2c4c7aSAndroid Build Coastguard Worker    return {4: 24, 6: 64}[version]
217*2f2c4c7aSAndroid Build Coastguard Worker
218*2f2c4c7aSAndroid Build Coastguard Worker  @staticmethod
219*2f2c4c7aSAndroid Build Coastguard Worker  def OnlinkPrefix(version, netid):
220*2f2c4c7aSAndroid Build Coastguard Worker    return {4: "10.0.%d.0" % netid,
221*2f2c4c7aSAndroid Build Coastguard Worker            6: "2001:db8:%02x::" % netid}[version]
222*2f2c4c7aSAndroid Build Coastguard Worker
223*2f2c4c7aSAndroid Build Coastguard Worker  @staticmethod
224*2f2c4c7aSAndroid Build Coastguard Worker  def GetRandomDestination(prefix):
225*2f2c4c7aSAndroid Build Coastguard Worker    if "." in prefix:
226*2f2c4c7aSAndroid Build Coastguard Worker      return prefix + "%d.%d" % (random.randint(0, 255), random.randint(0, 255))
227*2f2c4c7aSAndroid Build Coastguard Worker    else:
228*2f2c4c7aSAndroid Build Coastguard Worker      return prefix + "%x:%x" % (random.randint(0, 65535),
229*2f2c4c7aSAndroid Build Coastguard Worker                                 random.randint(0, 65535))
230*2f2c4c7aSAndroid Build Coastguard Worker
231*2f2c4c7aSAndroid Build Coastguard Worker  def GetProtocolFamily(self, version):
232*2f2c4c7aSAndroid Build Coastguard Worker    return {4: AF_INET, 6: AF_INET6}[version]
233*2f2c4c7aSAndroid Build Coastguard Worker
234*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
235*2f2c4c7aSAndroid Build Coastguard Worker  def CreateTunInterface(cls, netid):
236*2f2c4c7aSAndroid Build Coastguard Worker    iface = cls.GetInterfaceName(netid)
237*2f2c4c7aSAndroid Build Coastguard Worker    try:
238*2f2c4c7aSAndroid Build Coastguard Worker      f = open("/dev/net/tun", "r+b", buffering=0)
239*2f2c4c7aSAndroid Build Coastguard Worker    except IOError:
240*2f2c4c7aSAndroid Build Coastguard Worker      f = open("/dev/tun", "r+b", buffering=0)
241*2f2c4c7aSAndroid Build Coastguard Worker    ifr = struct.pack("16sH", iface.encode(), IFF_TAP | IFF_NO_PI)
242*2f2c4c7aSAndroid Build Coastguard Worker    ifr += b"\x00" * (40 - len(ifr))
243*2f2c4c7aSAndroid Build Coastguard Worker    fcntl.ioctl(f, TUNSETIFF, ifr)
244*2f2c4c7aSAndroid Build Coastguard Worker    # Give ourselves a predictable MAC address.
245*2f2c4c7aSAndroid Build Coastguard Worker    net_test.SetInterfaceHWAddr(iface, cls.MyMacAddress(netid))
246*2f2c4c7aSAndroid Build Coastguard Worker    # Disable DAD so we don't have to wait for it.
247*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetSysctl("/proc/sys/net/ipv6/conf/%s/accept_dad" % iface, 0)
248*2f2c4c7aSAndroid Build Coastguard Worker    # Set accept_ra to 2, because that's what we use.
249*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetSysctl("/proc/sys/net/ipv6/conf/%s/accept_ra" % iface, 2)
250*2f2c4c7aSAndroid Build Coastguard Worker    net_test.SetInterfaceUp(iface)
251*2f2c4c7aSAndroid Build Coastguard Worker    net_test.SetNonBlocking(f)
252*2f2c4c7aSAndroid Build Coastguard Worker    return f
253*2f2c4c7aSAndroid Build Coastguard Worker
254*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
255*2f2c4c7aSAndroid Build Coastguard Worker  def SendRA(cls, netid, retranstimer=None, reachabletime=0, routerlft=RA_VALIDITY,
256*2f2c4c7aSAndroid Build Coastguard Worker             piolft=RA_VALIDITY, m=0, o=0, piopflag=0, options=()):
257*2f2c4c7aSAndroid Build Coastguard Worker    macaddr = cls.RouterMacAddress(netid)
258*2f2c4c7aSAndroid Build Coastguard Worker    lladdr = cls._RouterAddress(netid, 6)
259*2f2c4c7aSAndroid Build Coastguard Worker
260*2f2c4c7aSAndroid Build Coastguard Worker    if retranstimer is None:
261*2f2c4c7aSAndroid Build Coastguard Worker      # If no retrans timer was specified, pick one that's as long as the
262*2f2c4c7aSAndroid Build Coastguard Worker      # router lifetime. This ensures that no spurious ND retransmits
263*2f2c4c7aSAndroid Build Coastguard Worker      # will interfere with test expectations.
264*2f2c4c7aSAndroid Build Coastguard Worker      retranstimer = routerlft * 1000  # Lifetime is in s, retrans timer in ms.
265*2f2c4c7aSAndroid Build Coastguard Worker
266*2f2c4c7aSAndroid Build Coastguard Worker    # We don't want any routes in the main table. If the kernel doesn't support
267*2f2c4c7aSAndroid Build Coastguard Worker    # putting RA routes into per-interface tables, configure routing manually.
268*2f2c4c7aSAndroid Build Coastguard Worker    if not HAVE_AUTOCONF_TABLE:
269*2f2c4c7aSAndroid Build Coastguard Worker      routerlft = 0
270*2f2c4c7aSAndroid Build Coastguard Worker
271*2f2c4c7aSAndroid Build Coastguard Worker    res1 = 0x10 if piopflag else 0
272*2f2c4c7aSAndroid Build Coastguard Worker
273*2f2c4c7aSAndroid Build Coastguard Worker    ra = (scapy.Ether(src=macaddr, dst="33:33:00:00:00:01") /
274*2f2c4c7aSAndroid Build Coastguard Worker          scapy.IPv6(src=lladdr, hlim=255) /
275*2f2c4c7aSAndroid Build Coastguard Worker          scapy.ICMPv6ND_RA(reachabletime=reachabletime,
276*2f2c4c7aSAndroid Build Coastguard Worker                            retranstimer=retranstimer,
277*2f2c4c7aSAndroid Build Coastguard Worker                            routerlifetime=routerlft,
278*2f2c4c7aSAndroid Build Coastguard Worker                            M=m, O=o) /
279*2f2c4c7aSAndroid Build Coastguard Worker          scapy.ICMPv6NDOptSrcLLAddr(lladdr=macaddr) /
280*2f2c4c7aSAndroid Build Coastguard Worker          scapy.ICMPv6NDOptPrefixInfo(prefix=cls.OnlinkPrefix(6, netid),
281*2f2c4c7aSAndroid Build Coastguard Worker                                      prefixlen=cls.OnlinkPrefixLen(6),
282*2f2c4c7aSAndroid Build Coastguard Worker                                      L=1, A=1, res1=res1,
283*2f2c4c7aSAndroid Build Coastguard Worker                                      validlifetime=piolft,
284*2f2c4c7aSAndroid Build Coastguard Worker                                      preferredlifetime=piolft))
285*2f2c4c7aSAndroid Build Coastguard Worker    for option in options:
286*2f2c4c7aSAndroid Build Coastguard Worker      ra /= option
287*2f2c4c7aSAndroid Build Coastguard Worker    posix.write(cls.tuns[netid].fileno(), bytes(ra))
288*2f2c4c7aSAndroid Build Coastguard Worker
289*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
290*2f2c4c7aSAndroid Build Coastguard Worker  def _RunSetupCommands(cls, netid, is_add):
291*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 6]:
292*2f2c4c7aSAndroid Build Coastguard Worker      # Find out how to configure things.
293*2f2c4c7aSAndroid Build Coastguard Worker      iface = cls.GetInterfaceName(netid)
294*2f2c4c7aSAndroid Build Coastguard Worker      ifindex = cls.ifindices[netid]
295*2f2c4c7aSAndroid Build Coastguard Worker      macaddr = cls.RouterMacAddress(netid)
296*2f2c4c7aSAndroid Build Coastguard Worker      router = cls._RouterAddress(netid, version)
297*2f2c4c7aSAndroid Build Coastguard Worker      table = cls._TableForNetid(netid)
298*2f2c4c7aSAndroid Build Coastguard Worker
299*2f2c4c7aSAndroid Build Coastguard Worker      # Set up routing rules.
300*2f2c4c7aSAndroid Build Coastguard Worker      start, end = cls.UidRangeForNetid(netid)
301*2f2c4c7aSAndroid Build Coastguard Worker      cls.iproute.UidRangeRule(version, is_add, start, end, table,
302*2f2c4c7aSAndroid Build Coastguard Worker                               cls.PRIORITY_UID)
303*2f2c4c7aSAndroid Build Coastguard Worker      cls.iproute.OifRule(version, is_add, iface, table, cls.PRIORITY_OIF)
304*2f2c4c7aSAndroid Build Coastguard Worker      cls.iproute.FwmarkRule(version, is_add, netid, cls.NETID_FWMASK, table,
305*2f2c4c7aSAndroid Build Coastguard Worker                             cls.PRIORITY_FWMARK)
306*2f2c4c7aSAndroid Build Coastguard Worker
307*2f2c4c7aSAndroid Build Coastguard Worker      # Configure routing and addressing.
308*2f2c4c7aSAndroid Build Coastguard Worker      #
309*2f2c4c7aSAndroid Build Coastguard Worker      # IPv6 uses autoconf for everything, except if per-device autoconf routing
310*2f2c4c7aSAndroid Build Coastguard Worker      # tables are not supported, in which case the default route (only) is
311*2f2c4c7aSAndroid Build Coastguard Worker      # configured manually. For IPv4 we have to manually configure addresses,
312*2f2c4c7aSAndroid Build Coastguard Worker      # routes, and neighbour cache entries (since we don't reply to ARP or ND).
313*2f2c4c7aSAndroid Build Coastguard Worker      #
314*2f2c4c7aSAndroid Build Coastguard Worker      # Since deleting addresses also causes routes to be deleted, we need to
315*2f2c4c7aSAndroid Build Coastguard Worker      # be careful with ordering or the delete commands will fail with ENOENT.
316*2f2c4c7aSAndroid Build Coastguard Worker      #
317*2f2c4c7aSAndroid Build Coastguard Worker      # A real Android system will have both IPv4 and IPv6 routes for
318*2f2c4c7aSAndroid Build Coastguard Worker      # directly-connected subnets in the per-interface routing tables. Ensure
319*2f2c4c7aSAndroid Build Coastguard Worker      # we create those as well.
320*2f2c4c7aSAndroid Build Coastguard Worker      do_routing = (version == 4 or cls.AUTOCONF_TABLE_OFFSET is None)
321*2f2c4c7aSAndroid Build Coastguard Worker      if is_add:
322*2f2c4c7aSAndroid Build Coastguard Worker        if version == 4:
323*2f2c4c7aSAndroid Build Coastguard Worker          cls.iproute.AddAddress(cls._MyIPv4Address(netid),
324*2f2c4c7aSAndroid Build Coastguard Worker                                 cls.OnlinkPrefixLen(4), ifindex)
325*2f2c4c7aSAndroid Build Coastguard Worker          cls.iproute.AddNeighbour(version, router, macaddr, ifindex)
326*2f2c4c7aSAndroid Build Coastguard Worker        if do_routing:
327*2f2c4c7aSAndroid Build Coastguard Worker          cls.iproute.AddRoute(version, table,
328*2f2c4c7aSAndroid Build Coastguard Worker                               cls.OnlinkPrefix(version, netid),
329*2f2c4c7aSAndroid Build Coastguard Worker                               cls.OnlinkPrefixLen(version), None, ifindex)
330*2f2c4c7aSAndroid Build Coastguard Worker          cls.iproute.AddRoute(version, table, "default", 0, router, ifindex)
331*2f2c4c7aSAndroid Build Coastguard Worker      else:
332*2f2c4c7aSAndroid Build Coastguard Worker        if do_routing:
333*2f2c4c7aSAndroid Build Coastguard Worker          cls.iproute.DelRoute(version, table, "default", 0, router, ifindex)
334*2f2c4c7aSAndroid Build Coastguard Worker          cls.iproute.DelRoute(version, table,
335*2f2c4c7aSAndroid Build Coastguard Worker                               cls.OnlinkPrefix(version, netid),
336*2f2c4c7aSAndroid Build Coastguard Worker                               cls.OnlinkPrefixLen(version), None, ifindex)
337*2f2c4c7aSAndroid Build Coastguard Worker        if version == 4:
338*2f2c4c7aSAndroid Build Coastguard Worker          cls.iproute.DelNeighbour(version, router, macaddr, ifindex)
339*2f2c4c7aSAndroid Build Coastguard Worker          cls.iproute.DelAddress(cls._MyIPv4Address(netid),
340*2f2c4c7aSAndroid Build Coastguard Worker                                 cls.OnlinkPrefixLen(4), ifindex)
341*2f2c4c7aSAndroid Build Coastguard Worker
342*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
343*2f2c4c7aSAndroid Build Coastguard Worker  def SetMarkReflectSysctls(cls, value):
344*2f2c4c7aSAndroid Build Coastguard Worker    """Makes kernel-generated replies use the mark of the original packet."""
345*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetSysctl(IPV4_MARK_REFLECT_SYSCTL, value)
346*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetSysctl(IPV6_MARK_REFLECT_SYSCTL, value)
347*2f2c4c7aSAndroid Build Coastguard Worker
348*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
349*2f2c4c7aSAndroid Build Coastguard Worker  def _SetInboundMarking(cls, netid, iface, is_add):
350*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 6]:
351*2f2c4c7aSAndroid Build Coastguard Worker      # Run iptables to set up incoming packet marking.
352*2f2c4c7aSAndroid Build Coastguard Worker      add_del = "-A" if is_add else "-D"
353*2f2c4c7aSAndroid Build Coastguard Worker      iptables = {4: "iptables", 6: "ip6tables"}[version]
354*2f2c4c7aSAndroid Build Coastguard Worker      args = "%s INPUT -t mangle -i %s -j MARK --set-mark %d" % (
355*2f2c4c7aSAndroid Build Coastguard Worker          add_del, iface, netid)
356*2f2c4c7aSAndroid Build Coastguard Worker      if net_test.RunIptablesCommand(version, args):
357*2f2c4c7aSAndroid Build Coastguard Worker        raise ConfigurationError("Setup command failed: %s" % args)
358*2f2c4c7aSAndroid Build Coastguard Worker
359*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
360*2f2c4c7aSAndroid Build Coastguard Worker  def SetInboundMarks(cls, is_add):
361*2f2c4c7aSAndroid Build Coastguard Worker    for netid in cls.tuns:
362*2f2c4c7aSAndroid Build Coastguard Worker      cls._SetInboundMarking(netid, cls.GetInterfaceName(netid), is_add)
363*2f2c4c7aSAndroid Build Coastguard Worker
364*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
365*2f2c4c7aSAndroid Build Coastguard Worker  def SetDefaultNetwork(cls, netid):
366*2f2c4c7aSAndroid Build Coastguard Worker    table = cls._TableForNetid(netid) if netid else None
367*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 6]:
368*2f2c4c7aSAndroid Build Coastguard Worker      is_add = table is not None
369*2f2c4c7aSAndroid Build Coastguard Worker      cls.iproute.DefaultRule(version, is_add, table, cls.PRIORITY_DEFAULT)
370*2f2c4c7aSAndroid Build Coastguard Worker
371*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
372*2f2c4c7aSAndroid Build Coastguard Worker  def ClearDefaultNetwork(cls):
373*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetDefaultNetwork(None)
374*2f2c4c7aSAndroid Build Coastguard Worker
375*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
376*2f2c4c7aSAndroid Build Coastguard Worker  def GetSysctl(cls, sysctl):
377*2f2c4c7aSAndroid Build Coastguard Worker    with open(sysctl, "r") as sysctl_file:
378*2f2c4c7aSAndroid Build Coastguard Worker      return sysctl_file.read()
379*2f2c4c7aSAndroid Build Coastguard Worker
380*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
381*2f2c4c7aSAndroid Build Coastguard Worker  def SetSysctl(cls, sysctl, value):
382*2f2c4c7aSAndroid Build Coastguard Worker    # Only save each sysctl value the first time we set it. This is so we can
383*2f2c4c7aSAndroid Build Coastguard Worker    # set it to arbitrary values multiple times and still write it back
384*2f2c4c7aSAndroid Build Coastguard Worker    # correctly at the end.
385*2f2c4c7aSAndroid Build Coastguard Worker    if sysctl not in cls.saved_sysctls:
386*2f2c4c7aSAndroid Build Coastguard Worker      cls.saved_sysctls[sysctl] = cls.GetSysctl(sysctl)
387*2f2c4c7aSAndroid Build Coastguard Worker    with open(sysctl, "w") as sysctl_file:
388*2f2c4c7aSAndroid Build Coastguard Worker      sysctl_file.write(str(value) + "\n")
389*2f2c4c7aSAndroid Build Coastguard Worker
390*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
391*2f2c4c7aSAndroid Build Coastguard Worker  def SetIPv6SysctlOnAllIfaces(cls, sysctl, value):
392*2f2c4c7aSAndroid Build Coastguard Worker    for netid in cls.tuns:
393*2f2c4c7aSAndroid Build Coastguard Worker      iface = cls.GetInterfaceName(netid)
394*2f2c4c7aSAndroid Build Coastguard Worker      name = "/proc/sys/net/ipv6/conf/%s/%s" % (iface, sysctl)
395*2f2c4c7aSAndroid Build Coastguard Worker      cls.SetSysctl(name, value)
396*2f2c4c7aSAndroid Build Coastguard Worker
397*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
398*2f2c4c7aSAndroid Build Coastguard Worker  def _RestoreSysctls(cls):
399*2f2c4c7aSAndroid Build Coastguard Worker    for sysctl, value in cls.saved_sysctls.items():
400*2f2c4c7aSAndroid Build Coastguard Worker      try:
401*2f2c4c7aSAndroid Build Coastguard Worker        with open(sysctl, "w") as sysctl_file:
402*2f2c4c7aSAndroid Build Coastguard Worker          sysctl_file.write(value)
403*2f2c4c7aSAndroid Build Coastguard Worker      except IOError:
404*2f2c4c7aSAndroid Build Coastguard Worker        pass
405*2f2c4c7aSAndroid Build Coastguard Worker
406*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
407*2f2c4c7aSAndroid Build Coastguard Worker  def _ICMPRatelimitFilename(cls, version):
408*2f2c4c7aSAndroid Build Coastguard Worker    return "/proc/sys/net/" + {4: "ipv4/icmp_ratelimit",
409*2f2c4c7aSAndroid Build Coastguard Worker                               6: "ipv6/icmp/ratelimit"}[version]
410*2f2c4c7aSAndroid Build Coastguard Worker
411*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
412*2f2c4c7aSAndroid Build Coastguard Worker  def _SetICMPRatelimit(cls, version, limit):
413*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetSysctl(cls._ICMPRatelimitFilename(version), limit)
414*2f2c4c7aSAndroid Build Coastguard Worker
415*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
416*2f2c4c7aSAndroid Build Coastguard Worker  def setUpClass(cls):
417*2f2c4c7aSAndroid Build Coastguard Worker    # This is per-class setup instead of per-testcase setup because shelling out
418*2f2c4c7aSAndroid Build Coastguard Worker    # to ip and iptables is slow, and because routing configuration doesn't
419*2f2c4c7aSAndroid Build Coastguard Worker    # change during the test.
420*2f2c4c7aSAndroid Build Coastguard Worker    cls.iproute = iproute.IPRoute()
421*2f2c4c7aSAndroid Build Coastguard Worker    cls.tuns = {}
422*2f2c4c7aSAndroid Build Coastguard Worker    cls.ifindices = {}
423*2f2c4c7aSAndroid Build Coastguard Worker    if HAVE_AUTOCONF_TABLE:
424*2f2c4c7aSAndroid Build Coastguard Worker      cls.SetSysctl(AUTOCONF_TABLE_SYSCTL, -1000)
425*2f2c4c7aSAndroid Build Coastguard Worker      cls.AUTOCONF_TABLE_OFFSET = -1000
426*2f2c4c7aSAndroid Build Coastguard Worker    else:
427*2f2c4c7aSAndroid Build Coastguard Worker      cls.AUTOCONF_TABLE_OFFSET = None
428*2f2c4c7aSAndroid Build Coastguard Worker
429*2f2c4c7aSAndroid Build Coastguard Worker    # Disable ICMP rate limits. These will be restored by _RestoreSysctls.
430*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 6]:
431*2f2c4c7aSAndroid Build Coastguard Worker      cls._SetICMPRatelimit(version, 0)
432*2f2c4c7aSAndroid Build Coastguard Worker
433*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 6]:
434*2f2c4c7aSAndroid Build Coastguard Worker      cls.iproute.UnreachableRule(version, True, cls.PRIORITY_UNREACHABLE)
435*2f2c4c7aSAndroid Build Coastguard Worker
436*2f2c4c7aSAndroid Build Coastguard Worker    for netid in cls.NETIDS:
437*2f2c4c7aSAndroid Build Coastguard Worker      cls.tuns[netid] = cls.CreateTunInterface(netid)
438*2f2c4c7aSAndroid Build Coastguard Worker      iface = cls.GetInterfaceName(netid)
439*2f2c4c7aSAndroid Build Coastguard Worker      cls.ifindices[netid] = net_test.GetInterfaceIndex(iface)
440*2f2c4c7aSAndroid Build Coastguard Worker
441*2f2c4c7aSAndroid Build Coastguard Worker      cls.SendRA(netid)
442*2f2c4c7aSAndroid Build Coastguard Worker      cls._RunSetupCommands(netid, True)
443*2f2c4c7aSAndroid Build Coastguard Worker
444*2f2c4c7aSAndroid Build Coastguard Worker    # Don't print lots of "device foo entered promiscuous mode" warnings.
445*2f2c4c7aSAndroid Build Coastguard Worker    cls.loglevel = cls.GetConsoleLogLevel()
446*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetConsoleLogLevel(net_test.KERN_INFO)
447*2f2c4c7aSAndroid Build Coastguard Worker
448*2f2c4c7aSAndroid Build Coastguard Worker    # When running on device, don't send connections through FwmarkServer.
449*2f2c4c7aSAndroid Build Coastguard Worker    os.environ["ANDROID_NO_USE_FWMARK_CLIENT"] = "1"
450*2f2c4c7aSAndroid Build Coastguard Worker
451*2f2c4c7aSAndroid Build Coastguard Worker    # Uncomment to look around at interface and rule configuration while
452*2f2c4c7aSAndroid Build Coastguard Worker    # running in the background. (Once the test finishes running, all the
453*2f2c4c7aSAndroid Build Coastguard Worker    # interfaces and rules are gone.)
454*2f2c4c7aSAndroid Build Coastguard Worker    # time.sleep(30)
455*2f2c4c7aSAndroid Build Coastguard Worker
456*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
457*2f2c4c7aSAndroid Build Coastguard Worker  def tearDownClass(cls):
458*2f2c4c7aSAndroid Build Coastguard Worker    del os.environ["ANDROID_NO_USE_FWMARK_CLIENT"]
459*2f2c4c7aSAndroid Build Coastguard Worker
460*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 6]:
461*2f2c4c7aSAndroid Build Coastguard Worker      try:
462*2f2c4c7aSAndroid Build Coastguard Worker        cls.iproute.UnreachableRule(version, False, cls.PRIORITY_UNREACHABLE)
463*2f2c4c7aSAndroid Build Coastguard Worker      except IOError:
464*2f2c4c7aSAndroid Build Coastguard Worker        pass
465*2f2c4c7aSAndroid Build Coastguard Worker
466*2f2c4c7aSAndroid Build Coastguard Worker    for netid in cls.tuns:
467*2f2c4c7aSAndroid Build Coastguard Worker      cls._RunSetupCommands(netid, False)
468*2f2c4c7aSAndroid Build Coastguard Worker      cls.tuns[netid].close()
469*2f2c4c7aSAndroid Build Coastguard Worker
470*2f2c4c7aSAndroid Build Coastguard Worker    cls.iproute.close()
471*2f2c4c7aSAndroid Build Coastguard Worker    cls._RestoreSysctls()
472*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetConsoleLogLevel(cls.loglevel)
473*2f2c4c7aSAndroid Build Coastguard Worker
474*2f2c4c7aSAndroid Build Coastguard Worker  def setUp(self):
475*2f2c4c7aSAndroid Build Coastguard Worker    self.ClearTunQueues()
476*2f2c4c7aSAndroid Build Coastguard Worker
477*2f2c4c7aSAndroid Build Coastguard Worker  def SetSocketMark(self, s, netid):
478*2f2c4c7aSAndroid Build Coastguard Worker    if netid is None:
479*2f2c4c7aSAndroid Build Coastguard Worker      netid = 0
480*2f2c4c7aSAndroid Build Coastguard Worker    s.setsockopt(SOL_SOCKET, net_test.SO_MARK, netid)
481*2f2c4c7aSAndroid Build Coastguard Worker
482*2f2c4c7aSAndroid Build Coastguard Worker  def GetSocketMark(self, s):
483*2f2c4c7aSAndroid Build Coastguard Worker    return s.getsockopt(SOL_SOCKET, net_test.SO_MARK)
484*2f2c4c7aSAndroid Build Coastguard Worker
485*2f2c4c7aSAndroid Build Coastguard Worker  def ClearSocketMark(self, s):
486*2f2c4c7aSAndroid Build Coastguard Worker    self.SetSocketMark(s, 0)
487*2f2c4c7aSAndroid Build Coastguard Worker
488*2f2c4c7aSAndroid Build Coastguard Worker  def BindToDevice(self, s, iface):
489*2f2c4c7aSAndroid Build Coastguard Worker    if not iface:
490*2f2c4c7aSAndroid Build Coastguard Worker      iface = ""
491*2f2c4c7aSAndroid Build Coastguard Worker    s.setsockopt(SOL_SOCKET, SO_BINDTODEVICE, iface.encode())
492*2f2c4c7aSAndroid Build Coastguard Worker
493*2f2c4c7aSAndroid Build Coastguard Worker  def SetUnicastInterface(self, s, ifindex):
494*2f2c4c7aSAndroid Build Coastguard Worker    # Otherwise, Python thinks it's a 1-byte option.
495*2f2c4c7aSAndroid Build Coastguard Worker    ifindex = struct.pack("!I", ifindex)
496*2f2c4c7aSAndroid Build Coastguard Worker
497*2f2c4c7aSAndroid Build Coastguard Worker    # Always set the IPv4 interface, because it will be used even on IPv6
498*2f2c4c7aSAndroid Build Coastguard Worker    # sockets if the destination address is a mapped address.
499*2f2c4c7aSAndroid Build Coastguard Worker    s.setsockopt(net_test.SOL_IP, IP_UNICAST_IF, ifindex)
500*2f2c4c7aSAndroid Build Coastguard Worker    if s.family == AF_INET6:
501*2f2c4c7aSAndroid Build Coastguard Worker      s.setsockopt(net_test.SOL_IPV6, IPV6_UNICAST_IF, ifindex)
502*2f2c4c7aSAndroid Build Coastguard Worker
503*2f2c4c7aSAndroid Build Coastguard Worker  def GetRemoteAddress(self, version):
504*2f2c4c7aSAndroid Build Coastguard Worker    return {4: self.IPV4_ADDR,
505*2f2c4c7aSAndroid Build Coastguard Worker            5: self.IPV4_ADDR,  # see GetRemoteSocketAddress()
506*2f2c4c7aSAndroid Build Coastguard Worker            6: self.IPV6_ADDR}[version]
507*2f2c4c7aSAndroid Build Coastguard Worker
508*2f2c4c7aSAndroid Build Coastguard Worker  def GetRemoteSocketAddress(self, version):
509*2f2c4c7aSAndroid Build Coastguard Worker    addr = self.GetRemoteAddress(version)
510*2f2c4c7aSAndroid Build Coastguard Worker    return "::ffff:" + addr if version == 5 else addr
511*2f2c4c7aSAndroid Build Coastguard Worker
512*2f2c4c7aSAndroid Build Coastguard Worker  def GetOtherRemoteSocketAddress(self, version):
513*2f2c4c7aSAndroid Build Coastguard Worker    return {4: self.IPV4_ADDR2,
514*2f2c4c7aSAndroid Build Coastguard Worker            5: "::ffff:" + self.IPV4_ADDR2,
515*2f2c4c7aSAndroid Build Coastguard Worker            6: self.IPV6_ADDR2}[version]
516*2f2c4c7aSAndroid Build Coastguard Worker
517*2f2c4c7aSAndroid Build Coastguard Worker  def SelectInterface(self, s, netid, mode):
518*2f2c4c7aSAndroid Build Coastguard Worker    if mode == "uid":
519*2f2c4c7aSAndroid Build Coastguard Worker      os.fchown(s.fileno(), self.UidForNetid(netid), -1)
520*2f2c4c7aSAndroid Build Coastguard Worker    elif mode == "mark":
521*2f2c4c7aSAndroid Build Coastguard Worker      self.SetSocketMark(s, netid)
522*2f2c4c7aSAndroid Build Coastguard Worker    elif mode == "oif":
523*2f2c4c7aSAndroid Build Coastguard Worker      iface = self.GetInterfaceName(netid) if netid else ""
524*2f2c4c7aSAndroid Build Coastguard Worker      self.BindToDevice(s, iface)
525*2f2c4c7aSAndroid Build Coastguard Worker    elif mode == "ucast_oif":
526*2f2c4c7aSAndroid Build Coastguard Worker      self.SetUnicastInterface(s, self.ifindices.get(netid, 0))
527*2f2c4c7aSAndroid Build Coastguard Worker    else:
528*2f2c4c7aSAndroid Build Coastguard Worker      raise ValueError("Unknown interface selection mode %s" % mode)
529*2f2c4c7aSAndroid Build Coastguard Worker
530*2f2c4c7aSAndroid Build Coastguard Worker  def BuildSocket(self, version, constructor, netid, routing_mode):
531*2f2c4c7aSAndroid Build Coastguard Worker    if version == 5: version = 6
532*2f2c4c7aSAndroid Build Coastguard Worker    s = constructor(self.GetProtocolFamily(version))
533*2f2c4c7aSAndroid Build Coastguard Worker
534*2f2c4c7aSAndroid Build Coastguard Worker    if routing_mode not in [None, "uid"]:
535*2f2c4c7aSAndroid Build Coastguard Worker      self.SelectInterface(s, netid, routing_mode)
536*2f2c4c7aSAndroid Build Coastguard Worker    elif routing_mode == "uid":
537*2f2c4c7aSAndroid Build Coastguard Worker      os.fchown(s.fileno(), self.UidForNetid(netid), -1)
538*2f2c4c7aSAndroid Build Coastguard Worker
539*2f2c4c7aSAndroid Build Coastguard Worker    return s
540*2f2c4c7aSAndroid Build Coastguard Worker
541*2f2c4c7aSAndroid Build Coastguard Worker  def RandomNetid(self, exclude=None):
542*2f2c4c7aSAndroid Build Coastguard Worker    """Return a random netid from the list of netids
543*2f2c4c7aSAndroid Build Coastguard Worker
544*2f2c4c7aSAndroid Build Coastguard Worker    Args:
545*2f2c4c7aSAndroid Build Coastguard Worker      exclude: a netid or list of netids that should not be chosen
546*2f2c4c7aSAndroid Build Coastguard Worker    """
547*2f2c4c7aSAndroid Build Coastguard Worker    if exclude is None:
548*2f2c4c7aSAndroid Build Coastguard Worker      exclude = []
549*2f2c4c7aSAndroid Build Coastguard Worker    elif isinstance(exclude, int):
550*2f2c4c7aSAndroid Build Coastguard Worker        exclude = [exclude]
551*2f2c4c7aSAndroid Build Coastguard Worker    diff = [netid for netid in self.NETIDS if netid not in exclude]
552*2f2c4c7aSAndroid Build Coastguard Worker    return random.choice(diff)
553*2f2c4c7aSAndroid Build Coastguard Worker
554*2f2c4c7aSAndroid Build Coastguard Worker  def SendOnNetid(self, version, s, dstaddr, dstport, netid, payload, cmsgs):
555*2f2c4c7aSAndroid Build Coastguard Worker    if netid is not None:
556*2f2c4c7aSAndroid Build Coastguard Worker      pktinfo = MakePktInfo(version, None, self.ifindices[netid])
557*2f2c4c7aSAndroid Build Coastguard Worker      cmsg_level, cmsg_name = {
558*2f2c4c7aSAndroid Build Coastguard Worker          4: (net_test.SOL_IP, csocket.IP_PKTINFO),
559*2f2c4c7aSAndroid Build Coastguard Worker          6: (net_test.SOL_IPV6, csocket.IPV6_PKTINFO)}[version]
560*2f2c4c7aSAndroid Build Coastguard Worker      cmsgs.append((cmsg_level, cmsg_name, pktinfo))
561*2f2c4c7aSAndroid Build Coastguard Worker    csocket.Sendmsg(s, (dstaddr, dstport), payload, cmsgs, csocket.MSG_CONFIRM)
562*2f2c4c7aSAndroid Build Coastguard Worker
563*2f2c4c7aSAndroid Build Coastguard Worker  def ReceiveEtherPacketOn(self, netid, packet):
564*2f2c4c7aSAndroid Build Coastguard Worker    posix.write(self.tuns[netid].fileno(), bytes(packet))
565*2f2c4c7aSAndroid Build Coastguard Worker
566*2f2c4c7aSAndroid Build Coastguard Worker  def ReceivePacketOn(self, netid, ip_packet):
567*2f2c4c7aSAndroid Build Coastguard Worker    routermac = self.RouterMacAddress(netid)
568*2f2c4c7aSAndroid Build Coastguard Worker    mymac = self.MyMacAddress(netid)
569*2f2c4c7aSAndroid Build Coastguard Worker    packet = scapy.Ether(src=routermac, dst=mymac) / ip_packet
570*2f2c4c7aSAndroid Build Coastguard Worker    self.ReceiveEtherPacketOn(netid, packet)
571*2f2c4c7aSAndroid Build Coastguard Worker
572*2f2c4c7aSAndroid Build Coastguard Worker  def ReadAllPacketsOn(self, netid, include_multicast=False):
573*2f2c4c7aSAndroid Build Coastguard Worker    """Return all queued packets on a netid as a list.
574*2f2c4c7aSAndroid Build Coastguard Worker
575*2f2c4c7aSAndroid Build Coastguard Worker    Args:
576*2f2c4c7aSAndroid Build Coastguard Worker      netid: The netid from which to read packets
577*2f2c4c7aSAndroid Build Coastguard Worker      include_multicast: A boolean, whether to remove multicast packets
578*2f2c4c7aSAndroid Build Coastguard Worker        (default=False)
579*2f2c4c7aSAndroid Build Coastguard Worker    """
580*2f2c4c7aSAndroid Build Coastguard Worker    packets = []
581*2f2c4c7aSAndroid Build Coastguard Worker    retries = 0
582*2f2c4c7aSAndroid Build Coastguard Worker    max_retries = 1
583*2f2c4c7aSAndroid Build Coastguard Worker    while True:
584*2f2c4c7aSAndroid Build Coastguard Worker      try:
585*2f2c4c7aSAndroid Build Coastguard Worker        packet = posix.read(self.tuns[netid].fileno(), 4096)
586*2f2c4c7aSAndroid Build Coastguard Worker        if not packet:
587*2f2c4c7aSAndroid Build Coastguard Worker          break
588*2f2c4c7aSAndroid Build Coastguard Worker        ether = scapy.Ether(packet)
589*2f2c4c7aSAndroid Build Coastguard Worker        # Multicast frames are frames where the first byte of the destination
590*2f2c4c7aSAndroid Build Coastguard Worker        # MAC address has 1 in the least-significant bit.
591*2f2c4c7aSAndroid Build Coastguard Worker        if include_multicast or not int(ether.dst.split(":")[0], 16) & 0x1:
592*2f2c4c7aSAndroid Build Coastguard Worker          packets.append(ether.payload)
593*2f2c4c7aSAndroid Build Coastguard Worker      except OSError as e:
594*2f2c4c7aSAndroid Build Coastguard Worker        # EAGAIN means there are no more packets waiting.
595*2f2c4c7aSAndroid Build Coastguard Worker        if e.errno == errno.EAGAIN:
596*2f2c4c7aSAndroid Build Coastguard Worker          # If we didn't see any packets, try again for good luck.
597*2f2c4c7aSAndroid Build Coastguard Worker          if not packets and retries < max_retries:
598*2f2c4c7aSAndroid Build Coastguard Worker            time.sleep(0.01)
599*2f2c4c7aSAndroid Build Coastguard Worker            retries += 1
600*2f2c4c7aSAndroid Build Coastguard Worker            continue
601*2f2c4c7aSAndroid Build Coastguard Worker          else:
602*2f2c4c7aSAndroid Build Coastguard Worker            break
603*2f2c4c7aSAndroid Build Coastguard Worker        # Anything else is unexpected.
604*2f2c4c7aSAndroid Build Coastguard Worker        else:
605*2f2c4c7aSAndroid Build Coastguard Worker          raise e
606*2f2c4c7aSAndroid Build Coastguard Worker    return packets
607*2f2c4c7aSAndroid Build Coastguard Worker
608*2f2c4c7aSAndroid Build Coastguard Worker  def InvalidateDstCache(self, version, netid):
609*2f2c4c7aSAndroid Build Coastguard Worker    """Invalidates destination cache entries of sockets on the specified table.
610*2f2c4c7aSAndroid Build Coastguard Worker
611*2f2c4c7aSAndroid Build Coastguard Worker    Creates and then deletes a low-priority throw route in the table for the
612*2f2c4c7aSAndroid Build Coastguard Worker    given netid, which invalidates the destination cache entries of any sockets
613*2f2c4c7aSAndroid Build Coastguard Worker    that refer to routes in that table.
614*2f2c4c7aSAndroid Build Coastguard Worker
615*2f2c4c7aSAndroid Build Coastguard Worker    The fact that this method actually invalidates destination cache entries is
616*2f2c4c7aSAndroid Build Coastguard Worker    tested by OutgoingTest#testIPv[46]Remarking, which checks that the kernel
617*2f2c4c7aSAndroid Build Coastguard Worker    does not re-route sockets when they are remarked, but does re-route them if
618*2f2c4c7aSAndroid Build Coastguard Worker    this method is called.
619*2f2c4c7aSAndroid Build Coastguard Worker
620*2f2c4c7aSAndroid Build Coastguard Worker    Args:
621*2f2c4c7aSAndroid Build Coastguard Worker      version: The IP version, 4 or 6.
622*2f2c4c7aSAndroid Build Coastguard Worker      netid: The netid to invalidate dst caches on.
623*2f2c4c7aSAndroid Build Coastguard Worker    """
624*2f2c4c7aSAndroid Build Coastguard Worker    iface = self.GetInterfaceName(netid)
625*2f2c4c7aSAndroid Build Coastguard Worker    ifindex = self.ifindices[netid]
626*2f2c4c7aSAndroid Build Coastguard Worker    table = self._TableForNetid(netid)
627*2f2c4c7aSAndroid Build Coastguard Worker    for action in [iproute.RTM_NEWROUTE, iproute.RTM_DELROUTE]:
628*2f2c4c7aSAndroid Build Coastguard Worker      self.iproute._Route(version, iproute.RTPROT_STATIC, action, table,
629*2f2c4c7aSAndroid Build Coastguard Worker                          "default", 0, nexthop=None, dev=None, mark=None,
630*2f2c4c7aSAndroid Build Coastguard Worker                          uid=None, route_type=iproute.RTN_THROW,
631*2f2c4c7aSAndroid Build Coastguard Worker                          priority=100000)
632*2f2c4c7aSAndroid Build Coastguard Worker
633*2f2c4c7aSAndroid Build Coastguard Worker  def ClearTunQueues(self):
634*2f2c4c7aSAndroid Build Coastguard Worker    # Keep reading packets on all netids until we get no packets on any of them.
635*2f2c4c7aSAndroid Build Coastguard Worker    waiting = None
636*2f2c4c7aSAndroid Build Coastguard Worker    while waiting != 0:
637*2f2c4c7aSAndroid Build Coastguard Worker      waiting = sum(len(self.ReadAllPacketsOn(netid)) for netid in self.NETIDS)
638*2f2c4c7aSAndroid Build Coastguard Worker
639*2f2c4c7aSAndroid Build Coastguard Worker  def assertPacketMatches(self, expected, actual):
640*2f2c4c7aSAndroid Build Coastguard Worker    # The expected packet is just a rough sketch of the packet we expect to
641*2f2c4c7aSAndroid Build Coastguard Worker    # receive. For example, it doesn't contain fields we can't predict, such as
642*2f2c4c7aSAndroid Build Coastguard Worker    # initial TCP sequence numbers, or that depend on the host implementation
643*2f2c4c7aSAndroid Build Coastguard Worker    # and settings, such as TCP options. To check whether the packet matches
644*2f2c4c7aSAndroid Build Coastguard Worker    # what we expect, instead of just checking all the known fields one by one,
645*2f2c4c7aSAndroid Build Coastguard Worker    # we blank out fields in the actual packet and then compare the whole
646*2f2c4c7aSAndroid Build Coastguard Worker    # packets to each other as strings. Because we modify the actual packet,
647*2f2c4c7aSAndroid Build Coastguard Worker    # make a copy here.
648*2f2c4c7aSAndroid Build Coastguard Worker    actual = actual.copy()
649*2f2c4c7aSAndroid Build Coastguard Worker
650*2f2c4c7aSAndroid Build Coastguard Worker    # Blank out IPv4 fields that we can't predict, like ID and the DF bit.
651*2f2c4c7aSAndroid Build Coastguard Worker    actualip = actual.getlayer("IP")
652*2f2c4c7aSAndroid Build Coastguard Worker    expectedip = expected.getlayer("IP")
653*2f2c4c7aSAndroid Build Coastguard Worker    if actualip and expectedip:
654*2f2c4c7aSAndroid Build Coastguard Worker      actualip.id = expectedip.id
655*2f2c4c7aSAndroid Build Coastguard Worker      actualip.flags &= 5
656*2f2c4c7aSAndroid Build Coastguard Worker      actualip.chksum = None  # Change the header, recalculate the checksum.
657*2f2c4c7aSAndroid Build Coastguard Worker
658*2f2c4c7aSAndroid Build Coastguard Worker    # Blank out the flow label, since new kernels randomize it by default.
659*2f2c4c7aSAndroid Build Coastguard Worker    actualipv6 = actual.getlayer("IPv6")
660*2f2c4c7aSAndroid Build Coastguard Worker    expectedipv6 = expected.getlayer("IPv6")
661*2f2c4c7aSAndroid Build Coastguard Worker    if actualipv6 and expectedipv6:
662*2f2c4c7aSAndroid Build Coastguard Worker      actualipv6.fl = expectedipv6.fl
663*2f2c4c7aSAndroid Build Coastguard Worker
664*2f2c4c7aSAndroid Build Coastguard Worker    # Blank out UDP fields that we can't predict (e.g., the source port for
665*2f2c4c7aSAndroid Build Coastguard Worker    # kernel-originated packets).
666*2f2c4c7aSAndroid Build Coastguard Worker    actualudp = actual.getlayer("UDP")
667*2f2c4c7aSAndroid Build Coastguard Worker    expectedudp = expected.getlayer("UDP")
668*2f2c4c7aSAndroid Build Coastguard Worker    if actualudp and expectedudp:
669*2f2c4c7aSAndroid Build Coastguard Worker      if expectedudp.sport is None:
670*2f2c4c7aSAndroid Build Coastguard Worker        actualudp.sport = None
671*2f2c4c7aSAndroid Build Coastguard Worker        actualudp.chksum = None
672*2f2c4c7aSAndroid Build Coastguard Worker      elif actualudp.chksum == 0xffff and expectedudp.chksum == 0:
673*2f2c4c7aSAndroid Build Coastguard Worker        # Scapy does not appear to change 0 to 0xffff as required by RFC 768.
674*2f2c4c7aSAndroid Build Coastguard Worker        # It is possible that scapy has been upgraded and this no longer triggers.
675*2f2c4c7aSAndroid Build Coastguard Worker        actualudp.chksum = 0
676*2f2c4c7aSAndroid Build Coastguard Worker
677*2f2c4c7aSAndroid Build Coastguard Worker    # Since the TCP code below messes with options, recalculate the length.
678*2f2c4c7aSAndroid Build Coastguard Worker    if actualip:
679*2f2c4c7aSAndroid Build Coastguard Worker      actualip.len = None
680*2f2c4c7aSAndroid Build Coastguard Worker    if actualipv6:
681*2f2c4c7aSAndroid Build Coastguard Worker      actualipv6.plen = None
682*2f2c4c7aSAndroid Build Coastguard Worker
683*2f2c4c7aSAndroid Build Coastguard Worker    # Blank out TCP fields that we can't predict.
684*2f2c4c7aSAndroid Build Coastguard Worker    actualtcp = actual.getlayer("TCP")
685*2f2c4c7aSAndroid Build Coastguard Worker    expectedtcp = expected.getlayer("TCP")
686*2f2c4c7aSAndroid Build Coastguard Worker    if actualtcp and expectedtcp:
687*2f2c4c7aSAndroid Build Coastguard Worker      actualtcp.dataofs = expectedtcp.dataofs
688*2f2c4c7aSAndroid Build Coastguard Worker      actualtcp.options = expectedtcp.options
689*2f2c4c7aSAndroid Build Coastguard Worker      actualtcp.window = expectedtcp.window
690*2f2c4c7aSAndroid Build Coastguard Worker      if expectedtcp.sport is None:
691*2f2c4c7aSAndroid Build Coastguard Worker        actualtcp.sport = None
692*2f2c4c7aSAndroid Build Coastguard Worker      if expectedtcp.seq is None:
693*2f2c4c7aSAndroid Build Coastguard Worker        actualtcp.seq = None
694*2f2c4c7aSAndroid Build Coastguard Worker      if expectedtcp.ack is None:
695*2f2c4c7aSAndroid Build Coastguard Worker        actualtcp.ack = None
696*2f2c4c7aSAndroid Build Coastguard Worker      actualtcp.chksum = None
697*2f2c4c7aSAndroid Build Coastguard Worker
698*2f2c4c7aSAndroid Build Coastguard Worker    # Serialize the packet so that expected packet fields that are only set when
699*2f2c4c7aSAndroid Build Coastguard Worker    # a packet is serialized e.g., the checksum) are filled in.
700*2f2c4c7aSAndroid Build Coastguard Worker    expected_real = expected.__class__(bytes(expected))
701*2f2c4c7aSAndroid Build Coastguard Worker    actual_real = actual.__class__(bytes(actual))
702*2f2c4c7aSAndroid Build Coastguard Worker    # repr() can be expensive. Call it only if the test is going to fail and we
703*2f2c4c7aSAndroid Build Coastguard Worker    # want to see the error.
704*2f2c4c7aSAndroid Build Coastguard Worker    if expected_real != actual_real:
705*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(repr(expected_real), repr(actual_real))
706*2f2c4c7aSAndroid Build Coastguard Worker
707*2f2c4c7aSAndroid Build Coastguard Worker  def PacketMatches(self, expected, actual):
708*2f2c4c7aSAndroid Build Coastguard Worker    try:
709*2f2c4c7aSAndroid Build Coastguard Worker      self.assertPacketMatches(expected, actual)
710*2f2c4c7aSAndroid Build Coastguard Worker      return True
711*2f2c4c7aSAndroid Build Coastguard Worker    except AssertionError:
712*2f2c4c7aSAndroid Build Coastguard Worker      return False
713*2f2c4c7aSAndroid Build Coastguard Worker
714*2f2c4c7aSAndroid Build Coastguard Worker  def ExpectNoPacketsOn(self, netid, msg):
715*2f2c4c7aSAndroid Build Coastguard Worker    packets = self.ReadAllPacketsOn(netid)
716*2f2c4c7aSAndroid Build Coastguard Worker    if packets:
717*2f2c4c7aSAndroid Build Coastguard Worker      firstpacket = repr(packets[0])
718*2f2c4c7aSAndroid Build Coastguard Worker    else:
719*2f2c4c7aSAndroid Build Coastguard Worker      firstpacket = ""
720*2f2c4c7aSAndroid Build Coastguard Worker    self.assertFalse(packets, msg + ": unexpected packet: " + firstpacket)
721*2f2c4c7aSAndroid Build Coastguard Worker
722*2f2c4c7aSAndroid Build Coastguard Worker  def ExpectPacketOn(self, netid, msg, expected):
723*2f2c4c7aSAndroid Build Coastguard Worker    # To avoid confusion due to lots of ICMPv6 ND going on all the time, drop
724*2f2c4c7aSAndroid Build Coastguard Worker    # multicast packets unless the packet we expect to see is a multicast
725*2f2c4c7aSAndroid Build Coastguard Worker    # packet. For now the only tests that use this are IPv6.
726*2f2c4c7aSAndroid Build Coastguard Worker    ipv6 = expected.getlayer("IPv6")
727*2f2c4c7aSAndroid Build Coastguard Worker    if ipv6 and ipv6.dst.startswith("ff"):
728*2f2c4c7aSAndroid Build Coastguard Worker      include_multicast = True
729*2f2c4c7aSAndroid Build Coastguard Worker    else:
730*2f2c4c7aSAndroid Build Coastguard Worker      include_multicast = False
731*2f2c4c7aSAndroid Build Coastguard Worker
732*2f2c4c7aSAndroid Build Coastguard Worker    packets = self.ReadAllPacketsOn(netid, include_multicast=include_multicast)
733*2f2c4c7aSAndroid Build Coastguard Worker    self.assertTrue(packets, msg + ": received no packets")
734*2f2c4c7aSAndroid Build Coastguard Worker
735*2f2c4c7aSAndroid Build Coastguard Worker    # If we receive a packet that matches what we expected, return it.
736*2f2c4c7aSAndroid Build Coastguard Worker    for packet in packets:
737*2f2c4c7aSAndroid Build Coastguard Worker      if self.PacketMatches(expected, packet):
738*2f2c4c7aSAndroid Build Coastguard Worker        return packet
739*2f2c4c7aSAndroid Build Coastguard Worker
740*2f2c4c7aSAndroid Build Coastguard Worker    # None of the packets matched. Call assertPacketMatches to output a diff
741*2f2c4c7aSAndroid Build Coastguard Worker    # between the expected packet and the last packet we received. In theory,
742*2f2c4c7aSAndroid Build Coastguard Worker    # we'd output a diff to the packet that's the best match for what we
743*2f2c4c7aSAndroid Build Coastguard Worker    # expected, but this is good enough for now.
744*2f2c4c7aSAndroid Build Coastguard Worker    try:
745*2f2c4c7aSAndroid Build Coastguard Worker      self.assertPacketMatches(expected, packets[-1])
746*2f2c4c7aSAndroid Build Coastguard Worker    except Exception as e:
747*2f2c4c7aSAndroid Build Coastguard Worker      raise UnexpectedPacketError(
748*2f2c4c7aSAndroid Build Coastguard Worker          "%s: diff with last packet:\n%s" % (msg, str(e)))
749*2f2c4c7aSAndroid Build Coastguard Worker
750*2f2c4c7aSAndroid Build Coastguard Worker  def Combinations(self, version):
751*2f2c4c7aSAndroid Build Coastguard Worker    """Produces a list of combinations to test."""
752*2f2c4c7aSAndroid Build Coastguard Worker    combinations = []
753*2f2c4c7aSAndroid Build Coastguard Worker
754*2f2c4c7aSAndroid Build Coastguard Worker    # Check packets addressed to the IP addresses of all our interfaces...
755*2f2c4c7aSAndroid Build Coastguard Worker    for dest_ip_netid in self.tuns:
756*2f2c4c7aSAndroid Build Coastguard Worker      ip_if = self.GetInterfaceName(dest_ip_netid)
757*2f2c4c7aSAndroid Build Coastguard Worker      myaddr = self.MyAddress(version, dest_ip_netid)
758*2f2c4c7aSAndroid Build Coastguard Worker      prefix = {4: "172.22.", 6: "2001:db8:aaaa::"}[version]
759*2f2c4c7aSAndroid Build Coastguard Worker      remoteaddr = self.GetRandomDestination(prefix)
760*2f2c4c7aSAndroid Build Coastguard Worker
761*2f2c4c7aSAndroid Build Coastguard Worker      # ... coming in on all our interfaces.
762*2f2c4c7aSAndroid Build Coastguard Worker      for netid in self.tuns:
763*2f2c4c7aSAndroid Build Coastguard Worker        iif = self.GetInterfaceName(netid)
764*2f2c4c7aSAndroid Build Coastguard Worker        combinations.append((netid, iif, ip_if, myaddr, remoteaddr))
765*2f2c4c7aSAndroid Build Coastguard Worker
766*2f2c4c7aSAndroid Build Coastguard Worker    return combinations
767*2f2c4c7aSAndroid Build Coastguard Worker
768*2f2c4c7aSAndroid Build Coastguard Worker  def _FormatMessage(self, iif, ip_if, extra, desc, reply_desc):
769*2f2c4c7aSAndroid Build Coastguard Worker    msg = "Receiving %s on %s to %s IP, %s" % (desc, iif, ip_if, extra)
770*2f2c4c7aSAndroid Build Coastguard Worker    if reply_desc:
771*2f2c4c7aSAndroid Build Coastguard Worker      msg += ": Expecting %s on %s" % (reply_desc, iif)
772*2f2c4c7aSAndroid Build Coastguard Worker    else:
773*2f2c4c7aSAndroid Build Coastguard Worker      msg += ": Expecting no packets on %s" % iif
774*2f2c4c7aSAndroid Build Coastguard Worker    return msg
775*2f2c4c7aSAndroid Build Coastguard Worker
776*2f2c4c7aSAndroid Build Coastguard Worker  def _ReceiveAndExpectResponse(self, netid, packet, reply, msg):
777*2f2c4c7aSAndroid Build Coastguard Worker    self.ReceivePacketOn(netid, packet)
778*2f2c4c7aSAndroid Build Coastguard Worker    if reply:
779*2f2c4c7aSAndroid Build Coastguard Worker      return self.ExpectPacketOn(netid, msg, reply)
780*2f2c4c7aSAndroid Build Coastguard Worker    else:
781*2f2c4c7aSAndroid Build Coastguard Worker      self.ExpectNoPacketsOn(netid, msg)
782*2f2c4c7aSAndroid Build Coastguard Worker      return None
783*2f2c4c7aSAndroid Build Coastguard Worker
784*2f2c4c7aSAndroid Build Coastguard Worker
785*2f2c4c7aSAndroid Build Coastguard Workerclass InboundMarkingTest(MultiNetworkBaseTest):
786*2f2c4c7aSAndroid Build Coastguard Worker  """Class that automatically sets up inbound marking."""
787*2f2c4c7aSAndroid Build Coastguard Worker
788*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
789*2f2c4c7aSAndroid Build Coastguard Worker  def setUpClass(cls):
790*2f2c4c7aSAndroid Build Coastguard Worker    super(InboundMarkingTest, cls).setUpClass()
791*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetInboundMarks(True)
792*2f2c4c7aSAndroid Build Coastguard Worker
793*2f2c4c7aSAndroid Build Coastguard Worker  @classmethod
794*2f2c4c7aSAndroid Build Coastguard Worker  def tearDownClass(cls):
795*2f2c4c7aSAndroid Build Coastguard Worker    cls.SetInboundMarks(False)
796*2f2c4c7aSAndroid Build Coastguard Worker    super(InboundMarkingTest, cls).tearDownClass()
797