xref: /aosp_15_r20/kernel/tests/net/test/srcaddr_selection_test.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 Workerimport errno
18*2f2c4c7aSAndroid Build Coastguard Workerimport random
19*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import *  # pylint: disable=wildcard-import
20*2f2c4c7aSAndroid Build Coastguard Workerimport time
21*2f2c4c7aSAndroid Build Coastguard Workerimport unittest
22*2f2c4c7aSAndroid Build Coastguard Worker
23*2f2c4c7aSAndroid Build Coastguard Workerfrom scapy import all as scapy
24*2f2c4c7aSAndroid Build Coastguard Worker
25*2f2c4c7aSAndroid Build Coastguard Workerimport csocket
26*2f2c4c7aSAndroid Build Coastguard Workerimport iproute
27*2f2c4c7aSAndroid Build Coastguard Workerimport multinetwork_base
28*2f2c4c7aSAndroid Build Coastguard Workerimport packets
29*2f2c4c7aSAndroid Build Coastguard Workerimport net_test
30*2f2c4c7aSAndroid Build Coastguard Worker
31*2f2c4c7aSAndroid Build Coastguard Worker# Setsockopt values.
32*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_ADDR_PREFERENCES = 72
33*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_PREFER_SRC_PUBLIC = 0x0002
34*2f2c4c7aSAndroid Build Coastguard Worker
35*2f2c4c7aSAndroid Build Coastguard Worker# The retrans timer is also the DAD timeout. We set this to a value that's not
36*2f2c4c7aSAndroid Build Coastguard Worker# so short that DAD will complete before we attempt to use the network, but
37*2f2c4c7aSAndroid Build Coastguard Worker# short enough that we don't have to wait too long for DAD to complete.
38*2f2c4c7aSAndroid Build Coastguard WorkerRETRANS_TIMER = 150
39*2f2c4c7aSAndroid Build Coastguard Worker
40*2f2c4c7aSAndroid Build Coastguard Worker
41*2f2c4c7aSAndroid Build Coastguard Workerclass IPv6SourceAddressSelectionTest(multinetwork_base.MultiNetworkBaseTest):
42*2f2c4c7aSAndroid Build Coastguard Worker  """Test for IPv6 source address selection.
43*2f2c4c7aSAndroid Build Coastguard Worker
44*2f2c4c7aSAndroid Build Coastguard Worker  Relevant kernel commits:
45*2f2c4c7aSAndroid Build Coastguard Worker    upstream net-next:
46*2f2c4c7aSAndroid Build Coastguard Worker      7fd2561 net: ipv6: Add a sysctl to make optimistic addresses useful candidates
47*2f2c4c7aSAndroid Build Coastguard Worker      c58da4c net: ipv6: allow explicitly choosing optimistic addresses
48*2f2c4c7aSAndroid Build Coastguard Worker      9131f3d ipv6: Do not iterate over all interfaces when finding source address on specific interface.
49*2f2c4c7aSAndroid Build Coastguard Worker      c0b8da1 ipv6: Fix finding best source address in ipv6_dev_get_saddr().
50*2f2c4c7aSAndroid Build Coastguard Worker      c15df30 ipv6: Remove unused arguments for __ipv6_dev_get_saddr().
51*2f2c4c7aSAndroid Build Coastguard Worker      3985e8a ipv6: sysctl to restrict candidate source addresses
52*2f2c4c7aSAndroid Build Coastguard Worker
53*2f2c4c7aSAndroid Build Coastguard Worker    android-3.10:
54*2f2c4c7aSAndroid Build Coastguard Worker      2ce95507 net: ipv6: Add a sysctl to make optimistic addresses useful candidates
55*2f2c4c7aSAndroid Build Coastguard Worker      0065bf4 net: ipv6: allow choosing optimistic addresses with use_optimistic
56*2f2c4c7aSAndroid Build Coastguard Worker      0633924 ipv6: sysctl to restrict candidate source addresses
57*2f2c4c7aSAndroid Build Coastguard Worker  """
58*2f2c4c7aSAndroid Build Coastguard Worker
59*2f2c4c7aSAndroid Build Coastguard Worker  def SetIPv6Sysctl(self, ifname, sysctl, value):
60*2f2c4c7aSAndroid Build Coastguard Worker    self.SetSysctl("/proc/sys/net/ipv6/conf/%s/%s" % (ifname, sysctl), value)
61*2f2c4c7aSAndroid Build Coastguard Worker
62*2f2c4c7aSAndroid Build Coastguard Worker  def SetDAD(self, ifname, value):
63*2f2c4c7aSAndroid Build Coastguard Worker    self.SetSysctl("/proc/sys/net/ipv6/conf/%s/accept_dad" % ifname, value)
64*2f2c4c7aSAndroid Build Coastguard Worker    self.SetSysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits" % ifname, value)
65*2f2c4c7aSAndroid Build Coastguard Worker
66*2f2c4c7aSAndroid Build Coastguard Worker  def SetOptimisticDAD(self, ifname, value):
67*2f2c4c7aSAndroid Build Coastguard Worker    self.SetSysctl("/proc/sys/net/ipv6/conf/%s/optimistic_dad" % ifname, value)
68*2f2c4c7aSAndroid Build Coastguard Worker
69*2f2c4c7aSAndroid Build Coastguard Worker  def SetUseTempaddrs(self, ifname, value):
70*2f2c4c7aSAndroid Build Coastguard Worker    self.SetSysctl("/proc/sys/net/ipv6/conf/%s/use_tempaddr" % ifname, value)
71*2f2c4c7aSAndroid Build Coastguard Worker
72*2f2c4c7aSAndroid Build Coastguard Worker  def SetUseOptimistic(self, ifname, value):
73*2f2c4c7aSAndroid Build Coastguard Worker    self.SetSysctl("/proc/sys/net/ipv6/conf/%s/use_optimistic" % ifname, value)
74*2f2c4c7aSAndroid Build Coastguard Worker
75*2f2c4c7aSAndroid Build Coastguard Worker  def SetForwarding(self, value):
76*2f2c4c7aSAndroid Build Coastguard Worker    self.SetSysctl("/proc/sys/net/ipv6/conf/all/forwarding", value)
77*2f2c4c7aSAndroid Build Coastguard Worker
78*2f2c4c7aSAndroid Build Coastguard Worker  def GetSourceIP(self, netid, mode="mark"):
79*2f2c4c7aSAndroid Build Coastguard Worker    s = self.BuildSocket(6, net_test.UDPSocket, netid, mode)
80*2f2c4c7aSAndroid Build Coastguard Worker    # Because why not...testing for temporary addresses is a separate thing.
81*2f2c4c7aSAndroid Build Coastguard Worker    s.setsockopt(IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, IPV6_PREFER_SRC_PUBLIC)
82*2f2c4c7aSAndroid Build Coastguard Worker
83*2f2c4c7aSAndroid Build Coastguard Worker    s.connect((net_test.IPV6_ADDR, 123))
84*2f2c4c7aSAndroid Build Coastguard Worker    src_addr = s.getsockname()[0]
85*2f2c4c7aSAndroid Build Coastguard Worker    self.assertTrue(src_addr)
86*2f2c4c7aSAndroid Build Coastguard Worker    s.close()
87*2f2c4c7aSAndroid Build Coastguard Worker    return src_addr
88*2f2c4c7aSAndroid Build Coastguard Worker
89*2f2c4c7aSAndroid Build Coastguard Worker  def assertAddressNotPresent(self, address):
90*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaises(IOError, self.iproute.GetAddress, address)
91*2f2c4c7aSAndroid Build Coastguard Worker
92*2f2c4c7aSAndroid Build Coastguard Worker  def assertAddressHasExpectedAttributes(
93*2f2c4c7aSAndroid Build Coastguard Worker      self, address, expected_ifindex, expected_flags):
94*2f2c4c7aSAndroid Build Coastguard Worker    ifa_msg = self.iproute.GetAddress(address)[0]
95*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(AF_INET6 if ":" in address else AF_INET, ifa_msg.family)
96*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(64, ifa_msg.prefixlen)
97*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(iproute.RT_SCOPE_UNIVERSE, ifa_msg.scope)
98*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected_ifindex, ifa_msg.index)
99*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected_flags, ifa_msg.flags & expected_flags)
100*2f2c4c7aSAndroid Build Coastguard Worker
101*2f2c4c7aSAndroid Build Coastguard Worker  def AddressIsTentative(self, address):
102*2f2c4c7aSAndroid Build Coastguard Worker    ifa_msg = self.iproute.GetAddress(address)[0]
103*2f2c4c7aSAndroid Build Coastguard Worker    return ifa_msg.flags & iproute.IFA_F_TENTATIVE
104*2f2c4c7aSAndroid Build Coastguard Worker
105*2f2c4c7aSAndroid Build Coastguard Worker  def BindToAddress(self, address):
106*2f2c4c7aSAndroid Build Coastguard Worker    s = net_test.UDPSocket(AF_INET6)
107*2f2c4c7aSAndroid Build Coastguard Worker    try:
108*2f2c4c7aSAndroid Build Coastguard Worker      s.bind((address, 0, 0, 0))
109*2f2c4c7aSAndroid Build Coastguard Worker    finally:
110*2f2c4c7aSAndroid Build Coastguard Worker      s.close()
111*2f2c4c7aSAndroid Build Coastguard Worker
112*2f2c4c7aSAndroid Build Coastguard Worker  def SendWithSourceAddress(self, address, netid, dest=net_test.IPV6_ADDR):
113*2f2c4c7aSAndroid Build Coastguard Worker    pktinfo = multinetwork_base.MakePktInfo(6, address, 0)
114*2f2c4c7aSAndroid Build Coastguard Worker    cmsgs = [(net_test.SOL_IPV6, IPV6_PKTINFO, pktinfo)]
115*2f2c4c7aSAndroid Build Coastguard Worker    s = self.BuildSocket(6, net_test.UDPSocket, netid, "mark")
116*2f2c4c7aSAndroid Build Coastguard Worker    try:
117*2f2c4c7aSAndroid Build Coastguard Worker      return csocket.Sendmsg(s, (dest, 53), b"Hello", cmsgs, 0)
118*2f2c4c7aSAndroid Build Coastguard Worker    finally:
119*2f2c4c7aSAndroid Build Coastguard Worker      s.close()
120*2f2c4c7aSAndroid Build Coastguard Worker
121*2f2c4c7aSAndroid Build Coastguard Worker  def assertAddressUsable(self, address, netid):
122*2f2c4c7aSAndroid Build Coastguard Worker    self.BindToAddress(address)
123*2f2c4c7aSAndroid Build Coastguard Worker    self.SendWithSourceAddress(address, netid)
124*2f2c4c7aSAndroid Build Coastguard Worker    # No exceptions? Good.
125*2f2c4c7aSAndroid Build Coastguard Worker
126*2f2c4c7aSAndroid Build Coastguard Worker  def assertAddressNotUsable(self, address, netid):
127*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(errno.EADDRNOTAVAIL, self.BindToAddress, address)
128*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(errno.EINVAL,
129*2f2c4c7aSAndroid Build Coastguard Worker                           self.SendWithSourceAddress, address, netid)
130*2f2c4c7aSAndroid Build Coastguard Worker
131*2f2c4c7aSAndroid Build Coastguard Worker  def assertAddressSelected(self, address, netid):
132*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(address, self.GetSourceIP(netid))
133*2f2c4c7aSAndroid Build Coastguard Worker
134*2f2c4c7aSAndroid Build Coastguard Worker  def assertAddressNotSelected(self, address, netid):
135*2f2c4c7aSAndroid Build Coastguard Worker    self.assertNotEqual(address, self.GetSourceIP(netid))
136*2f2c4c7aSAndroid Build Coastguard Worker
137*2f2c4c7aSAndroid Build Coastguard Worker  def WaitForDad(self, address):
138*2f2c4c7aSAndroid Build Coastguard Worker    for _ in range(20):
139*2f2c4c7aSAndroid Build Coastguard Worker      if not self.AddressIsTentative(address):
140*2f2c4c7aSAndroid Build Coastguard Worker        return
141*2f2c4c7aSAndroid Build Coastguard Worker      time.sleep(0.1)
142*2f2c4c7aSAndroid Build Coastguard Worker    raise AssertionError(f"{address} did not complete DAD after 2 seconds")
143*2f2c4c7aSAndroid Build Coastguard Worker
144*2f2c4c7aSAndroid Build Coastguard Worker  def WaitForDadFailure(self, address):
145*2f2c4c7aSAndroid Build Coastguard Worker    # Address should be either deleted or set IFA_F_DADFAILED flag after DAD failure
146*2f2c4c7aSAndroid Build Coastguard Worker    for _ in range(20):
147*2f2c4c7aSAndroid Build Coastguard Worker      try:
148*2f2c4c7aSAndroid Build Coastguard Worker        ifa_msg = self.iproute.GetAddress(address)[0]
149*2f2c4c7aSAndroid Build Coastguard Worker      except OSError:
150*2f2c4c7aSAndroid Build Coastguard Worker        return
151*2f2c4c7aSAndroid Build Coastguard Worker      if ifa_msg.flags & iproute.IFA_F_DADFAILED:
152*2f2c4c7aSAndroid Build Coastguard Worker        return
153*2f2c4c7aSAndroid Build Coastguard Worker      time.sleep(0.1)
154*2f2c4c7aSAndroid Build Coastguard Worker    raise AssertionError(f"{address} did not complete DAD failure after 2 seconds")
155*2f2c4c7aSAndroid Build Coastguard Worker
156*2f2c4c7aSAndroid Build Coastguard Worker
157*2f2c4c7aSAndroid Build Coastguard Workerclass MultiInterfaceSourceAddressSelectionTest(IPv6SourceAddressSelectionTest):
158*2f2c4c7aSAndroid Build Coastguard Worker
159*2f2c4c7aSAndroid Build Coastguard Worker  def setUp(self):
160*2f2c4c7aSAndroid Build Coastguard Worker    # [0]  Make sure DAD, optimistic DAD, and the use_optimistic option
161*2f2c4c7aSAndroid Build Coastguard Worker    # are all consistently disabled at the outset.
162*2f2c4c7aSAndroid Build Coastguard Worker    for netid in self.tuns:
163*2f2c4c7aSAndroid Build Coastguard Worker      ifname = self.GetInterfaceName(netid)
164*2f2c4c7aSAndroid Build Coastguard Worker      self.SetDAD(ifname, 0)
165*2f2c4c7aSAndroid Build Coastguard Worker      self.SetOptimisticDAD(ifname, 0)
166*2f2c4c7aSAndroid Build Coastguard Worker      self.SetUseTempaddrs(ifname, 0)
167*2f2c4c7aSAndroid Build Coastguard Worker      self.SetUseOptimistic(ifname, 0)
168*2f2c4c7aSAndroid Build Coastguard Worker      self.SetIPv6Sysctl(ifname, "use_oif_addrs_only", 0)
169*2f2c4c7aSAndroid Build Coastguard Worker
170*2f2c4c7aSAndroid Build Coastguard Worker    # [1]  Pick an interface on which to test.
171*2f2c4c7aSAndroid Build Coastguard Worker    self.test_netid = random.choice(list(self.tuns.keys()))
172*2f2c4c7aSAndroid Build Coastguard Worker    self.test_ip = self.MyAddress(6, self.test_netid)
173*2f2c4c7aSAndroid Build Coastguard Worker    self.test_ifindex = self.ifindices[self.test_netid]
174*2f2c4c7aSAndroid Build Coastguard Worker    self.test_ifname = self.GetInterfaceName(self.test_netid)
175*2f2c4c7aSAndroid Build Coastguard Worker    self.test_lladdr = net_test.GetLinkAddress(self.test_ifname, True)
176*2f2c4c7aSAndroid Build Coastguard Worker
177*2f2c4c7aSAndroid Build Coastguard Worker    # [2]  Delete the test interface's IPv6 address.
178*2f2c4c7aSAndroid Build Coastguard Worker    self.iproute.DelAddress(self.test_ip, 64, self.test_ifindex)
179*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressNotPresent(self.test_ip)
180*2f2c4c7aSAndroid Build Coastguard Worker
181*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressNotUsable(self.test_ip, self.test_netid)
182*2f2c4c7aSAndroid Build Coastguard Worker    # Verify that the link-local address is not tentative.
183*2f2c4c7aSAndroid Build Coastguard Worker    # Even though we disable DAD above, without this change occasionally the
184*2f2c4c7aSAndroid Build Coastguard Worker    # test fails. This might be due to us disabling DAD only after the
185*2f2c4c7aSAndroid Build Coastguard Worker    # link-local address is generated.
186*2f2c4c7aSAndroid Build Coastguard Worker    self.WaitForDad(self.test_lladdr)
187*2f2c4c7aSAndroid Build Coastguard Worker
188*2f2c4c7aSAndroid Build Coastguard Worker    # Disable forwarding, because optimistic addresses don't work when
189*2f2c4c7aSAndroid Build Coastguard Worker    # forwarding is on. Forwarding will be re-enabled when the sysctls are
190*2f2c4c7aSAndroid Build Coastguard Worker    # restored by MultiNetworkBaseTest.tearDownClass.
191*2f2c4c7aSAndroid Build Coastguard Worker    # TODO: Fix this and remove this hack.
192*2f2c4c7aSAndroid Build Coastguard Worker    self.SetForwarding("0")
193*2f2c4c7aSAndroid Build Coastguard Worker
194*2f2c4c7aSAndroid Build Coastguard Worker
195*2f2c4c7aSAndroid Build Coastguard Workerclass TentativeAddressTest(MultiInterfaceSourceAddressSelectionTest):
196*2f2c4c7aSAndroid Build Coastguard Worker
197*2f2c4c7aSAndroid Build Coastguard Worker  def testRfc6724Behaviour(self):
198*2f2c4c7aSAndroid Build Coastguard Worker    # [3]  Get an IPv6 address back, in DAD start-up.
199*2f2c4c7aSAndroid Build Coastguard Worker    self.SetDAD(self.test_ifname, 1)  # Enable DAD
200*2f2c4c7aSAndroid Build Coastguard Worker    # Send a RA to start SLAAC and subsequent DAD.
201*2f2c4c7aSAndroid Build Coastguard Worker    self.SendRA(self.test_netid, retranstimer=RETRANS_TIMER)
202*2f2c4c7aSAndroid Build Coastguard Worker    # Get flags and prove tentative-ness.
203*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressHasExpectedAttributes(
204*2f2c4c7aSAndroid Build Coastguard Worker        self.test_ip, self.test_ifindex, iproute.IFA_F_TENTATIVE)
205*2f2c4c7aSAndroid Build Coastguard Worker
206*2f2c4c7aSAndroid Build Coastguard Worker    # Even though the interface has an IPv6 address, its tentative nature
207*2f2c4c7aSAndroid Build Coastguard Worker    # prevents it from being selected.
208*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressNotUsable(self.test_ip, self.test_netid)
209*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressNotSelected(self.test_ip, self.test_netid)
210*2f2c4c7aSAndroid Build Coastguard Worker
211*2f2c4c7aSAndroid Build Coastguard Worker    # Busy wait for DAD to complete (should be less than 1 second).
212*2f2c4c7aSAndroid Build Coastguard Worker    self.WaitForDad(self.test_ip)
213*2f2c4c7aSAndroid Build Coastguard Worker
214*2f2c4c7aSAndroid Build Coastguard Worker    # The test_ip should have completed DAD by now, and should be the
215*2f2c4c7aSAndroid Build Coastguard Worker    # chosen source address, eligible to bind to, etc.
216*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressUsable(self.test_ip, self.test_netid)
217*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressSelected(self.test_ip, self.test_netid)
218*2f2c4c7aSAndroid Build Coastguard Worker
219*2f2c4c7aSAndroid Build Coastguard Worker
220*2f2c4c7aSAndroid Build Coastguard Workerclass OptimisticAddressTest(MultiInterfaceSourceAddressSelectionTest):
221*2f2c4c7aSAndroid Build Coastguard Worker
222*2f2c4c7aSAndroid Build Coastguard Worker  def testRfc6724Behaviour(self):
223*2f2c4c7aSAndroid Build Coastguard Worker    # [3]  Get an IPv6 address back, in optimistic DAD start-up.
224*2f2c4c7aSAndroid Build Coastguard Worker    self.SetDAD(self.test_ifname, 1)  # Enable DAD
225*2f2c4c7aSAndroid Build Coastguard Worker    self.SetOptimisticDAD(self.test_ifname, 1)
226*2f2c4c7aSAndroid Build Coastguard Worker    # Send a RA to start SLAAC and subsequent DAD.
227*2f2c4c7aSAndroid Build Coastguard Worker    self.SendRA(self.test_netid, retranstimer=RETRANS_TIMER)
228*2f2c4c7aSAndroid Build Coastguard Worker    # Get flags and prove optimism.
229*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressHasExpectedAttributes(
230*2f2c4c7aSAndroid Build Coastguard Worker        self.test_ip, self.test_ifindex, iproute.IFA_F_OPTIMISTIC)
231*2f2c4c7aSAndroid Build Coastguard Worker
232*2f2c4c7aSAndroid Build Coastguard Worker    # Optimistic addresses are usable but are not selected.
233*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressUsable(self.test_ip, self.test_netid)
234*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressNotSelected(self.test_ip, self.test_netid)
235*2f2c4c7aSAndroid Build Coastguard Worker
236*2f2c4c7aSAndroid Build Coastguard Worker    # Busy wait for DAD to complete (should be less than 1 second).
237*2f2c4c7aSAndroid Build Coastguard Worker    self.WaitForDad(self.test_ip)
238*2f2c4c7aSAndroid Build Coastguard Worker
239*2f2c4c7aSAndroid Build Coastguard Worker    # The test_ip should have completed DAD by now, and should be the
240*2f2c4c7aSAndroid Build Coastguard Worker    # chosen source address.
241*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressUsable(self.test_ip, self.test_netid)
242*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressSelected(self.test_ip, self.test_netid)
243*2f2c4c7aSAndroid Build Coastguard Worker
244*2f2c4c7aSAndroid Build Coastguard Worker
245*2f2c4c7aSAndroid Build Coastguard Workerclass OptimisticAddressOkayTest(MultiInterfaceSourceAddressSelectionTest):
246*2f2c4c7aSAndroid Build Coastguard Worker
247*2f2c4c7aSAndroid Build Coastguard Worker  def testModifiedRfc6724Behaviour(self):
248*2f2c4c7aSAndroid Build Coastguard Worker    # [3]  Get an IPv6 address back, in optimistic DAD start-up.
249*2f2c4c7aSAndroid Build Coastguard Worker    self.SetDAD(self.test_ifname, 1)  # Enable DAD
250*2f2c4c7aSAndroid Build Coastguard Worker    self.SetOptimisticDAD(self.test_ifname, 1)
251*2f2c4c7aSAndroid Build Coastguard Worker    self.SetUseOptimistic(self.test_ifname, 1)
252*2f2c4c7aSAndroid Build Coastguard Worker    # Send a RA to start SLAAC and subsequent DAD.
253*2f2c4c7aSAndroid Build Coastguard Worker    self.SendRA(self.test_netid, retranstimer=RETRANS_TIMER)
254*2f2c4c7aSAndroid Build Coastguard Worker    # Get flags and prove optimistism.
255*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressHasExpectedAttributes(
256*2f2c4c7aSAndroid Build Coastguard Worker        self.test_ip, self.test_ifindex, iproute.IFA_F_OPTIMISTIC)
257*2f2c4c7aSAndroid Build Coastguard Worker
258*2f2c4c7aSAndroid Build Coastguard Worker    # The interface has an IPv6 address and, despite its optimistic nature,
259*2f2c4c7aSAndroid Build Coastguard Worker    # the use_optimistic option allows it to be selected.
260*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressUsable(self.test_ip, self.test_netid)
261*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressSelected(self.test_ip, self.test_netid)
262*2f2c4c7aSAndroid Build Coastguard Worker
263*2f2c4c7aSAndroid Build Coastguard Worker
264*2f2c4c7aSAndroid Build Coastguard Workerclass ValidBeforeOptimisticTest(MultiInterfaceSourceAddressSelectionTest):
265*2f2c4c7aSAndroid Build Coastguard Worker
266*2f2c4c7aSAndroid Build Coastguard Worker  def testModifiedRfc6724Behaviour(self):
267*2f2c4c7aSAndroid Build Coastguard Worker    # [3]  Add a valid IPv6 address to this interface and verify it is
268*2f2c4c7aSAndroid Build Coastguard Worker    # selected as the source address.
269*2f2c4c7aSAndroid Build Coastguard Worker    preferred_ip = self.OnlinkPrefix(6, self.test_netid) + "cafe"
270*2f2c4c7aSAndroid Build Coastguard Worker    self.iproute.AddAddress(preferred_ip, 64, self.test_ifindex)
271*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressHasExpectedAttributes(
272*2f2c4c7aSAndroid Build Coastguard Worker        preferred_ip, self.test_ifindex, iproute.IFA_F_PERMANENT)
273*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(preferred_ip, self.GetSourceIP(self.test_netid))
274*2f2c4c7aSAndroid Build Coastguard Worker
275*2f2c4c7aSAndroid Build Coastguard Worker    # [4]  Get another IPv6 address, in optimistic DAD start-up.
276*2f2c4c7aSAndroid Build Coastguard Worker    self.SetDAD(self.test_ifname, 1)  # Enable DAD
277*2f2c4c7aSAndroid Build Coastguard Worker    self.SetOptimisticDAD(self.test_ifname, 1)
278*2f2c4c7aSAndroid Build Coastguard Worker    self.SetUseOptimistic(self.test_ifname, 1)
279*2f2c4c7aSAndroid Build Coastguard Worker    # Send a RA to start SLAAC and subsequent DAD.
280*2f2c4c7aSAndroid Build Coastguard Worker    self.SendRA(self.test_netid, retranstimer=RETRANS_TIMER)
281*2f2c4c7aSAndroid Build Coastguard Worker    # Get flags and prove optimism.
282*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressHasExpectedAttributes(
283*2f2c4c7aSAndroid Build Coastguard Worker        self.test_ip, self.test_ifindex, iproute.IFA_F_OPTIMISTIC)
284*2f2c4c7aSAndroid Build Coastguard Worker
285*2f2c4c7aSAndroid Build Coastguard Worker    # Since the interface has another IPv6 address, the optimistic address
286*2f2c4c7aSAndroid Build Coastguard Worker    # is not selected--the other, valid address is chosen.
287*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressUsable(self.test_ip, self.test_netid)
288*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressNotSelected(self.test_ip, self.test_netid)
289*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressSelected(preferred_ip, self.test_netid)
290*2f2c4c7aSAndroid Build Coastguard Worker
291*2f2c4c7aSAndroid Build Coastguard Worker
292*2f2c4c7aSAndroid Build Coastguard Workerclass DadFailureTest(MultiInterfaceSourceAddressSelectionTest):
293*2f2c4c7aSAndroid Build Coastguard Worker
294*2f2c4c7aSAndroid Build Coastguard Worker  def testDadFailure(self):
295*2f2c4c7aSAndroid Build Coastguard Worker    # [3]  Get an IPv6 address back, in optimistic DAD start-up.
296*2f2c4c7aSAndroid Build Coastguard Worker    self.SetDAD(self.test_ifname, 1)  # Enable DAD
297*2f2c4c7aSAndroid Build Coastguard Worker    self.SetOptimisticDAD(self.test_ifname, 1)
298*2f2c4c7aSAndroid Build Coastguard Worker    self.SetUseOptimistic(self.test_ifname, 1)
299*2f2c4c7aSAndroid Build Coastguard Worker    # Send a RA to start SLAAC and subsequent DAD.
300*2f2c4c7aSAndroid Build Coastguard Worker    self.SendRA(self.test_netid, retranstimer=RETRANS_TIMER)
301*2f2c4c7aSAndroid Build Coastguard Worker    time.sleep(0.1) # Give the kernel time to notice our RA
302*2f2c4c7aSAndroid Build Coastguard Worker    # Prove optimism and usability.
303*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressHasExpectedAttributes(
304*2f2c4c7aSAndroid Build Coastguard Worker        self.test_ip, self.test_ifindex, iproute.IFA_F_OPTIMISTIC)
305*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressUsable(self.test_ip, self.test_netid)
306*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressSelected(self.test_ip, self.test_netid)
307*2f2c4c7aSAndroid Build Coastguard Worker
308*2f2c4c7aSAndroid Build Coastguard Worker    # Send a NA for the optimistic address, indicating address conflict
309*2f2c4c7aSAndroid Build Coastguard Worker    # ("DAD defense").
310*2f2c4c7aSAndroid Build Coastguard Worker    conflict_macaddr = "02:00:0b:ad:d0:0d"
311*2f2c4c7aSAndroid Build Coastguard Worker    dad_defense = (scapy.Ether(src=conflict_macaddr, dst="33:33:33:00:00:01") /
312*2f2c4c7aSAndroid Build Coastguard Worker                   scapy.IPv6(src=self.test_ip, dst="ff02::1") /
313*2f2c4c7aSAndroid Build Coastguard Worker                   scapy.ICMPv6ND_NA(tgt=self.test_ip, R=0, S=0, O=1) /
314*2f2c4c7aSAndroid Build Coastguard Worker                   scapy.ICMPv6NDOptDstLLAddr(lladdr=conflict_macaddr))
315*2f2c4c7aSAndroid Build Coastguard Worker    self.ReceiveEtherPacketOn(self.test_netid, dad_defense)
316*2f2c4c7aSAndroid Build Coastguard Worker    self.WaitForDadFailure(self.test_ip)
317*2f2c4c7aSAndroid Build Coastguard Worker
318*2f2c4c7aSAndroid Build Coastguard Worker    # The address should have failed DAD, and therefore no longer be usable.
319*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressNotUsable(self.test_ip, self.test_netid)
320*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressNotSelected(self.test_ip, self.test_netid)
321*2f2c4c7aSAndroid Build Coastguard Worker
322*2f2c4c7aSAndroid Build Coastguard Worker    # TODO(ek): verify that an RTM_DELADDR issued for the DAD-failed address.
323*2f2c4c7aSAndroid Build Coastguard Worker
324*2f2c4c7aSAndroid Build Coastguard Worker
325*2f2c4c7aSAndroid Build Coastguard Workerclass NoNsFromOptimisticTest(MultiInterfaceSourceAddressSelectionTest):
326*2f2c4c7aSAndroid Build Coastguard Worker
327*2f2c4c7aSAndroid Build Coastguard Worker  def testSendToOnlinkDestination(self):
328*2f2c4c7aSAndroid Build Coastguard Worker    # [3]  Get an IPv6 address back, in optimistic DAD start-up.
329*2f2c4c7aSAndroid Build Coastguard Worker    self.SetDAD(self.test_ifname, 1)  # Enable DAD
330*2f2c4c7aSAndroid Build Coastguard Worker    self.SetOptimisticDAD(self.test_ifname, 1)
331*2f2c4c7aSAndroid Build Coastguard Worker    self.SetUseOptimistic(self.test_ifname, 1)
332*2f2c4c7aSAndroid Build Coastguard Worker    # Send a RA to start SLAAC and subsequent DAD.
333*2f2c4c7aSAndroid Build Coastguard Worker    self.SendRA(self.test_netid, retranstimer=RETRANS_TIMER)
334*2f2c4c7aSAndroid Build Coastguard Worker    # Prove optimism and usability.
335*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressHasExpectedAttributes(
336*2f2c4c7aSAndroid Build Coastguard Worker        self.test_ip, self.test_ifindex, iproute.IFA_F_OPTIMISTIC)
337*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressUsable(self.test_ip, self.test_netid)
338*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressSelected(self.test_ip, self.test_netid)
339*2f2c4c7aSAndroid Build Coastguard Worker
340*2f2c4c7aSAndroid Build Coastguard Worker    # [4]  Send to an on-link destination and observe a Neighbor Solicitation
341*2f2c4c7aSAndroid Build Coastguard Worker    # packet with a source address that is NOT the optimistic address.
342*2f2c4c7aSAndroid Build Coastguard Worker    # In this setup, the only usable address is the link-local address.
343*2f2c4c7aSAndroid Build Coastguard Worker    onlink_dest = self.GetRandomDestination(
344*2f2c4c7aSAndroid Build Coastguard Worker        self.OnlinkPrefix(6, self.test_netid))
345*2f2c4c7aSAndroid Build Coastguard Worker    self.SendWithSourceAddress(self.test_ip, self.test_netid, onlink_dest)
346*2f2c4c7aSAndroid Build Coastguard Worker
347*2f2c4c7aSAndroid Build Coastguard Worker    expected_ns = packets.NS(
348*2f2c4c7aSAndroid Build Coastguard Worker        self.test_lladdr,
349*2f2c4c7aSAndroid Build Coastguard Worker        onlink_dest,
350*2f2c4c7aSAndroid Build Coastguard Worker        self.MyMacAddress(self.test_netid))[1]
351*2f2c4c7aSAndroid Build Coastguard Worker    self.ExpectPacketOn(self.test_netid, "link-local NS", expected_ns)
352*2f2c4c7aSAndroid Build Coastguard Worker
353*2f2c4c7aSAndroid Build Coastguard Worker
354*2f2c4c7aSAndroid Build Coastguard Worker# TODO(ek): add tests listening for netlink events.
355*2f2c4c7aSAndroid Build Coastguard Worker
356*2f2c4c7aSAndroid Build Coastguard Worker
357*2f2c4c7aSAndroid Build Coastguard Workerclass DefaultCandidateSrcAddrsTest(MultiInterfaceSourceAddressSelectionTest):
358*2f2c4c7aSAndroid Build Coastguard Worker
359*2f2c4c7aSAndroid Build Coastguard Worker  def testChoosesNonInterfaceSourceAddress(self):
360*2f2c4c7aSAndroid Build Coastguard Worker    self.SetIPv6Sysctl(self.test_ifname, "use_oif_addrs_only", 0)
361*2f2c4c7aSAndroid Build Coastguard Worker    src_ip = self.GetSourceIP(self.test_netid)
362*2f2c4c7aSAndroid Build Coastguard Worker    self.assertFalse(src_ip in [self.test_ip, self.test_lladdr])
363*2f2c4c7aSAndroid Build Coastguard Worker    self.assertTrue(src_ip in
364*2f2c4c7aSAndroid Build Coastguard Worker                    [self.MyAddress(6, netid)
365*2f2c4c7aSAndroid Build Coastguard Worker                     for netid in self.tuns if netid != self.test_netid])
366*2f2c4c7aSAndroid Build Coastguard Worker
367*2f2c4c7aSAndroid Build Coastguard Worker
368*2f2c4c7aSAndroid Build Coastguard Workerclass RestrictedCandidateSrcAddrsTest(MultiInterfaceSourceAddressSelectionTest):
369*2f2c4c7aSAndroid Build Coastguard Worker
370*2f2c4c7aSAndroid Build Coastguard Worker  def testChoosesOnlyInterfaceSourceAddress(self):
371*2f2c4c7aSAndroid Build Coastguard Worker    self.SetIPv6Sysctl(self.test_ifname, "use_oif_addrs_only", 1)
372*2f2c4c7aSAndroid Build Coastguard Worker    # self.test_ifname does not have a global IPv6 address, so the only
373*2f2c4c7aSAndroid Build Coastguard Worker    # candidate is the existing link-local address.
374*2f2c4c7aSAndroid Build Coastguard Worker    self.assertAddressSelected(self.test_lladdr, self.test_netid)
375*2f2c4c7aSAndroid Build Coastguard Worker
376*2f2c4c7aSAndroid Build Coastguard Worker
377*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__":
378*2f2c4c7aSAndroid Build Coastguard Worker  unittest.main()
379