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