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 cstruct 18*2f2c4c7aSAndroid Build Coastguard Workerimport ctypes 19*2f2c4c7aSAndroid Build Coastguard Workerimport errno 20*2f2c4c7aSAndroid Build Coastguard Workerimport os 21*2f2c4c7aSAndroid Build Coastguard Workerimport random 22*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import * # pylint: disable=wildcard-import 23*2f2c4c7aSAndroid Build Coastguard Workerimport struct 24*2f2c4c7aSAndroid Build Coastguard Workerimport time # pylint: disable=unused-import 25*2f2c4c7aSAndroid Build Coastguard Workerimport unittest 26*2f2c4c7aSAndroid Build Coastguard Worker 27*2f2c4c7aSAndroid Build Coastguard Workerfrom scapy import all as scapy 28*2f2c4c7aSAndroid Build Coastguard Worker 29*2f2c4c7aSAndroid Build Coastguard Workerimport csocket 30*2f2c4c7aSAndroid Build Coastguard Workerimport iproute 31*2f2c4c7aSAndroid Build Coastguard Workerimport multinetwork_base 32*2f2c4c7aSAndroid Build Coastguard Workerimport net_test 33*2f2c4c7aSAndroid Build Coastguard Workerimport netlink 34*2f2c4c7aSAndroid Build Coastguard Workerimport packets 35*2f2c4c7aSAndroid Build Coastguard Worker 36*2f2c4c7aSAndroid Build Coastguard Worker# For brevity. 37*2f2c4c7aSAndroid Build Coastguard WorkerUDP_PAYLOAD = net_test.UDP_PAYLOAD 38*2f2c4c7aSAndroid Build Coastguard Worker 39*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_FLOWINFO = 11 40*2f2c4c7aSAndroid Build Coastguard Worker 41*2f2c4c7aSAndroid Build Coastguard WorkerSYNCOOKIES_SYSCTL = "/proc/sys/net/ipv4/tcp_syncookies" 42*2f2c4c7aSAndroid Build Coastguard WorkerTCP_MARK_ACCEPT_SYSCTL = "/proc/sys/net/ipv4/tcp_fwmark_accept" 43*2f2c4c7aSAndroid Build Coastguard Worker 44*2f2c4c7aSAndroid Build Coastguard Worker 45*2f2c4c7aSAndroid Build Coastguard Workerclass OutgoingTest(multinetwork_base.MultiNetworkBaseTest): 46*2f2c4c7aSAndroid Build Coastguard Worker 47*2f2c4c7aSAndroid Build Coastguard Worker # How many times to run outgoing packet tests. 48*2f2c4c7aSAndroid Build Coastguard Worker ITERATIONS = 5 49*2f2c4c7aSAndroid Build Coastguard Worker 50*2f2c4c7aSAndroid Build Coastguard Worker def CheckPingPacket(self, version, netid, routing_mode, packet): 51*2f2c4c7aSAndroid Build Coastguard Worker s = self.BuildSocket(version, net_test.PingSocket, netid, routing_mode) 52*2f2c4c7aSAndroid Build Coastguard Worker 53*2f2c4c7aSAndroid Build Coastguard Worker myaddr = self.MyAddress(version, netid) 54*2f2c4c7aSAndroid Build Coastguard Worker mysockaddr = self.MySocketAddress(version, netid) 55*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) 56*2f2c4c7aSAndroid Build Coastguard Worker s.bind((mysockaddr, packets.PING_IDENT)) 57*2f2c4c7aSAndroid Build Coastguard Worker net_test.SetSocketTos(s, packets.PING_TOS) 58*2f2c4c7aSAndroid Build Coastguard Worker 59*2f2c4c7aSAndroid Build Coastguard Worker dstaddr = self.GetRemoteAddress(version) 60*2f2c4c7aSAndroid Build Coastguard Worker dstsockaddr = self.GetRemoteSocketAddress(version) 61*2f2c4c7aSAndroid Build Coastguard Worker desc, expected = packets.ICMPEcho(version, myaddr, dstaddr) 62*2f2c4c7aSAndroid Build Coastguard Worker msg = "IPv%d ping: expected %s on %s" % ( 63*2f2c4c7aSAndroid Build Coastguard Worker version, desc, self.GetInterfaceName(netid)) 64*2f2c4c7aSAndroid Build Coastguard Worker 65*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(packet + packets.PING_PAYLOAD, (dstsockaddr, 19321)) 66*2f2c4c7aSAndroid Build Coastguard Worker 67*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg, expected) 68*2f2c4c7aSAndroid Build Coastguard Worker s.close() 69*2f2c4c7aSAndroid Build Coastguard Worker 70*2f2c4c7aSAndroid Build Coastguard Worker def CheckTCPSYNPacket(self, version, netid, routing_mode): 71*2f2c4c7aSAndroid Build Coastguard Worker s = self.BuildSocket(version, net_test.TCPSocket, netid, routing_mode) 72*2f2c4c7aSAndroid Build Coastguard Worker 73*2f2c4c7aSAndroid Build Coastguard Worker myaddr = self.MyAddress(version, netid) 74*2f2c4c7aSAndroid Build Coastguard Worker dstaddr = self.GetRemoteAddress(version) 75*2f2c4c7aSAndroid Build Coastguard Worker dstsockaddr = self.GetRemoteSocketAddress(version) 76*2f2c4c7aSAndroid Build Coastguard Worker desc, expected = packets.SYN(53, version, myaddr, dstaddr, 77*2f2c4c7aSAndroid Build Coastguard Worker sport=None, seq=None) 78*2f2c4c7aSAndroid Build Coastguard Worker 79*2f2c4c7aSAndroid Build Coastguard Worker 80*2f2c4c7aSAndroid Build Coastguard Worker # Non-blocking TCP connects always return EINPROGRESS. 81*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EINPROGRESS, s.connect, (dstsockaddr, 53)) 82*2f2c4c7aSAndroid Build Coastguard Worker msg = "IPv%s TCP connect: expected %s on %s" % ( 83*2f2c4c7aSAndroid Build Coastguard Worker version, desc, self.GetInterfaceName(netid)) 84*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg, expected) 85*2f2c4c7aSAndroid Build Coastguard Worker s.close() 86*2f2c4c7aSAndroid Build Coastguard Worker 87*2f2c4c7aSAndroid Build Coastguard Worker def CheckUDPPacket(self, version, netid, routing_mode): 88*2f2c4c7aSAndroid Build Coastguard Worker s = self.BuildSocket(version, net_test.UDPSocket, netid, routing_mode) 89*2f2c4c7aSAndroid Build Coastguard Worker 90*2f2c4c7aSAndroid Build Coastguard Worker myaddr = self.MyAddress(version, netid) 91*2f2c4c7aSAndroid Build Coastguard Worker dstaddr = self.GetRemoteAddress(version) 92*2f2c4c7aSAndroid Build Coastguard Worker dstsockaddr = self.GetRemoteSocketAddress(version) 93*2f2c4c7aSAndroid Build Coastguard Worker 94*2f2c4c7aSAndroid Build Coastguard Worker desc, expected = packets.UDP(version, myaddr, dstaddr, sport=None) 95*2f2c4c7aSAndroid Build Coastguard Worker msg = "IPv%s UDP %%s: expected %s on %s" % ( 96*2f2c4c7aSAndroid Build Coastguard Worker version, desc, self.GetInterfaceName(netid)) 97*2f2c4c7aSAndroid Build Coastguard Worker 98*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(UDP_PAYLOAD, (dstsockaddr, 53)) 99*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg % "sendto", expected) 100*2f2c4c7aSAndroid Build Coastguard Worker 101*2f2c4c7aSAndroid Build Coastguard Worker # IP_UNICAST_IF doesn't seem to work on connected sockets, so no TCP. 102*2f2c4c7aSAndroid Build Coastguard Worker if routing_mode != "ucast_oif": 103*2f2c4c7aSAndroid Build Coastguard Worker s.connect((dstsockaddr, 53)) 104*2f2c4c7aSAndroid Build Coastguard Worker s.send(UDP_PAYLOAD) 105*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg % "connect/send", expected) 106*2f2c4c7aSAndroid Build Coastguard Worker 107*2f2c4c7aSAndroid Build Coastguard Worker s.close() 108*2f2c4c7aSAndroid Build Coastguard Worker 109*2f2c4c7aSAndroid Build Coastguard Worker def CheckRawGrePacket(self, version, netid, routing_mode): 110*2f2c4c7aSAndroid Build Coastguard Worker s = self.BuildSocket(version, net_test.RawGRESocket, netid, routing_mode) 111*2f2c4c7aSAndroid Build Coastguard Worker 112*2f2c4c7aSAndroid Build Coastguard Worker inner_version = {4: 6, 6: 4}[version] 113*2f2c4c7aSAndroid Build Coastguard Worker inner_src = self.MyAddress(inner_version, netid) 114*2f2c4c7aSAndroid Build Coastguard Worker inner_dst = self.GetRemoteAddress(inner_version) 115*2f2c4c7aSAndroid Build Coastguard Worker inner = bytes(packets.UDP(inner_version, inner_src, inner_dst, sport=None)[1]) 116*2f2c4c7aSAndroid Build Coastguard Worker 117*2f2c4c7aSAndroid Build Coastguard Worker ethertype = {4: net_test.ETH_P_IP, 6: net_test.ETH_P_IPV6}[inner_version] 118*2f2c4c7aSAndroid Build Coastguard Worker # A GRE header can be as simple as two zero bytes and the ethertype. 119*2f2c4c7aSAndroid Build Coastguard Worker packet = struct.pack("!i", ethertype) + inner 120*2f2c4c7aSAndroid Build Coastguard Worker myaddr = self.MyAddress(version, netid) 121*2f2c4c7aSAndroid Build Coastguard Worker dstaddr = self.GetRemoteAddress(version) 122*2f2c4c7aSAndroid Build Coastguard Worker 123*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(packet, (dstaddr, IPPROTO_GRE)) 124*2f2c4c7aSAndroid Build Coastguard Worker desc, expected = packets.GRE(version, myaddr, dstaddr, ethertype, inner) 125*2f2c4c7aSAndroid Build Coastguard Worker msg = "Raw IPv%d GRE with inner IPv%d UDP: expected %s on %s" % ( 126*2f2c4c7aSAndroid Build Coastguard Worker version, inner_version, desc, self.GetInterfaceName(netid)) 127*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg, expected) 128*2f2c4c7aSAndroid Build Coastguard Worker s.close() 129*2f2c4c7aSAndroid Build Coastguard Worker 130*2f2c4c7aSAndroid Build Coastguard Worker def CheckOutgoingPackets(self, routing_mode): 131*2f2c4c7aSAndroid Build Coastguard Worker for _ in range(self.ITERATIONS): 132*2f2c4c7aSAndroid Build Coastguard Worker for netid in self.tuns: 133*2f2c4c7aSAndroid Build Coastguard Worker 134*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPingPacket(4, netid, routing_mode, self.IPV4_PING) 135*2f2c4c7aSAndroid Build Coastguard Worker # Kernel bug. 136*2f2c4c7aSAndroid Build Coastguard Worker if routing_mode != "oif": 137*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPingPacket(6, netid, routing_mode, self.IPV6_PING) 138*2f2c4c7aSAndroid Build Coastguard Worker 139*2f2c4c7aSAndroid Build Coastguard Worker # IP_UNICAST_IF doesn't seem to work on connected sockets, so no TCP. 140*2f2c4c7aSAndroid Build Coastguard Worker if routing_mode != "ucast_oif": 141*2f2c4c7aSAndroid Build Coastguard Worker self.CheckTCPSYNPacket(4, netid, routing_mode) 142*2f2c4c7aSAndroid Build Coastguard Worker self.CheckTCPSYNPacket(6, netid, routing_mode) 143*2f2c4c7aSAndroid Build Coastguard Worker self.CheckTCPSYNPacket(5, netid, routing_mode) 144*2f2c4c7aSAndroid Build Coastguard Worker 145*2f2c4c7aSAndroid Build Coastguard Worker self.CheckUDPPacket(4, netid, routing_mode) 146*2f2c4c7aSAndroid Build Coastguard Worker self.CheckUDPPacket(6, netid, routing_mode) 147*2f2c4c7aSAndroid Build Coastguard Worker self.CheckUDPPacket(5, netid, routing_mode) 148*2f2c4c7aSAndroid Build Coastguard Worker 149*2f2c4c7aSAndroid Build Coastguard Worker # Creating raw sockets on non-root UIDs requires properly setting 150*2f2c4c7aSAndroid Build Coastguard Worker # capabilities, which is hard to do from Python. 151*2f2c4c7aSAndroid Build Coastguard Worker # IP_UNICAST_IF is not supported on raw sockets. 152*2f2c4c7aSAndroid Build Coastguard Worker if routing_mode not in ["uid", "ucast_oif"]: 153*2f2c4c7aSAndroid Build Coastguard Worker self.CheckRawGrePacket(4, netid, routing_mode) 154*2f2c4c7aSAndroid Build Coastguard Worker self.CheckRawGrePacket(6, netid, routing_mode) 155*2f2c4c7aSAndroid Build Coastguard Worker 156*2f2c4c7aSAndroid Build Coastguard Worker def testMarkRouting(self): 157*2f2c4c7aSAndroid Build Coastguard Worker """Checks that socket marking selects the right outgoing interface.""" 158*2f2c4c7aSAndroid Build Coastguard Worker self.CheckOutgoingPackets("mark") 159*2f2c4c7aSAndroid Build Coastguard Worker 160*2f2c4c7aSAndroid Build Coastguard Worker def testUidRouting(self): 161*2f2c4c7aSAndroid Build Coastguard Worker """Checks that UID routing selects the right outgoing interface.""" 162*2f2c4c7aSAndroid Build Coastguard Worker self.CheckOutgoingPackets("uid") 163*2f2c4c7aSAndroid Build Coastguard Worker 164*2f2c4c7aSAndroid Build Coastguard Worker def testOifRouting(self): 165*2f2c4c7aSAndroid Build Coastguard Worker """Checks that oif routing selects the right outgoing interface.""" 166*2f2c4c7aSAndroid Build Coastguard Worker self.CheckOutgoingPackets("oif") 167*2f2c4c7aSAndroid Build Coastguard Worker 168*2f2c4c7aSAndroid Build Coastguard Worker def testUcastOifRouting(self): 169*2f2c4c7aSAndroid Build Coastguard Worker """Checks that ucast oif routing selects the right outgoing interface.""" 170*2f2c4c7aSAndroid Build Coastguard Worker self.CheckOutgoingPackets("ucast_oif") 171*2f2c4c7aSAndroid Build Coastguard Worker 172*2f2c4c7aSAndroid Build Coastguard Worker def CheckRemarking(self, version, use_connect): 173*2f2c4c7aSAndroid Build Coastguard Worker modes = ["mark", "oif", "uid"] 174*2f2c4c7aSAndroid Build Coastguard Worker # Setting UNICAST_IF on connected sockets does not work. 175*2f2c4c7aSAndroid Build Coastguard Worker if not use_connect: 176*2f2c4c7aSAndroid Build Coastguard Worker modes += ["ucast_oif"] 177*2f2c4c7aSAndroid Build Coastguard Worker 178*2f2c4c7aSAndroid Build Coastguard Worker for mode in modes: 179*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.UDPSocket(self.GetProtocolFamily(version)) 180*2f2c4c7aSAndroid Build Coastguard Worker 181*2f2c4c7aSAndroid Build Coastguard Worker # Figure out what packets to expect. 182*2f2c4c7aSAndroid Build Coastguard Worker sport = net_test.BindRandomPort(version, s) 183*2f2c4c7aSAndroid Build Coastguard Worker dstaddr = {4: self.IPV4_ADDR, 6: self.IPV6_ADDR}[version] 184*2f2c4c7aSAndroid Build Coastguard Worker unspec = {4: "0.0.0.0", 6: "::"}[version] # Placeholder. 185*2f2c4c7aSAndroid Build Coastguard Worker desc, expected = packets.UDP(version, unspec, dstaddr, sport) 186*2f2c4c7aSAndroid Build Coastguard Worker 187*2f2c4c7aSAndroid Build Coastguard Worker # If we're testing connected sockets, connect the socket on the first 188*2f2c4c7aSAndroid Build Coastguard Worker # netid now. 189*2f2c4c7aSAndroid Build Coastguard Worker if use_connect: 190*2f2c4c7aSAndroid Build Coastguard Worker netid = list(self.tuns.keys())[0] 191*2f2c4c7aSAndroid Build Coastguard Worker self.SelectInterface(s, netid, mode) 192*2f2c4c7aSAndroid Build Coastguard Worker s.connect((dstaddr, 53)) 193*2f2c4c7aSAndroid Build Coastguard Worker expected.src = self.MyAddress(version, netid) 194*2f2c4c7aSAndroid Build Coastguard Worker 195*2f2c4c7aSAndroid Build Coastguard Worker # For each netid, select that network without closing the socket, and 196*2f2c4c7aSAndroid Build Coastguard Worker # check that the packets sent on that socket go out on the right network. 197*2f2c4c7aSAndroid Build Coastguard Worker # 198*2f2c4c7aSAndroid Build Coastguard Worker # For connected sockets, routing is cached in the socket's destination 199*2f2c4c7aSAndroid Build Coastguard Worker # cache entry. In this case, we check that selecting the network a second 200*2f2c4c7aSAndroid Build Coastguard Worker # time on the same socket (except via SO_BINDTODEVICE, or SO_MARK on 5.0+ 201*2f2c4c7aSAndroid Build Coastguard Worker # kernels) does not change routing, but that subsequently invalidating the 202*2f2c4c7aSAndroid Build Coastguard Worker # destination cache entry does. This is a bug in the kernel because 203*2f2c4c7aSAndroid Build Coastguard Worker # re-selecting the netid should cause routing to change, and future 204*2f2c4c7aSAndroid Build Coastguard Worker # kernels may fix this bug for per-UID routing and ucast_oif routing like 205*2f2c4c7aSAndroid Build Coastguard Worker # they already have for mark-based routing. But until they do, this 206*2f2c4c7aSAndroid Build Coastguard Worker # behaviour provides a convenient way to check that InvalidateDstCache 207*2f2c4c7aSAndroid Build Coastguard Worker # actually works. 208*2f2c4c7aSAndroid Build Coastguard Worker prevnetid = None 209*2f2c4c7aSAndroid Build Coastguard Worker for netid in self.tuns: 210*2f2c4c7aSAndroid Build Coastguard Worker self.SelectInterface(s, netid, mode) 211*2f2c4c7aSAndroid Build Coastguard Worker if not use_connect: 212*2f2c4c7aSAndroid Build Coastguard Worker expected.src = self.MyAddress(version, netid) 213*2f2c4c7aSAndroid Build Coastguard Worker 214*2f2c4c7aSAndroid Build Coastguard Worker def ExpectSendUsesNetid(netid): 215*2f2c4c7aSAndroid Build Coastguard Worker connected_str = "Connected" if use_connect else "Unconnected" 216*2f2c4c7aSAndroid Build Coastguard Worker msg = "%s UDPv%d socket remarked using %s: expecting %s on %s" % ( 217*2f2c4c7aSAndroid Build Coastguard Worker connected_str, version, mode, desc, self.GetInterfaceName(netid)) 218*2f2c4c7aSAndroid Build Coastguard Worker if use_connect: 219*2f2c4c7aSAndroid Build Coastguard Worker s.send(UDP_PAYLOAD) 220*2f2c4c7aSAndroid Build Coastguard Worker else: 221*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(UDP_PAYLOAD, (dstaddr, 53)) 222*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg, expected) 223*2f2c4c7aSAndroid Build Coastguard Worker 224*2f2c4c7aSAndroid Build Coastguard Worker # Does this socket have a stale dst cache entry that we need to clear? 225*2f2c4c7aSAndroid Build Coastguard Worker def SocketHasStaleDstCacheEntry(): 226*2f2c4c7aSAndroid Build Coastguard Worker if not prevnetid: 227*2f2c4c7aSAndroid Build Coastguard Worker # This is the first time we're marking the socket. 228*2f2c4c7aSAndroid Build Coastguard Worker return False 229*2f2c4c7aSAndroid Build Coastguard Worker if not use_connect: 230*2f2c4c7aSAndroid Build Coastguard Worker # Non-connected sockets never have dst cache entries. 231*2f2c4c7aSAndroid Build Coastguard Worker return False 232*2f2c4c7aSAndroid Build Coastguard Worker if mode in ["uid", "ucast_oif"]: 233*2f2c4c7aSAndroid Build Coastguard Worker # No kernel invalidates the dst cache entry if the UID or the 234*2f2c4c7aSAndroid Build Coastguard Worker # UCAST_OIF socket option changes. 235*2f2c4c7aSAndroid Build Coastguard Worker return True 236*2f2c4c7aSAndroid Build Coastguard Worker if mode == "oif": 237*2f2c4c7aSAndroid Build Coastguard Worker # Changing SO_BINDTODEVICE always invalidates the dst cache entry. 238*2f2c4c7aSAndroid Build Coastguard Worker return False 239*2f2c4c7aSAndroid Build Coastguard Worker if mode == "mark": 240*2f2c4c7aSAndroid Build Coastguard Worker # Changing the mark invalidates the dst cache entry in 5.0+. 241*2f2c4c7aSAndroid Build Coastguard Worker return net_test.LINUX_VERSION < (5, 0, 0) 242*2f2c4c7aSAndroid Build Coastguard Worker raise AssertionError("%s must be one of %s" % (mode, modes)) 243*2f2c4c7aSAndroid Build Coastguard Worker 244*2f2c4c7aSAndroid Build Coastguard Worker if SocketHasStaleDstCacheEntry(): 245*2f2c4c7aSAndroid Build Coastguard Worker ExpectSendUsesNetid(prevnetid) 246*2f2c4c7aSAndroid Build Coastguard Worker # ... until we invalidate it. 247*2f2c4c7aSAndroid Build Coastguard Worker self.InvalidateDstCache(version, prevnetid) 248*2f2c4c7aSAndroid Build Coastguard Worker 249*2f2c4c7aSAndroid Build Coastguard Worker # In any case, future sends must be correct. 250*2f2c4c7aSAndroid Build Coastguard Worker ExpectSendUsesNetid(netid) 251*2f2c4c7aSAndroid Build Coastguard Worker 252*2f2c4c7aSAndroid Build Coastguard Worker self.SelectInterface(s, None, mode) 253*2f2c4c7aSAndroid Build Coastguard Worker prevnetid = netid 254*2f2c4c7aSAndroid Build Coastguard Worker 255*2f2c4c7aSAndroid Build Coastguard Worker s.close() 256*2f2c4c7aSAndroid Build Coastguard Worker 257*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4Remarking(self): 258*2f2c4c7aSAndroid Build Coastguard Worker """Checks that updating the mark on an IPv4 socket changes routing.""" 259*2f2c4c7aSAndroid Build Coastguard Worker self.CheckRemarking(4, False) 260*2f2c4c7aSAndroid Build Coastguard Worker self.CheckRemarking(4, True) 261*2f2c4c7aSAndroid Build Coastguard Worker 262*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6Remarking(self): 263*2f2c4c7aSAndroid Build Coastguard Worker """Checks that updating the mark on an IPv6 socket changes routing.""" 264*2f2c4c7aSAndroid Build Coastguard Worker self.CheckRemarking(6, False) 265*2f2c4c7aSAndroid Build Coastguard Worker self.CheckRemarking(6, True) 266*2f2c4c7aSAndroid Build Coastguard Worker 267*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6StickyPktinfo(self): 268*2f2c4c7aSAndroid Build Coastguard Worker for _ in range(self.ITERATIONS): 269*2f2c4c7aSAndroid Build Coastguard Worker for netid in self.tuns: 270*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.UDPSocket(AF_INET6) 271*2f2c4c7aSAndroid Build Coastguard Worker 272*2f2c4c7aSAndroid Build Coastguard Worker # Set a flowlabel. 273*2f2c4c7aSAndroid Build Coastguard Worker net_test.SetFlowLabel(s, net_test.IPV6_ADDR, 0xdead) 274*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_FLOWINFO_SEND, 1) 275*2f2c4c7aSAndroid Build Coastguard Worker 276*2f2c4c7aSAndroid Build Coastguard Worker # Set some destination options. 277*2f2c4c7aSAndroid Build Coastguard Worker nonce = b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c" 278*2f2c4c7aSAndroid Build Coastguard Worker dstopts = b"".join([ 279*2f2c4c7aSAndroid Build Coastguard Worker b"\x11\x02", # Next header=UDP, 24 bytes of options. 280*2f2c4c7aSAndroid Build Coastguard Worker b"\x01\x06", b"\x00" * 6, # PadN, 6 bytes of padding. 281*2f2c4c7aSAndroid Build Coastguard Worker b"\x8b\x0c", # ILNP nonce, 12 bytes. 282*2f2c4c7aSAndroid Build Coastguard Worker nonce 283*2f2c4c7aSAndroid Build Coastguard Worker ]) 284*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, IPV6_DSTOPTS, dstopts) 285*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, IPV6_UNICAST_HOPS, 255) 286*2f2c4c7aSAndroid Build Coastguard Worker 287*2f2c4c7aSAndroid Build Coastguard Worker pktinfo = multinetwork_base.MakePktInfo(6, None, self.ifindices[netid]) 288*2f2c4c7aSAndroid Build Coastguard Worker 289*2f2c4c7aSAndroid Build Coastguard Worker # Set the sticky pktinfo option. 290*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, IPV6_PKTINFO, pktinfo) 291*2f2c4c7aSAndroid Build Coastguard Worker 292*2f2c4c7aSAndroid Build Coastguard Worker # Specify the flowlabel in the destination address. 293*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(UDP_PAYLOAD, (net_test.IPV6_ADDR, 53, 0xdead, 0)) 294*2f2c4c7aSAndroid Build Coastguard Worker 295*2f2c4c7aSAndroid Build Coastguard Worker sport = s.getsockname()[1] 296*2f2c4c7aSAndroid Build Coastguard Worker srcaddr = self.MyAddress(6, netid) 297*2f2c4c7aSAndroid Build Coastguard Worker expected = (scapy.IPv6(src=srcaddr, dst=net_test.IPV6_ADDR, 298*2f2c4c7aSAndroid Build Coastguard Worker fl=0xdead, hlim=255) / 299*2f2c4c7aSAndroid Build Coastguard Worker scapy.IPv6ExtHdrDestOpt( 300*2f2c4c7aSAndroid Build Coastguard Worker options=[scapy.PadN(optdata="\x00\x00\x00\x00\x00\x00"), 301*2f2c4c7aSAndroid Build Coastguard Worker scapy.HBHOptUnknown(otype=0x8b, 302*2f2c4c7aSAndroid Build Coastguard Worker optdata=nonce)]) / 303*2f2c4c7aSAndroid Build Coastguard Worker scapy.UDP(sport=sport, dport=53) / 304*2f2c4c7aSAndroid Build Coastguard Worker UDP_PAYLOAD) 305*2f2c4c7aSAndroid Build Coastguard Worker msg = "IPv6 UDP using sticky pktinfo: expected UDP packet on %s" % ( 306*2f2c4c7aSAndroid Build Coastguard Worker self.GetInterfaceName(netid)) 307*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg, expected) 308*2f2c4c7aSAndroid Build Coastguard Worker s.close() 309*2f2c4c7aSAndroid Build Coastguard Worker 310*2f2c4c7aSAndroid Build Coastguard Worker def CheckPktinfoRouting(self, version): 311*2f2c4c7aSAndroid Build Coastguard Worker for _ in range(self.ITERATIONS): 312*2f2c4c7aSAndroid Build Coastguard Worker for netid in self.tuns: 313*2f2c4c7aSAndroid Build Coastguard Worker family = self.GetProtocolFamily(version) 314*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.UDPSocket(family) 315*2f2c4c7aSAndroid Build Coastguard Worker 316*2f2c4c7aSAndroid Build Coastguard Worker if version == 6: 317*2f2c4c7aSAndroid Build Coastguard Worker # Create a flowlabel so we can use it. 318*2f2c4c7aSAndroid Build Coastguard Worker net_test.SetFlowLabel(s, net_test.IPV6_ADDR, 0xbeef) 319*2f2c4c7aSAndroid Build Coastguard Worker 320*2f2c4c7aSAndroid Build Coastguard Worker # Specify some arbitrary options. 321*2f2c4c7aSAndroid Build Coastguard Worker # We declare the flowlabel as ctypes.c_uint32 because on a 32-bit 322*2f2c4c7aSAndroid Build Coastguard Worker # Python interpreter an integer greater than 0x7fffffff (such as our 323*2f2c4c7aSAndroid Build Coastguard Worker # chosen flowlabel after being passed through htonl) is converted to 324*2f2c4c7aSAndroid Build Coastguard Worker # long, and _MakeMsgControl doesn't know what to do with longs. 325*2f2c4c7aSAndroid Build Coastguard Worker cmsgs = [ 326*2f2c4c7aSAndroid Build Coastguard Worker (net_test.SOL_IPV6, IPV6_HOPLIMIT, 39), 327*2f2c4c7aSAndroid Build Coastguard Worker (net_test.SOL_IPV6, IPV6_TCLASS, 0x83), 328*2f2c4c7aSAndroid Build Coastguard Worker (net_test.SOL_IPV6, IPV6_FLOWINFO, ctypes.c_uint(htonl(0xbeef))), 329*2f2c4c7aSAndroid Build Coastguard Worker ] 330*2f2c4c7aSAndroid Build Coastguard Worker else: 331*2f2c4c7aSAndroid Build Coastguard Worker # Support for setting IPv4 TOS and TTL via cmsg only appeared in 3.13. 332*2f2c4c7aSAndroid Build Coastguard Worker cmsgs = [] 333*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IP, IP_TTL, 39) 334*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IP, IP_TOS, 0x83) 335*2f2c4c7aSAndroid Build Coastguard Worker 336*2f2c4c7aSAndroid Build Coastguard Worker dstaddr = self.GetRemoteAddress(version) 337*2f2c4c7aSAndroid Build Coastguard Worker self.SendOnNetid(version, s, dstaddr, 53, netid, UDP_PAYLOAD, cmsgs) 338*2f2c4c7aSAndroid Build Coastguard Worker 339*2f2c4c7aSAndroid Build Coastguard Worker sport = s.getsockname()[1] 340*2f2c4c7aSAndroid Build Coastguard Worker srcaddr = self.MyAddress(version, netid) 341*2f2c4c7aSAndroid Build Coastguard Worker 342*2f2c4c7aSAndroid Build Coastguard Worker desc, expected = packets.UDPWithOptions(version, srcaddr, dstaddr, 343*2f2c4c7aSAndroid Build Coastguard Worker sport=sport) 344*2f2c4c7aSAndroid Build Coastguard Worker 345*2f2c4c7aSAndroid Build Coastguard Worker msg = "IPv%d UDP using pktinfo routing: expected %s on %s" % ( 346*2f2c4c7aSAndroid Build Coastguard Worker version, desc, self.GetInterfaceName(netid)) 347*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg, expected) 348*2f2c4c7aSAndroid Build Coastguard Worker 349*2f2c4c7aSAndroid Build Coastguard Worker s.close() 350*2f2c4c7aSAndroid Build Coastguard Worker 351*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4PktinfoRouting(self): 352*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPktinfoRouting(4) 353*2f2c4c7aSAndroid Build Coastguard Worker 354*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6PktinfoRouting(self): 355*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPktinfoRouting(6) 356*2f2c4c7aSAndroid Build Coastguard Worker 357*2f2c4c7aSAndroid Build Coastguard Worker 358*2f2c4c7aSAndroid Build Coastguard Workerclass MarkTest(multinetwork_base.InboundMarkingTest): 359*2f2c4c7aSAndroid Build Coastguard Worker 360*2f2c4c7aSAndroid Build Coastguard Worker def CheckReflection(self, version, gen_packet, gen_reply): 361*2f2c4c7aSAndroid Build Coastguard Worker """Checks that replies go out on the same interface as the original. 362*2f2c4c7aSAndroid Build Coastguard Worker 363*2f2c4c7aSAndroid Build Coastguard Worker For each combination: 364*2f2c4c7aSAndroid Build Coastguard Worker - Calls gen_packet to generate a packet to that IP address. 365*2f2c4c7aSAndroid Build Coastguard Worker - Writes the packet generated by gen_packet on the given tun 366*2f2c4c7aSAndroid Build Coastguard Worker interface, causing the kernel to receive it. 367*2f2c4c7aSAndroid Build Coastguard Worker - Checks that the kernel's reply matches the packet generated by 368*2f2c4c7aSAndroid Build Coastguard Worker gen_reply. 369*2f2c4c7aSAndroid Build Coastguard Worker 370*2f2c4c7aSAndroid Build Coastguard Worker Args: 371*2f2c4c7aSAndroid Build Coastguard Worker version: An integer, 4 or 6. 372*2f2c4c7aSAndroid Build Coastguard Worker gen_packet: A function taking an IP version (an integer), a source 373*2f2c4c7aSAndroid Build Coastguard Worker address and a destination address (strings), and returning a scapy 374*2f2c4c7aSAndroid Build Coastguard Worker packet. 375*2f2c4c7aSAndroid Build Coastguard Worker gen_reply: A function taking the same arguments as gen_packet, 376*2f2c4c7aSAndroid Build Coastguard Worker plus a scapy packet, and returning a scapy packet. 377*2f2c4c7aSAndroid Build Coastguard Worker """ 378*2f2c4c7aSAndroid Build Coastguard Worker for netid, iif, ip_if, myaddr, remoteaddr in self.Combinations(version): 379*2f2c4c7aSAndroid Build Coastguard Worker # Generate a test packet. 380*2f2c4c7aSAndroid Build Coastguard Worker desc, packet = gen_packet(version, remoteaddr, myaddr) 381*2f2c4c7aSAndroid Build Coastguard Worker 382*2f2c4c7aSAndroid Build Coastguard Worker # Test with mark reflection enabled and disabled. 383*2f2c4c7aSAndroid Build Coastguard Worker for reflect in [0, 1]: 384*2f2c4c7aSAndroid Build Coastguard Worker self.SetMarkReflectSysctls(reflect) 385*2f2c4c7aSAndroid Build Coastguard Worker # HACK: IPv6 ping replies always do a routing lookup with the 386*2f2c4c7aSAndroid Build Coastguard Worker # interface the ping came in on. So even if mark reflection is not 387*2f2c4c7aSAndroid Build Coastguard Worker # working, IPv6 ping replies will be properly reflected. Don't 388*2f2c4c7aSAndroid Build Coastguard Worker # fail when that happens. 389*2f2c4c7aSAndroid Build Coastguard Worker if reflect or desc == "ICMPv6 echo": 390*2f2c4c7aSAndroid Build Coastguard Worker reply_desc, reply = gen_reply(version, myaddr, remoteaddr, packet) 391*2f2c4c7aSAndroid Build Coastguard Worker else: 392*2f2c4c7aSAndroid Build Coastguard Worker reply_desc, reply = None, None 393*2f2c4c7aSAndroid Build Coastguard Worker 394*2f2c4c7aSAndroid Build Coastguard Worker msg = self._FormatMessage(iif, ip_if, "reflect=%d" % reflect, 395*2f2c4c7aSAndroid Build Coastguard Worker desc, reply_desc) 396*2f2c4c7aSAndroid Build Coastguard Worker self._ReceiveAndExpectResponse(netid, packet, reply, msg) 397*2f2c4c7aSAndroid Build Coastguard Worker 398*2f2c4c7aSAndroid Build Coastguard Worker def SYNToClosedPort(self, *args): 399*2f2c4c7aSAndroid Build Coastguard Worker return packets.SYN(999, *args) 400*2f2c4c7aSAndroid Build Coastguard Worker 401*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4ICMPErrorsReflectMark(self): 402*2f2c4c7aSAndroid Build Coastguard Worker self.CheckReflection(4, packets.UDP, packets.ICMPPortUnreachable) 403*2f2c4c7aSAndroid Build Coastguard Worker 404*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6ICMPErrorsReflectMark(self): 405*2f2c4c7aSAndroid Build Coastguard Worker self.CheckReflection(6, packets.UDP, packets.ICMPPortUnreachable) 406*2f2c4c7aSAndroid Build Coastguard Worker 407*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4PingRepliesReflectMarkAndTos(self): 408*2f2c4c7aSAndroid Build Coastguard Worker self.CheckReflection(4, packets.ICMPEcho, packets.ICMPReply) 409*2f2c4c7aSAndroid Build Coastguard Worker 410*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6PingRepliesReflectMarkAndTos(self): 411*2f2c4c7aSAndroid Build Coastguard Worker self.CheckReflection(6, packets.ICMPEcho, packets.ICMPReply) 412*2f2c4c7aSAndroid Build Coastguard Worker 413*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4RSTsReflectMark(self): 414*2f2c4c7aSAndroid Build Coastguard Worker self.CheckReflection(4, self.SYNToClosedPort, packets.RST) 415*2f2c4c7aSAndroid Build Coastguard Worker 416*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6RSTsReflectMark(self): 417*2f2c4c7aSAndroid Build Coastguard Worker self.CheckReflection(6, self.SYNToClosedPort, packets.RST) 418*2f2c4c7aSAndroid Build Coastguard Worker 419*2f2c4c7aSAndroid Build Coastguard Worker 420*2f2c4c7aSAndroid Build Coastguard Workerclass TCPAcceptTest(multinetwork_base.InboundMarkingTest): 421*2f2c4c7aSAndroid Build Coastguard Worker 422*2f2c4c7aSAndroid Build Coastguard Worker MODE_BINDTODEVICE = "SO_BINDTODEVICE" 423*2f2c4c7aSAndroid Build Coastguard Worker MODE_INCOMING_MARK = "incoming mark" 424*2f2c4c7aSAndroid Build Coastguard Worker MODE_EXPLICIT_MARK = "explicit mark" 425*2f2c4c7aSAndroid Build Coastguard Worker MODE_UID = "uid" 426*2f2c4c7aSAndroid Build Coastguard Worker 427*2f2c4c7aSAndroid Build Coastguard Worker @classmethod 428*2f2c4c7aSAndroid Build Coastguard Worker def setUpClass(cls): 429*2f2c4c7aSAndroid Build Coastguard Worker super(TCPAcceptTest, cls).setUpClass() 430*2f2c4c7aSAndroid Build Coastguard Worker 431*2f2c4c7aSAndroid Build Coastguard Worker # Open a port so we can observe SYN+ACKs. Since it's a dual-stack socket it 432*2f2c4c7aSAndroid Build Coastguard Worker # will accept both IPv4 and IPv6 connections. We do this here instead of in 433*2f2c4c7aSAndroid Build Coastguard Worker # each test so we can use the same socket every time. That way, if a kernel 434*2f2c4c7aSAndroid Build Coastguard Worker # bug causes incoming packets to mark the listening socket instead of the 435*2f2c4c7aSAndroid Build Coastguard Worker # accepted socket, the test will fail as soon as the next address/interface 436*2f2c4c7aSAndroid Build Coastguard Worker # combination is tried. 437*2f2c4c7aSAndroid Build Coastguard Worker cls.listensocket = net_test.IPv6TCPSocket() 438*2f2c4c7aSAndroid Build Coastguard Worker cls.listenport = net_test.BindRandomPort(6, cls.listensocket) 439*2f2c4c7aSAndroid Build Coastguard Worker 440*2f2c4c7aSAndroid Build Coastguard Worker def _SetTCPMarkAcceptSysctl(self, value): 441*2f2c4c7aSAndroid Build Coastguard Worker self.SetSysctl(TCP_MARK_ACCEPT_SYSCTL, value) 442*2f2c4c7aSAndroid Build Coastguard Worker 443*2f2c4c7aSAndroid Build Coastguard Worker def CheckTCPConnection(self, mode, listensocket, netid, version, 444*2f2c4c7aSAndroid Build Coastguard Worker myaddr, remoteaddr, packet, reply, msg): 445*2f2c4c7aSAndroid Build Coastguard Worker establishing_ack = packets.ACK(version, remoteaddr, myaddr, reply)[1] 446*2f2c4c7aSAndroid Build Coastguard Worker 447*2f2c4c7aSAndroid Build Coastguard Worker # Attempt to confuse the kernel. 448*2f2c4c7aSAndroid Build Coastguard Worker self.InvalidateDstCache(version, netid) 449*2f2c4c7aSAndroid Build Coastguard Worker 450*2f2c4c7aSAndroid Build Coastguard Worker self.ReceivePacketOn(netid, establishing_ack) 451*2f2c4c7aSAndroid Build Coastguard Worker 452*2f2c4c7aSAndroid Build Coastguard Worker # If we're using UID routing, the accept() call has to be run as a UID that 453*2f2c4c7aSAndroid Build Coastguard Worker # is routed to the specified netid, because the UID of the socket returned 454*2f2c4c7aSAndroid Build Coastguard Worker # by accept() is the effective UID of the process that calls it. It doesn't 455*2f2c4c7aSAndroid Build Coastguard Worker # need to be the same UID; any UID that selects the same interface will do. 456*2f2c4c7aSAndroid Build Coastguard Worker with net_test.RunAsUid(self.UidForNetid(netid)): 457*2f2c4c7aSAndroid Build Coastguard Worker s, _ = listensocket.accept() 458*2f2c4c7aSAndroid Build Coastguard Worker 459*2f2c4c7aSAndroid Build Coastguard Worker try: 460*2f2c4c7aSAndroid Build Coastguard Worker # Check that data sent on the connection goes out on the right interface. 461*2f2c4c7aSAndroid Build Coastguard Worker desc, data = packets.ACK(version, myaddr, remoteaddr, establishing_ack, 462*2f2c4c7aSAndroid Build Coastguard Worker payload=UDP_PAYLOAD) 463*2f2c4c7aSAndroid Build Coastguard Worker s.send(UDP_PAYLOAD) 464*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg + ": expecting %s" % desc, data) 465*2f2c4c7aSAndroid Build Coastguard Worker self.InvalidateDstCache(version, netid) 466*2f2c4c7aSAndroid Build Coastguard Worker 467*2f2c4c7aSAndroid Build Coastguard Worker # Keep up our end of the conversation. 468*2f2c4c7aSAndroid Build Coastguard Worker ack = packets.ACK(version, remoteaddr, myaddr, data)[1] 469*2f2c4c7aSAndroid Build Coastguard Worker self.InvalidateDstCache(version, netid) 470*2f2c4c7aSAndroid Build Coastguard Worker self.ReceivePacketOn(netid, ack) 471*2f2c4c7aSAndroid Build Coastguard Worker 472*2f2c4c7aSAndroid Build Coastguard Worker mark = self.GetSocketMark(s) 473*2f2c4c7aSAndroid Build Coastguard Worker finally: 474*2f2c4c7aSAndroid Build Coastguard Worker self.InvalidateDstCache(version, netid) 475*2f2c4c7aSAndroid Build Coastguard Worker s.close() 476*2f2c4c7aSAndroid Build Coastguard Worker self.InvalidateDstCache(version, netid) 477*2f2c4c7aSAndroid Build Coastguard Worker 478*2f2c4c7aSAndroid Build Coastguard Worker if mode == self.MODE_INCOMING_MARK: 479*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(netid, mark & self.NETID_FWMASK, 480*2f2c4c7aSAndroid Build Coastguard Worker msg + ": Accepted socket: Expected mark %d, got %d" % ( 481*2f2c4c7aSAndroid Build Coastguard Worker netid, mark)) 482*2f2c4c7aSAndroid Build Coastguard Worker elif mode != self.MODE_EXPLICIT_MARK: 483*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(0, self.GetSocketMark(listensocket)) 484*2f2c4c7aSAndroid Build Coastguard Worker 485*2f2c4c7aSAndroid Build Coastguard Worker # Check the FIN was sent on the right interface, and ack it. We don't expect 486*2f2c4c7aSAndroid Build Coastguard Worker # this to fail because by the time the connection is established things are 487*2f2c4c7aSAndroid Build Coastguard Worker # likely working, but a) extra tests are always good and b) extra packets 488*2f2c4c7aSAndroid Build Coastguard Worker # like the FIN (and retransmitted FINs) could cause later tests that expect 489*2f2c4c7aSAndroid Build Coastguard Worker # no packets to fail. 490*2f2c4c7aSAndroid Build Coastguard Worker desc, fin = packets.FIN(version, myaddr, remoteaddr, ack) 491*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg + ": expecting %s after close" % desc, fin) 492*2f2c4c7aSAndroid Build Coastguard Worker 493*2f2c4c7aSAndroid Build Coastguard Worker desc, finack = packets.FIN(version, remoteaddr, myaddr, fin) 494*2f2c4c7aSAndroid Build Coastguard Worker self.ReceivePacketOn(netid, finack) 495*2f2c4c7aSAndroid Build Coastguard Worker 496*2f2c4c7aSAndroid Build Coastguard Worker # Since we called close() earlier, the userspace socket object is gone, so 497*2f2c4c7aSAndroid Build Coastguard Worker # the socket has no UID. If we're doing UID routing, the ack might be routed 498*2f2c4c7aSAndroid Build Coastguard Worker # incorrectly. Not much we can do here. 499*2f2c4c7aSAndroid Build Coastguard Worker desc, finackack = packets.ACK(version, myaddr, remoteaddr, finack) 500*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg + ": expecting final ack", finackack) 501*2f2c4c7aSAndroid Build Coastguard Worker 502*2f2c4c7aSAndroid Build Coastguard Worker def CheckTCP(self, version, modes): 503*2f2c4c7aSAndroid Build Coastguard Worker """Checks that incoming TCP connections work. 504*2f2c4c7aSAndroid Build Coastguard Worker 505*2f2c4c7aSAndroid Build Coastguard Worker Args: 506*2f2c4c7aSAndroid Build Coastguard Worker version: An integer, 4 or 6. 507*2f2c4c7aSAndroid Build Coastguard Worker modes: A list of modes to excercise. 508*2f2c4c7aSAndroid Build Coastguard Worker """ 509*2f2c4c7aSAndroid Build Coastguard Worker for syncookies in [0, 2]: 510*2f2c4c7aSAndroid Build Coastguard Worker for mode in modes: 511*2f2c4c7aSAndroid Build Coastguard Worker for netid, iif, ip_if, myaddr, remoteaddr in self.Combinations(version): 512*2f2c4c7aSAndroid Build Coastguard Worker listensocket = self.listensocket 513*2f2c4c7aSAndroid Build Coastguard Worker listenport = listensocket.getsockname()[1] 514*2f2c4c7aSAndroid Build Coastguard Worker 515*2f2c4c7aSAndroid Build Coastguard Worker accept_sysctl = 1 if mode == self.MODE_INCOMING_MARK else 0 516*2f2c4c7aSAndroid Build Coastguard Worker self._SetTCPMarkAcceptSysctl(accept_sysctl) 517*2f2c4c7aSAndroid Build Coastguard Worker self.SetMarkReflectSysctls(accept_sysctl) 518*2f2c4c7aSAndroid Build Coastguard Worker 519*2f2c4c7aSAndroid Build Coastguard Worker bound_dev = iif if mode == self.MODE_BINDTODEVICE else None 520*2f2c4c7aSAndroid Build Coastguard Worker self.BindToDevice(listensocket, bound_dev) 521*2f2c4c7aSAndroid Build Coastguard Worker 522*2f2c4c7aSAndroid Build Coastguard Worker mark = netid if mode == self.MODE_EXPLICIT_MARK else 0 523*2f2c4c7aSAndroid Build Coastguard Worker self.SetSocketMark(listensocket, mark) 524*2f2c4c7aSAndroid Build Coastguard Worker 525*2f2c4c7aSAndroid Build Coastguard Worker uid = self.UidForNetid(netid) if mode == self.MODE_UID else 0 526*2f2c4c7aSAndroid Build Coastguard Worker os.fchown(listensocket.fileno(), uid, -1) 527*2f2c4c7aSAndroid Build Coastguard Worker 528*2f2c4c7aSAndroid Build Coastguard Worker # Generate the packet here instead of in the outer loop, so 529*2f2c4c7aSAndroid Build Coastguard Worker # subsequent TCP connections use different source ports and 530*2f2c4c7aSAndroid Build Coastguard Worker # retransmissions from old connections don't confuse subsequent 531*2f2c4c7aSAndroid Build Coastguard Worker # tests. 532*2f2c4c7aSAndroid Build Coastguard Worker desc, packet = packets.SYN(listenport, version, remoteaddr, myaddr) 533*2f2c4c7aSAndroid Build Coastguard Worker 534*2f2c4c7aSAndroid Build Coastguard Worker if mode: 535*2f2c4c7aSAndroid Build Coastguard Worker reply_desc, reply = packets.SYNACK(version, myaddr, remoteaddr, 536*2f2c4c7aSAndroid Build Coastguard Worker packet) 537*2f2c4c7aSAndroid Build Coastguard Worker else: 538*2f2c4c7aSAndroid Build Coastguard Worker reply_desc, reply = None, None 539*2f2c4c7aSAndroid Build Coastguard Worker 540*2f2c4c7aSAndroid Build Coastguard Worker extra = "mode=%s, syncookies=%d" % (mode, syncookies) 541*2f2c4c7aSAndroid Build Coastguard Worker msg = self._FormatMessage(iif, ip_if, extra, desc, reply_desc) 542*2f2c4c7aSAndroid Build Coastguard Worker reply = self._ReceiveAndExpectResponse(netid, packet, reply, msg) 543*2f2c4c7aSAndroid Build Coastguard Worker if reply: 544*2f2c4c7aSAndroid Build Coastguard Worker self.CheckTCPConnection(mode, listensocket, netid, version, myaddr, 545*2f2c4c7aSAndroid Build Coastguard Worker remoteaddr, packet, reply, msg) 546*2f2c4c7aSAndroid Build Coastguard Worker 547*2f2c4c7aSAndroid Build Coastguard Worker def testBasicTCP(self): 548*2f2c4c7aSAndroid Build Coastguard Worker self.CheckTCP(4, [None, self.MODE_BINDTODEVICE, self.MODE_EXPLICIT_MARK]) 549*2f2c4c7aSAndroid Build Coastguard Worker self.CheckTCP(6, [None, self.MODE_BINDTODEVICE, self.MODE_EXPLICIT_MARK]) 550*2f2c4c7aSAndroid Build Coastguard Worker 551*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4MarkAccept(self): 552*2f2c4c7aSAndroid Build Coastguard Worker self.CheckTCP(4, [self.MODE_INCOMING_MARK]) 553*2f2c4c7aSAndroid Build Coastguard Worker 554*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6MarkAccept(self): 555*2f2c4c7aSAndroid Build Coastguard Worker self.CheckTCP(6, [self.MODE_INCOMING_MARK]) 556*2f2c4c7aSAndroid Build Coastguard Worker 557*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4UidAccept(self): 558*2f2c4c7aSAndroid Build Coastguard Worker self.CheckTCP(4, [self.MODE_UID]) 559*2f2c4c7aSAndroid Build Coastguard Worker 560*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6UidAccept(self): 561*2f2c4c7aSAndroid Build Coastguard Worker self.CheckTCP(6, [self.MODE_UID]) 562*2f2c4c7aSAndroid Build Coastguard Worker 563*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6ExplicitMark(self): 564*2f2c4c7aSAndroid Build Coastguard Worker self.CheckTCP(6, [self.MODE_EXPLICIT_MARK]) 565*2f2c4c7aSAndroid Build Coastguard Worker 566*2f2c4c7aSAndroid Build Coastguard Workerclass RIOTest(multinetwork_base.MultiNetworkBaseTest): 567*2f2c4c7aSAndroid Build Coastguard Worker """Test for IPv6 RFC 4191 route information option 568*2f2c4c7aSAndroid Build Coastguard Worker 569*2f2c4c7aSAndroid Build Coastguard Worker Relevant kernel commits: 570*2f2c4c7aSAndroid Build Coastguard Worker upstream: 571*2f2c4c7aSAndroid Build Coastguard Worker f104a567e673 ipv6: use rt6_get_dflt_router to get default router in rt6_route_rcv 572*2f2c4c7aSAndroid Build Coastguard Worker bbea124bc99d net: ipv6: Add sysctl for minimum prefix len acceptable in RIOs. 573*2f2c4c7aSAndroid Build Coastguard Worker 574*2f2c4c7aSAndroid Build Coastguard Worker android-4.9: 575*2f2c4c7aSAndroid Build Coastguard Worker d860b2e8a7f1 FROMLIST: net: ipv6: Add sysctl for minimum prefix len acceptable in RIOs 576*2f2c4c7aSAndroid Build Coastguard Worker 577*2f2c4c7aSAndroid Build Coastguard Worker android-4.4: 578*2f2c4c7aSAndroid Build Coastguard Worker e953f89b8563 net: ipv6: Add sysctl for minimum prefix len acceptable in RIOs. 579*2f2c4c7aSAndroid Build Coastguard Worker 580*2f2c4c7aSAndroid Build Coastguard Worker android-4.1: 581*2f2c4c7aSAndroid Build Coastguard Worker 84f2f47716cd net: ipv6: Add sysctl for minimum prefix len acceptable in RIOs. 582*2f2c4c7aSAndroid Build Coastguard Worker 583*2f2c4c7aSAndroid Build Coastguard Worker android-3.18: 584*2f2c4c7aSAndroid Build Coastguard Worker 65f8936934fa net: ipv6: Add sysctl for minimum prefix len acceptable in RIOs. 585*2f2c4c7aSAndroid Build Coastguard Worker 586*2f2c4c7aSAndroid Build Coastguard Worker android-3.10: 587*2f2c4c7aSAndroid Build Coastguard Worker 161e88ebebc7 net: ipv6: Add sysctl for minimum prefix len acceptable in RIOs. 588*2f2c4c7aSAndroid Build Coastguard Worker 589*2f2c4c7aSAndroid Build Coastguard Worker """ 590*2f2c4c7aSAndroid Build Coastguard Worker 591*2f2c4c7aSAndroid Build Coastguard Worker def setUp(self): 592*2f2c4c7aSAndroid Build Coastguard Worker super(RIOTest, self).setUp() 593*2f2c4c7aSAndroid Build Coastguard Worker self.NETID = random.choice(self.NETIDS) 594*2f2c4c7aSAndroid Build Coastguard Worker self.IFACE = self.GetInterfaceName(self.NETID) 595*2f2c4c7aSAndroid Build Coastguard Worker # return sysctls to default values before each test case 596*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMinPlen(0) 597*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMaxPlen(0) 598*2f2c4c7aSAndroid Build Coastguard Worker if multinetwork_base.HAVE_ACCEPT_RA_MIN_LFT: 599*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaMinLft(0) 600*2f2c4c7aSAndroid Build Coastguard Worker if multinetwork_base.HAVE_RA_HONOR_PIO_LIFE: 601*2f2c4c7aSAndroid Build Coastguard Worker self.SetRaHonorPioLife(0) 602*2f2c4c7aSAndroid Build Coastguard Worker if multinetwork_base.HAVE_RA_HONOR_PIO_PFLAG: 603*2f2c4c7aSAndroid Build Coastguard Worker self.SetRaHonorPioPflag(0) 604*2f2c4c7aSAndroid Build Coastguard Worker 605*2f2c4c7aSAndroid Build Coastguard Worker def GetRoutingTable(self): 606*2f2c4c7aSAndroid Build Coastguard Worker if multinetwork_base.HAVE_AUTOCONF_TABLE: 607*2f2c4c7aSAndroid Build Coastguard Worker return self._TableForNetid(self.NETID) 608*2f2c4c7aSAndroid Build Coastguard Worker else: 609*2f2c4c7aSAndroid Build Coastguard Worker # main table 610*2f2c4c7aSAndroid Build Coastguard Worker return 254 611*2f2c4c7aSAndroid Build Coastguard Worker 612*2f2c4c7aSAndroid Build Coastguard Worker def SetAcceptRaRtInfoMinPlen(self, plen): 613*2f2c4c7aSAndroid Build Coastguard Worker self.SetSysctl( 614*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/ipv6/conf/%s/accept_ra_rt_info_min_plen" 615*2f2c4c7aSAndroid Build Coastguard Worker % self.IFACE, plen) 616*2f2c4c7aSAndroid Build Coastguard Worker 617*2f2c4c7aSAndroid Build Coastguard Worker def GetAcceptRaRtInfoMinPlen(self): 618*2f2c4c7aSAndroid Build Coastguard Worker return int(self.GetSysctl( 619*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/ipv6/conf/%s/accept_ra_rt_info_min_plen" % self.IFACE)) 620*2f2c4c7aSAndroid Build Coastguard Worker 621*2f2c4c7aSAndroid Build Coastguard Worker def SetAcceptRaRtInfoMaxPlen(self, plen): 622*2f2c4c7aSAndroid Build Coastguard Worker self.SetSysctl( 623*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/ipv6/conf/%s/accept_ra_rt_info_max_plen" 624*2f2c4c7aSAndroid Build Coastguard Worker % self.IFACE, plen) 625*2f2c4c7aSAndroid Build Coastguard Worker 626*2f2c4c7aSAndroid Build Coastguard Worker def GetAcceptRaRtInfoMaxPlen(self): 627*2f2c4c7aSAndroid Build Coastguard Worker return int(self.GetSysctl( 628*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/ipv6/conf/%s/accept_ra_rt_info_max_plen" % self.IFACE)) 629*2f2c4c7aSAndroid Build Coastguard Worker 630*2f2c4c7aSAndroid Build Coastguard Worker def SetAcceptRaMinLft(self, min_lft): 631*2f2c4c7aSAndroid Build Coastguard Worker self.SetSysctl( 632*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/ipv6/conf/%s/accept_ra_min_lft" % self.IFACE, min_lft) 633*2f2c4c7aSAndroid Build Coastguard Worker 634*2f2c4c7aSAndroid Build Coastguard Worker def SetRaHonorPioPflag(self, val): 635*2f2c4c7aSAndroid Build Coastguard Worker self.SetSysctl( 636*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/ipv6/conf/%s/ra_honor_pio_pflag" % self.IFACE, val) 637*2f2c4c7aSAndroid Build Coastguard Worker 638*2f2c4c7aSAndroid Build Coastguard Worker def GetAcceptRaMinLft(self): 639*2f2c4c7aSAndroid Build Coastguard Worker return int(self.GetSysctl( 640*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/ipv6/conf/%s/accept_ra_min_lft" % self.IFACE)) 641*2f2c4c7aSAndroid Build Coastguard Worker 642*2f2c4c7aSAndroid Build Coastguard Worker def SetRaHonorPioLife(self, enabled): 643*2f2c4c7aSAndroid Build Coastguard Worker self.SetSysctl( 644*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/ipv6/conf/%s/ra_honor_pio_life" % self.IFACE, enabled) 645*2f2c4c7aSAndroid Build Coastguard Worker 646*2f2c4c7aSAndroid Build Coastguard Worker def GetRaHonorPioLife(self): 647*2f2c4c7aSAndroid Build Coastguard Worker return int(self.GetSysctl( 648*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/ipv6/conf/%s/ra_honor_pio_life" % self.IFACE)) 649*2f2c4c7aSAndroid Build Coastguard Worker 650*2f2c4c7aSAndroid Build Coastguard Worker def SendRIO(self, rtlifetime, plen, prefix, prf): 651*2f2c4c7aSAndroid Build Coastguard Worker options = scapy.ICMPv6NDOptRouteInfo(rtlifetime=rtlifetime, plen=plen, 652*2f2c4c7aSAndroid Build Coastguard Worker prefix=prefix, prf=prf) 653*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID, options=(options,)) 654*2f2c4c7aSAndroid Build Coastguard Worker 655*2f2c4c7aSAndroid Build Coastguard Worker def FindRoutesWithDestination(self, destination): 656*2f2c4c7aSAndroid Build Coastguard Worker canonical = net_test.CanonicalizeIPv6Address(destination) 657*2f2c4c7aSAndroid Build Coastguard Worker return [r for _, r in self.iproute.DumpRoutes(6, self.GetRoutingTable()) 658*2f2c4c7aSAndroid Build Coastguard Worker if ('RTA_DST' in r and r['RTA_DST'] == canonical)] 659*2f2c4c7aSAndroid Build Coastguard Worker 660*2f2c4c7aSAndroid Build Coastguard Worker def FindRoutesWithGateway(self): 661*2f2c4c7aSAndroid Build Coastguard Worker return [r for _, r in self.iproute.DumpRoutes(6, self.GetRoutingTable()) 662*2f2c4c7aSAndroid Build Coastguard Worker if 'RTA_GATEWAY' in r] 663*2f2c4c7aSAndroid Build Coastguard Worker 664*2f2c4c7aSAndroid Build Coastguard Worker def CountRoutes(self): 665*2f2c4c7aSAndroid Build Coastguard Worker return len(self.iproute.DumpRoutes(6, self.GetRoutingTable())) 666*2f2c4c7aSAndroid Build Coastguard Worker 667*2f2c4c7aSAndroid Build Coastguard Worker def GetRouteExpiration(self, route): 668*2f2c4c7aSAndroid Build Coastguard Worker return float(route['RTA_CACHEINFO'].expires) / 100.0 669*2f2c4c7aSAndroid Build Coastguard Worker 670*2f2c4c7aSAndroid Build Coastguard Worker def AssertExpirationInRange(self, routes, lifetime, epsilon): 671*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(routes) 672*2f2c4c7aSAndroid Build Coastguard Worker found = False 673*2f2c4c7aSAndroid Build Coastguard Worker # Assert that at least one route in routes has the expected lifetime 674*2f2c4c7aSAndroid Build Coastguard Worker for route in routes: 675*2f2c4c7aSAndroid Build Coastguard Worker expiration = self.GetRouteExpiration(route) 676*2f2c4c7aSAndroid Build Coastguard Worker if expiration < lifetime - epsilon: 677*2f2c4c7aSAndroid Build Coastguard Worker continue 678*2f2c4c7aSAndroid Build Coastguard Worker if expiration > lifetime + epsilon: 679*2f2c4c7aSAndroid Build Coastguard Worker continue 680*2f2c4c7aSAndroid Build Coastguard Worker found = True 681*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(found) 682*2f2c4c7aSAndroid Build Coastguard Worker 683*2f2c4c7aSAndroid Build Coastguard Worker def DelRA6(self, prefix, plen): 684*2f2c4c7aSAndroid Build Coastguard Worker version = 6 685*2f2c4c7aSAndroid Build Coastguard Worker netid = self.NETID 686*2f2c4c7aSAndroid Build Coastguard Worker table = self._TableForNetid(netid) 687*2f2c4c7aSAndroid Build Coastguard Worker router = self._RouterAddress(netid, version) 688*2f2c4c7aSAndroid Build Coastguard Worker ifindex = self.ifindices[netid] 689*2f2c4c7aSAndroid Build Coastguard Worker self.iproute._Route(version, iproute.RTPROT_RA, iproute.RTM_DELROUTE, 690*2f2c4c7aSAndroid Build Coastguard Worker table, prefix, plen, router, ifindex, None, None) 691*2f2c4c7aSAndroid Build Coastguard Worker 692*2f2c4c7aSAndroid Build Coastguard Worker def testSetAcceptRaRtInfoMinPlen(self): 693*2f2c4c7aSAndroid Build Coastguard Worker for plen in range(-1, 130): 694*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMinPlen(plen) 695*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(plen, self.GetAcceptRaRtInfoMinPlen()) 696*2f2c4c7aSAndroid Build Coastguard Worker 697*2f2c4c7aSAndroid Build Coastguard Worker def testSetAcceptRaRtInfoMaxPlen(self): 698*2f2c4c7aSAndroid Build Coastguard Worker for plen in range(-1, 130): 699*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMaxPlen(plen) 700*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(plen, self.GetAcceptRaRtInfoMaxPlen()) 701*2f2c4c7aSAndroid Build Coastguard Worker 702*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_AUTOCONF_TABLE, 703*2f2c4c7aSAndroid Build Coastguard Worker "need support for per-table autoconf") 704*2f2c4c7aSAndroid Build Coastguard Worker def testZeroRtLifetime(self): 705*2f2c4c7aSAndroid Build Coastguard Worker PREFIX = "2001:db8:8901:2300::" 706*2f2c4c7aSAndroid Build Coastguard Worker RTLIFETIME = 73500 707*2f2c4c7aSAndroid Build Coastguard Worker PLEN = 56 708*2f2c4c7aSAndroid Build Coastguard Worker PRF = 0 709*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMaxPlen(PLEN) 710*2f2c4c7aSAndroid Build Coastguard Worker self.SendRIO(RTLIFETIME, PLEN, PREFIX, PRF) 711*2f2c4c7aSAndroid Build Coastguard Worker # Give the kernel time to notice our RA 712*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.01) 713*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(self.FindRoutesWithDestination(PREFIX)) 714*2f2c4c7aSAndroid Build Coastguard Worker # RIO with rtlifetime = 0 should remove from routing table 715*2f2c4c7aSAndroid Build Coastguard Worker self.SendRIO(0, PLEN, PREFIX, PRF) 716*2f2c4c7aSAndroid Build Coastguard Worker # Give the kernel time to notice our RA 717*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.01) 718*2f2c4c7aSAndroid Build Coastguard Worker self.assertFalse(self.FindRoutesWithDestination(PREFIX)) 719*2f2c4c7aSAndroid Build Coastguard Worker 720*2f2c4c7aSAndroid Build Coastguard Worker def testMinPrefixLenRejection(self): 721*2f2c4c7aSAndroid Build Coastguard Worker PREFIX = "2001:db8:8902:2345::" 722*2f2c4c7aSAndroid Build Coastguard Worker RTLIFETIME = 70372 723*2f2c4c7aSAndroid Build Coastguard Worker PRF = 0 724*2f2c4c7aSAndroid Build Coastguard Worker # sweep from high to low to avoid spurious failures from late arrivals. 725*2f2c4c7aSAndroid Build Coastguard Worker for plen in range(130, 1, -1): 726*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMinPlen(plen) 727*2f2c4c7aSAndroid Build Coastguard Worker # RIO with plen < min_plen should be ignored 728*2f2c4c7aSAndroid Build Coastguard Worker self.SendRIO(RTLIFETIME, plen - 1, PREFIX, PRF) 729*2f2c4c7aSAndroid Build Coastguard Worker # Give the kernel time to notice our RAs 730*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) 731*2f2c4c7aSAndroid Build Coastguard Worker # Expect no routes 732*2f2c4c7aSAndroid Build Coastguard Worker routes = self.FindRoutesWithDestination(PREFIX) 733*2f2c4c7aSAndroid Build Coastguard Worker self.assertFalse(routes) 734*2f2c4c7aSAndroid Build Coastguard Worker 735*2f2c4c7aSAndroid Build Coastguard Worker def testMaxPrefixLenRejection(self): 736*2f2c4c7aSAndroid Build Coastguard Worker PREFIX = "2001:db8:8903:2345::" 737*2f2c4c7aSAndroid Build Coastguard Worker RTLIFETIME = 73078 738*2f2c4c7aSAndroid Build Coastguard Worker PRF = 0 739*2f2c4c7aSAndroid Build Coastguard Worker # sweep from low to high to avoid spurious failures from late arrivals. 740*2f2c4c7aSAndroid Build Coastguard Worker for plen in range(-1, 128, 1): 741*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMaxPlen(plen) 742*2f2c4c7aSAndroid Build Coastguard Worker # RIO with plen > max_plen should be ignored 743*2f2c4c7aSAndroid Build Coastguard Worker self.SendRIO(RTLIFETIME, plen + 1, PREFIX, PRF) 744*2f2c4c7aSAndroid Build Coastguard Worker # Give the kernel time to notice our RAs 745*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) 746*2f2c4c7aSAndroid Build Coastguard Worker # Expect no routes 747*2f2c4c7aSAndroid Build Coastguard Worker routes = self.FindRoutesWithDestination(PREFIX) 748*2f2c4c7aSAndroid Build Coastguard Worker self.assertFalse(routes) 749*2f2c4c7aSAndroid Build Coastguard Worker 750*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_AUTOCONF_TABLE, 751*2f2c4c7aSAndroid Build Coastguard Worker "need support for per-table autoconf") 752*2f2c4c7aSAndroid Build Coastguard Worker def testSimpleAccept(self): 753*2f2c4c7aSAndroid Build Coastguard Worker PREFIX = "2001:db8:8904:2345::" 754*2f2c4c7aSAndroid Build Coastguard Worker RTLIFETIME = 9993 755*2f2c4c7aSAndroid Build Coastguard Worker PRF = 0 756*2f2c4c7aSAndroid Build Coastguard Worker PLEN = 56 757*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMinPlen(48) 758*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMaxPlen(64) 759*2f2c4c7aSAndroid Build Coastguard Worker self.SendRIO(RTLIFETIME, PLEN, PREFIX, PRF) 760*2f2c4c7aSAndroid Build Coastguard Worker # Give the kernel time to notice our RA 761*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.01) 762*2f2c4c7aSAndroid Build Coastguard Worker routes = self.FindRoutesWithGateway() 763*2f2c4c7aSAndroid Build Coastguard Worker self.AssertExpirationInRange(routes, RTLIFETIME, 1) 764*2f2c4c7aSAndroid Build Coastguard Worker self.DelRA6(PREFIX, PLEN) 765*2f2c4c7aSAndroid Build Coastguard Worker 766*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_AUTOCONF_TABLE, 767*2f2c4c7aSAndroid Build Coastguard Worker "need support for per-table autoconf") 768*2f2c4c7aSAndroid Build Coastguard Worker def testEqualMinMaxAccept(self): 769*2f2c4c7aSAndroid Build Coastguard Worker PREFIX = "2001:db8:8905:2345::" 770*2f2c4c7aSAndroid Build Coastguard Worker RTLIFETIME = 6326 771*2f2c4c7aSAndroid Build Coastguard Worker PLEN = 21 772*2f2c4c7aSAndroid Build Coastguard Worker PRF = 0 773*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMinPlen(PLEN) 774*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMaxPlen(PLEN) 775*2f2c4c7aSAndroid Build Coastguard Worker self.SendRIO(RTLIFETIME, PLEN, PREFIX, PRF) 776*2f2c4c7aSAndroid Build Coastguard Worker # Give the kernel time to notice our RA 777*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.01) 778*2f2c4c7aSAndroid Build Coastguard Worker routes = self.FindRoutesWithGateway() 779*2f2c4c7aSAndroid Build Coastguard Worker self.AssertExpirationInRange(routes, RTLIFETIME, 1) 780*2f2c4c7aSAndroid Build Coastguard Worker self.DelRA6(PREFIX, PLEN) 781*2f2c4c7aSAndroid Build Coastguard Worker 782*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_AUTOCONF_TABLE, 783*2f2c4c7aSAndroid Build Coastguard Worker "need support for per-table autoconf") 784*2f2c4c7aSAndroid Build Coastguard Worker def testZeroLengthPrefix(self): 785*2f2c4c7aSAndroid Build Coastguard Worker PREFIX = "2001:db8:8906:2345::" 786*2f2c4c7aSAndroid Build Coastguard Worker RTLIFETIME = self.RA_VALIDITY * 2 787*2f2c4c7aSAndroid Build Coastguard Worker PLEN = 0 788*2f2c4c7aSAndroid Build Coastguard Worker PRF = 0 789*2f2c4c7aSAndroid Build Coastguard Worker # Max plen = 0 still allows default RIOs! 790*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMaxPlen(PLEN) 791*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID) 792*2f2c4c7aSAndroid Build Coastguard Worker # Give the kernel time to notice our RA 793*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.01) 794*2f2c4c7aSAndroid Build Coastguard Worker default = self.FindRoutesWithGateway() 795*2f2c4c7aSAndroid Build Coastguard Worker self.AssertExpirationInRange(default, self.RA_VALIDITY, 1) 796*2f2c4c7aSAndroid Build Coastguard Worker # RIO with prefix length = 0, should overwrite default route lifetime 797*2f2c4c7aSAndroid Build Coastguard Worker # note that the RIO lifetime overwrites the RA lifetime. 798*2f2c4c7aSAndroid Build Coastguard Worker self.SendRIO(RTLIFETIME, PLEN, PREFIX, PRF) 799*2f2c4c7aSAndroid Build Coastguard Worker # Give the kernel time to notice our RA 800*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.01) 801*2f2c4c7aSAndroid Build Coastguard Worker default = self.FindRoutesWithGateway() 802*2f2c4c7aSAndroid Build Coastguard Worker self.AssertExpirationInRange(default, RTLIFETIME, 1) 803*2f2c4c7aSAndroid Build Coastguard Worker self.DelRA6(PREFIX, PLEN) 804*2f2c4c7aSAndroid Build Coastguard Worker 805*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_AUTOCONF_TABLE, 806*2f2c4c7aSAndroid Build Coastguard Worker "need support for per-table autoconf") 807*2f2c4c7aSAndroid Build Coastguard Worker def testManyRIOs(self): 808*2f2c4c7aSAndroid Build Coastguard Worker RTLIFETIME = 68012 809*2f2c4c7aSAndroid Build Coastguard Worker PLEN = 56 810*2f2c4c7aSAndroid Build Coastguard Worker PRF = 0 811*2f2c4c7aSAndroid Build Coastguard Worker COUNT = 1000 812*2f2c4c7aSAndroid Build Coastguard Worker baseline = self.CountRoutes() 813*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMaxPlen(56) 814*2f2c4c7aSAndroid Build Coastguard Worker # Send many RIOs compared to the expected number on a healthy system. 815*2f2c4c7aSAndroid Build Coastguard Worker for i in range(0, COUNT): 816*2f2c4c7aSAndroid Build Coastguard Worker prefix = "2001:db8:%x:1100::" % i 817*2f2c4c7aSAndroid Build Coastguard Worker self.SendRIO(RTLIFETIME, PLEN, prefix, PRF) 818*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) 819*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(COUNT + baseline, self.CountRoutes()) 820*2f2c4c7aSAndroid Build Coastguard Worker for i in range(0, COUNT): 821*2f2c4c7aSAndroid Build Coastguard Worker prefix = "2001:db8:%x:1100::" % i 822*2f2c4c7aSAndroid Build Coastguard Worker self.DelRA6(prefix, PLEN) 823*2f2c4c7aSAndroid Build Coastguard Worker # Expect that we can return to baseline config without lingering routes. 824*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(baseline, self.CountRoutes()) 825*2f2c4c7aSAndroid Build Coastguard Worker 826*2f2c4c7aSAndroid Build Coastguard Worker # Contextually, testAcceptRa tests do not belong in RIOTest, but as it 827*2f2c4c7aSAndroid Build Coastguard Worker # turns out, RIOTest has all the useful helpers defined for these tests. 828*2f2c4c7aSAndroid Build Coastguard Worker # TODO: Rename test class or merge RIOTest with RATest. 829*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_ACCEPT_RA_MIN_LFT, 830*2f2c4c7aSAndroid Build Coastguard Worker "need support for accept_ra_min_lft") 831*2f2c4c7aSAndroid Build Coastguard Worker def testAcceptRaMinLftReadWrite(self): 832*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaMinLft(500) 833*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(500, self.GetAcceptRaMinLft()) 834*2f2c4c7aSAndroid Build Coastguard Worker 835*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_RA_HONOR_PIO_LIFE, 836*2f2c4c7aSAndroid Build Coastguard Worker "need support for ra_honor_pio_life") 837*2f2c4c7aSAndroid Build Coastguard Worker def testRaHonorPioLifeReadWrite(self): 838*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(0, self.GetRaHonorPioLife()) 839*2f2c4c7aSAndroid Build Coastguard Worker self.SetRaHonorPioLife(1) 840*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(1, self.GetRaHonorPioLife()) 841*2f2c4c7aSAndroid Build Coastguard Worker 842*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_RA_HONOR_PIO_LIFE, 843*2f2c4c7aSAndroid Build Coastguard Worker "need support for ra_honor_pio_life") 844*2f2c4c7aSAndroid Build Coastguard Worker def testRaHonorPioLife(self): 845*2f2c4c7aSAndroid Build Coastguard Worker self.SetRaHonorPioLife(1) 846*2f2c4c7aSAndroid Build Coastguard Worker 847*2f2c4c7aSAndroid Build Coastguard Worker # Test setup has sent an initial RA -- expire it. 848*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID, routerlft=0, piolft=0) 849*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 850*2f2c4c7aSAndroid Build Coastguard Worker 851*2f2c4c7aSAndroid Build Coastguard Worker # Assert that the address was deleted. 852*2f2c4c7aSAndroid Build Coastguard Worker self.assertIsNone(self.MyAddress(6, self.NETID)) 853*2f2c4c7aSAndroid Build Coastguard Worker 854*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_ACCEPT_RA_MIN_LFT, 855*2f2c4c7aSAndroid Build Coastguard Worker "need support for accept_ra_min_lft") 856*2f2c4c7aSAndroid Build Coastguard Worker def testAcceptRaMinLftRouterLifetime(self): 857*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaMinLft(500) 858*2f2c4c7aSAndroid Build Coastguard Worker 859*2f2c4c7aSAndroid Build Coastguard Worker # Test setup has sent an initial RA. Expire it and test that the RA with 860*2f2c4c7aSAndroid Build Coastguard Worker # lifetime 0 deletes the default route. 861*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID, routerlft=0, piolft=0) 862*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 863*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual([], self.FindRoutesWithGateway()) 864*2f2c4c7aSAndroid Build Coastguard Worker 865*2f2c4c7aSAndroid Build Coastguard Worker # RA with lifetime 400 is ignored 866*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID, routerlft=400) 867*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 868*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual([], self.FindRoutesWithGateway()) 869*2f2c4c7aSAndroid Build Coastguard Worker 870*2f2c4c7aSAndroid Build Coastguard Worker # RA with lifetime 600 is processed 871*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID, routerlft=600) 872*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 873*2f2c4c7aSAndroid Build Coastguard Worker # SendRA sets routerlft to 0 if HAVE_AUTOCONF_TABLE is false... 874*2f2c4c7aSAndroid Build Coastguard Worker # TODO: Fix this correctly. 875*2f2c4c7aSAndroid Build Coastguard Worker if multinetwork_base.HAVE_AUTOCONF_TABLE: 876*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(1, len(self.FindRoutesWithGateway())) 877*2f2c4c7aSAndroid Build Coastguard Worker 878*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_ACCEPT_RA_MIN_LFT, 879*2f2c4c7aSAndroid Build Coastguard Worker "need support for accept_ra_min_lft") 880*2f2c4c7aSAndroid Build Coastguard Worker def testAcceptRaMinLftPIOLifetime(self): 881*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaMinLft(500) 882*2f2c4c7aSAndroid Build Coastguard Worker 883*2f2c4c7aSAndroid Build Coastguard Worker # Test setup has sent an initial RA -- expire it. 884*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID, routerlft=0, piolft=0) 885*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 886*2f2c4c7aSAndroid Build Coastguard Worker # Check that the prefix route was deleted. 887*2f2c4c7aSAndroid Build Coastguard Worker prefixroutes = self.FindRoutesWithDestination(self.OnlinkPrefix(6, self.NETID)) 888*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual([], prefixroutes) 889*2f2c4c7aSAndroid Build Coastguard Worker 890*2f2c4c7aSAndroid Build Coastguard Worker # Sending a 0-lifetime PIO does not cause the address to be deleted, see 891*2f2c4c7aSAndroid Build Coastguard Worker # rfc2462#section-5.5.3. 892*2f2c4c7aSAndroid Build Coastguard Worker address = self.MyAddress(6, self.NETID) 893*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.DelAddress(address, 64, self.ifindices[self.NETID]) 894*2f2c4c7aSAndroid Build Coastguard Worker 895*2f2c4c7aSAndroid Build Coastguard Worker # PIO with lifetime 400 is ignored 896*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID, piolft=400) 897*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 898*2f2c4c7aSAndroid Build Coastguard Worker self.assertIsNone(self.MyAddress(6, self.NETID)) 899*2f2c4c7aSAndroid Build Coastguard Worker 900*2f2c4c7aSAndroid Build Coastguard Worker # PIO with lifetime 600 is processed 901*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID, piolft=600) 902*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 903*2f2c4c7aSAndroid Build Coastguard Worker self.assertIsNotNone(self.MyAddress(6, self.NETID)) 904*2f2c4c7aSAndroid Build Coastguard Worker 905*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_ACCEPT_RA_MIN_LFT, 906*2f2c4c7aSAndroid Build Coastguard Worker "need support for accept_ra_min_lft") 907*2f2c4c7aSAndroid Build Coastguard Worker def testAcceptRaMinLftRIOLifetime(self): 908*2f2c4c7aSAndroid Build Coastguard Worker PREFIX = "2001:db8:8901:2300::" 909*2f2c4c7aSAndroid Build Coastguard Worker PLEN = 64 910*2f2c4c7aSAndroid Build Coastguard Worker PRF = 0 911*2f2c4c7aSAndroid Build Coastguard Worker 912*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaRtInfoMaxPlen(PLEN) 913*2f2c4c7aSAndroid Build Coastguard Worker self.SetAcceptRaMinLft(500) 914*2f2c4c7aSAndroid Build Coastguard Worker 915*2f2c4c7aSAndroid Build Coastguard Worker # RIO with lifetime 400 is ignored 916*2f2c4c7aSAndroid Build Coastguard Worker self.SendRIO(400, PLEN, PREFIX, PRF) 917*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 918*2f2c4c7aSAndroid Build Coastguard Worker self.assertFalse(self.FindRoutesWithDestination(PREFIX)) 919*2f2c4c7aSAndroid Build Coastguard Worker 920*2f2c4c7aSAndroid Build Coastguard Worker # RIO with lifetime 600 is processed 921*2f2c4c7aSAndroid Build Coastguard Worker self.SendRIO(600, PLEN, PREFIX, PRF) 922*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 923*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(self.FindRoutesWithDestination(PREFIX)) 924*2f2c4c7aSAndroid Build Coastguard Worker 925*2f2c4c7aSAndroid Build Coastguard Worker # RIO with lifetime 0 deletes the route 926*2f2c4c7aSAndroid Build Coastguard Worker self.SendRIO(0, PLEN, PREFIX, PRF) 927*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 928*2f2c4c7aSAndroid Build Coastguard Worker self.assertFalse(self.FindRoutesWithDestination(PREFIX)) 929*2f2c4c7aSAndroid Build Coastguard Worker 930*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_RA_HONOR_PIO_PFLAG, 931*2f2c4c7aSAndroid Build Coastguard Worker "needs support for ra_honor_pio_pflag") 932*2f2c4c7aSAndroid Build Coastguard Worker def testPioPflag(self): 933*2f2c4c7aSAndroid Build Coastguard Worker self.SetRaHonorPioPflag(1); 934*2f2c4c7aSAndroid Build Coastguard Worker 935*2f2c4c7aSAndroid Build Coastguard Worker # Test setup has sent an initial RA -- expire it. 936*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID, routerlft=0, piolft=0) 937*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 938*2f2c4c7aSAndroid Build Coastguard Worker # Check that the prefix route was deleted. 939*2f2c4c7aSAndroid Build Coastguard Worker prefixroutes = self.FindRoutesWithDestination(self.OnlinkPrefix(6, self.NETID)) 940*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual([], prefixroutes) 941*2f2c4c7aSAndroid Build Coastguard Worker 942*2f2c4c7aSAndroid Build Coastguard Worker # Sending a 0-lifetime PIO does not cause the address to be deleted, see 943*2f2c4c7aSAndroid Build Coastguard Worker # rfc2462#section-5.5.3. 944*2f2c4c7aSAndroid Build Coastguard Worker address = self.MyAddress(6, self.NETID) 945*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.DelAddress(address, 64, self.ifindices[self.NETID]) 946*2f2c4c7aSAndroid Build Coastguard Worker 947*2f2c4c7aSAndroid Build Coastguard Worker # PIO with p-flag is ignored 948*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID, piopflag=1) 949*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 950*2f2c4c7aSAndroid Build Coastguard Worker self.assertIsNone(self.MyAddress(6, self.NETID)) 951*2f2c4c7aSAndroid Build Coastguard Worker 952*2f2c4c7aSAndroid Build Coastguard Worker self.SetRaHonorPioPflag(0); 953*2f2c4c7aSAndroid Build Coastguard Worker # PIO with p-flag is processed 954*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID, piopflag=1) 955*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) # Give the kernel time to notice our RA 956*2f2c4c7aSAndroid Build Coastguard Worker self.assertIsNotNone(self.MyAddress(6, self.NETID)) 957*2f2c4c7aSAndroid Build Coastguard Worker 958*2f2c4c7aSAndroid Build Coastguard Worker 959*2f2c4c7aSAndroid Build Coastguard Workerclass RATest(multinetwork_base.MultiNetworkBaseTest): 960*2f2c4c7aSAndroid Build Coastguard Worker 961*2f2c4c7aSAndroid Build Coastguard Worker ND_ROUTER_ADVERT = 134 962*2f2c4c7aSAndroid Build Coastguard Worker ND_OPT_PIO = 3 963*2f2c4c7aSAndroid Build Coastguard Worker ND_OPT_PREF64 = 38 964*2f2c4c7aSAndroid Build Coastguard Worker NDOptHeader = cstruct.Struct("ndopt_header", "!BB", "type length") 965*2f2c4c7aSAndroid Build Coastguard Worker Pref64Option = cstruct.Struct("pref64_option", "!BBH12s", 966*2f2c4c7aSAndroid Build Coastguard Worker "type length lft_plc prefix") 967*2f2c4c7aSAndroid Build Coastguard Worker 968*2f2c4c7aSAndroid Build Coastguard Worker # Android Common Kernels are always based off of an LTS release, 969*2f2c4c7aSAndroid Build Coastguard Worker # skipping this (always failing due to lack of an ACK specific patch) test 970*2f2c4c7aSAndroid Build Coastguard Worker # on Linus's kernels (and various other upstream dev branches) allows 971*2f2c4c7aSAndroid Build Coastguard Worker # for easier testing of Linux rc's and various developer trees. 972*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(net_test.IS_STABLE, "not STABLE/LTS kernel") 973*2f2c4c7aSAndroid Build Coastguard Worker def testHasAutoconfTable(self): 974*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(multinetwork_base.HAVE_AUTOCONF_TABLE) 975*2f2c4c7aSAndroid Build Coastguard Worker 976*2f2c4c7aSAndroid Build Coastguard Worker def testDoesNotHaveObsoleteSysctl(self): 977*2f2c4c7aSAndroid Build Coastguard Worker self.assertFalse(os.path.isfile( 978*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/ipv6/route/autoconf_table_offset")) 979*2f2c4c7aSAndroid Build Coastguard Worker 980*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_AUTOCONF_TABLE, 981*2f2c4c7aSAndroid Build Coastguard Worker "no support for per-table autoconf") 982*2f2c4c7aSAndroid Build Coastguard Worker def testPurgeDefaultRouters(self): 983*2f2c4c7aSAndroid Build Coastguard Worker 984*2f2c4c7aSAndroid Build Coastguard Worker def CheckIPv6Connectivity(expect_connectivity): 985*2f2c4c7aSAndroid Build Coastguard Worker for netid in self.NETIDS: 986*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.UDPSocket(AF_INET6) 987*2f2c4c7aSAndroid Build Coastguard Worker self.SetSocketMark(s, netid) 988*2f2c4c7aSAndroid Build Coastguard Worker if expect_connectivity: 989*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(s.sendto(UDP_PAYLOAD, (net_test.IPV6_ADDR, 1234))) 990*2f2c4c7aSAndroid Build Coastguard Worker else: 991*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.ENETUNREACH, s.sendto, UDP_PAYLOAD, 992*2f2c4c7aSAndroid Build Coastguard Worker (net_test.IPV6_ADDR, 1234)) 993*2f2c4c7aSAndroid Build Coastguard Worker s.close() 994*2f2c4c7aSAndroid Build Coastguard Worker 995*2f2c4c7aSAndroid Build Coastguard Worker try: 996*2f2c4c7aSAndroid Build Coastguard Worker CheckIPv6Connectivity(True) 997*2f2c4c7aSAndroid Build Coastguard Worker self.SetIPv6SysctlOnAllIfaces("accept_ra", 1) 998*2f2c4c7aSAndroid Build Coastguard Worker self.SetSysctl("/proc/sys/net/ipv6/conf/all/forwarding", 1) 999*2f2c4c7aSAndroid Build Coastguard Worker CheckIPv6Connectivity(False) 1000*2f2c4c7aSAndroid Build Coastguard Worker finally: 1001*2f2c4c7aSAndroid Build Coastguard Worker self.SetSysctl("/proc/sys/net/ipv6/conf/all/forwarding", 0) 1002*2f2c4c7aSAndroid Build Coastguard Worker for netid in self.NETIDS: 1003*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(netid) 1004*2f2c4c7aSAndroid Build Coastguard Worker CheckIPv6Connectivity(True) 1005*2f2c4c7aSAndroid Build Coastguard Worker 1006*2f2c4c7aSAndroid Build Coastguard Worker def testOnlinkCommunication(self): 1007*2f2c4c7aSAndroid Build Coastguard Worker """Checks that on-link communication goes direct and not through routers.""" 1008*2f2c4c7aSAndroid Build Coastguard Worker for netid in self.tuns: 1009*2f2c4c7aSAndroid Build Coastguard Worker # Send a UDP packet to a random on-link destination. 1010*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.UDPSocket(AF_INET6) 1011*2f2c4c7aSAndroid Build Coastguard Worker iface = self.GetInterfaceName(netid) 1012*2f2c4c7aSAndroid Build Coastguard Worker self.BindToDevice(s, iface) 1013*2f2c4c7aSAndroid Build Coastguard Worker # dstaddr can never be our address because GetRandomDestination only fills 1014*2f2c4c7aSAndroid Build Coastguard Worker # in the lower 32 bits, but our address has 0xff in the byte before that 1015*2f2c4c7aSAndroid Build Coastguard Worker # (since it's constructed from the EUI-64 and so has ff:fe in the middle). 1016*2f2c4c7aSAndroid Build Coastguard Worker dstaddr = self.GetRandomDestination(self.OnlinkPrefix(6, netid)) 1017*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(UDP_PAYLOAD, (dstaddr, 53)) 1018*2f2c4c7aSAndroid Build Coastguard Worker 1019*2f2c4c7aSAndroid Build Coastguard Worker # Expect an NS for that destination on the interface. 1020*2f2c4c7aSAndroid Build Coastguard Worker myaddr = self.MyAddress(6, netid) 1021*2f2c4c7aSAndroid Build Coastguard Worker mymac = self.MyMacAddress(netid) 1022*2f2c4c7aSAndroid Build Coastguard Worker desc, expected = packets.NS(myaddr, dstaddr, mymac) 1023*2f2c4c7aSAndroid Build Coastguard Worker msg = "Sending UDP packet to on-link destination: expecting %s" % desc 1024*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.0001) # Required to make the test work on kernel 3.1(!) 1025*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg, expected) 1026*2f2c4c7aSAndroid Build Coastguard Worker 1027*2f2c4c7aSAndroid Build Coastguard Worker # Send an NA. 1028*2f2c4c7aSAndroid Build Coastguard Worker tgtmac = "02:00:00:00:%02x:99" % netid 1029*2f2c4c7aSAndroid Build Coastguard Worker _, reply = packets.NA(dstaddr, myaddr, tgtmac) 1030*2f2c4c7aSAndroid Build Coastguard Worker # Don't use ReceivePacketOn, since that uses the router's MAC address as 1031*2f2c4c7aSAndroid Build Coastguard Worker # the source. Instead, construct our own Ethernet header with source 1032*2f2c4c7aSAndroid Build Coastguard Worker # MAC of tgtmac. 1033*2f2c4c7aSAndroid Build Coastguard Worker reply = scapy.Ether(src=tgtmac, dst=mymac) / reply 1034*2f2c4c7aSAndroid Build Coastguard Worker self.ReceiveEtherPacketOn(netid, reply) 1035*2f2c4c7aSAndroid Build Coastguard Worker 1036*2f2c4c7aSAndroid Build Coastguard Worker # Expect the kernel to send the original UDP packet now that the ND cache 1037*2f2c4c7aSAndroid Build Coastguard Worker # entry has been populated. 1038*2f2c4c7aSAndroid Build Coastguard Worker sport = s.getsockname()[1] 1039*2f2c4c7aSAndroid Build Coastguard Worker desc, expected = packets.UDP(6, myaddr, dstaddr, sport=sport) 1040*2f2c4c7aSAndroid Build Coastguard Worker msg = "After NA response, expecting %s" % desc 1041*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg, expected) 1042*2f2c4c7aSAndroid Build Coastguard Worker 1043*2f2c4c7aSAndroid Build Coastguard Worker s.close() 1044*2f2c4c7aSAndroid Build Coastguard Worker 1045*2f2c4c7aSAndroid Build Coastguard Worker # This test documents a known issue: routing tables are never deleted. 1046*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(multinetwork_base.HAVE_AUTOCONF_TABLE, 1047*2f2c4c7aSAndroid Build Coastguard Worker "no support for per-table autoconf") 1048*2f2c4c7aSAndroid Build Coastguard Worker def testLeftoverRoutes(self): 1049*2f2c4c7aSAndroid Build Coastguard Worker def GetNumRoutes(): 1050*2f2c4c7aSAndroid Build Coastguard Worker with open("/proc/net/ipv6_route") as ipv6_route: 1051*2f2c4c7aSAndroid Build Coastguard Worker return len(ipv6_route.readlines()) 1052*2f2c4c7aSAndroid Build Coastguard Worker 1053*2f2c4c7aSAndroid Build Coastguard Worker num_routes = GetNumRoutes() 1054*2f2c4c7aSAndroid Build Coastguard Worker for i in range(10, 20): 1055*2f2c4c7aSAndroid Build Coastguard Worker try: 1056*2f2c4c7aSAndroid Build Coastguard Worker self.tuns[i] = self.CreateTunInterface(i) 1057*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(i) 1058*2f2c4c7aSAndroid Build Coastguard Worker self.tuns[i].close() 1059*2f2c4c7aSAndroid Build Coastguard Worker finally: 1060*2f2c4c7aSAndroid Build Coastguard Worker del self.tuns[i] 1061*2f2c4c7aSAndroid Build Coastguard Worker self.assertLess(num_routes, GetNumRoutes()) 1062*2f2c4c7aSAndroid Build Coastguard Worker 1063*2f2c4c7aSAndroid Build Coastguard Worker def SendNdUseropt(self, option): 1064*2f2c4c7aSAndroid Build Coastguard Worker options = scapy.ICMPv6NDOptRouteInfo(rtlifetime=rtlifetime, plen=plen, 1065*2f2c4c7aSAndroid Build Coastguard Worker prefix=prefix, prf=prf) 1066*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(self.NETID, options=(options,)) 1067*2f2c4c7aSAndroid Build Coastguard Worker 1068*2f2c4c7aSAndroid Build Coastguard Worker def MakePref64Option(self, prefix, lifetime): 1069*2f2c4c7aSAndroid Build Coastguard Worker prefix = inet_pton(AF_INET6, prefix)[:12] 1070*2f2c4c7aSAndroid Build Coastguard Worker lft_plc = (lifetime & 0xfff8) | 0 # 96-bit prefix length 1071*2f2c4c7aSAndroid Build Coastguard Worker return self.Pref64Option((self.ND_OPT_PREF64, 2, lft_plc, prefix)) 1072*2f2c4c7aSAndroid Build Coastguard Worker 1073*2f2c4c7aSAndroid Build Coastguard Worker def testPref64UserOption(self): 1074*2f2c4c7aSAndroid Build Coastguard Worker # Open a netlink socket to receive RTM_NEWNDUSEROPT messages. 1075*2f2c4c7aSAndroid Build Coastguard Worker s = netlink.NetlinkSocket(netlink.NETLINK_ROUTE, iproute.RTMGRP_ND_USEROPT) 1076*2f2c4c7aSAndroid Build Coastguard Worker 1077*2f2c4c7aSAndroid Build Coastguard Worker # Send an RA with the PREF64 option. 1078*2f2c4c7aSAndroid Build Coastguard Worker netid = random.choice(self.NETIDS) 1079*2f2c4c7aSAndroid Build Coastguard Worker opt = self.MakePref64Option("64:ff9b::", 300) 1080*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(netid, options=(opt.Pack(),)) 1081*2f2c4c7aSAndroid Build Coastguard Worker 1082*2f2c4c7aSAndroid Build Coastguard Worker # Check that we get an an RTM_NEWNDUSEROPT message on the socket with the 1083*2f2c4c7aSAndroid Build Coastguard Worker # expected option. 1084*2f2c4c7aSAndroid Build Coastguard Worker csocket.SetSocketTimeout(s.sock, 100) 1085*2f2c4c7aSAndroid Build Coastguard Worker 1086*2f2c4c7aSAndroid Build Coastguard Worker needPIO = multinetwork_base.HAVE_USEROPT_PIO_FIX 1087*2f2c4c7aSAndroid Build Coastguard Worker needPref64 = True 1088*2f2c4c7aSAndroid Build Coastguard Worker 1089*2f2c4c7aSAndroid Build Coastguard Worker while needPIO or needPref64: 1090*2f2c4c7aSAndroid Build Coastguard Worker try: 1091*2f2c4c7aSAndroid Build Coastguard Worker data = s._Recv() 1092*2f2c4c7aSAndroid Build Coastguard Worker except IOError as e: 1093*2f2c4c7aSAndroid Build Coastguard Worker self.fail("Should have received an RTM_NEWNDUSEROPT message. " 1094*2f2c4c7aSAndroid Build Coastguard Worker "Please ensure the kernel supports receiving the " 1095*2f2c4c7aSAndroid Build Coastguard Worker "PREF64 RA option. Error: %s" % e) 1096*2f2c4c7aSAndroid Build Coastguard Worker # Check that the message is received correctly. 1097*2f2c4c7aSAndroid Build Coastguard Worker nlmsghdr, data = cstruct.Read(data, netlink.NLMsgHdr) 1098*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(iproute.RTM_NEWNDUSEROPT, nlmsghdr.type) 1099*2f2c4c7aSAndroid Build Coastguard Worker 1100*2f2c4c7aSAndroid Build Coastguard Worker # print("data=[%s]\n" % data) 1101*2f2c4c7aSAndroid Build Coastguard Worker 1102*2f2c4c7aSAndroid Build Coastguard Worker # Check the option contents. 1103*2f2c4c7aSAndroid Build Coastguard Worker ndopthdr, data = cstruct.Read(data, iproute.NdUseroptMsg) 1104*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(AF_INET6, ndopthdr.family) 1105*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(self.ND_ROUTER_ADVERT, ndopthdr.icmp_type) 1106*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(0, ndopthdr.icmp_code) 1107*2f2c4c7aSAndroid Build Coastguard Worker 1108*2f2c4c7aSAndroid Build Coastguard Worker self.assertLessEqual(ndopthdr.opts_len, len(data)) 1109*2f2c4c7aSAndroid Build Coastguard Worker data, leftover = data[:ndopthdr.opts_len], data[ndopthdr.opts_len:] 1110*2f2c4c7aSAndroid Build Coastguard Worker 1111*2f2c4c7aSAndroid Build Coastguard Worker # print("ndopthdr=[%s] data=[%s] leftover=[%s]" % (ndopthdr, data, leftover)) 1112*2f2c4c7aSAndroid Build Coastguard Worker 1113*2f2c4c7aSAndroid Build Coastguard Worker while data: 1114*2f2c4c7aSAndroid Build Coastguard Worker # print("data2=[%s]\n" % data) 1115*2f2c4c7aSAndroid Build Coastguard Worker 1116*2f2c4c7aSAndroid Build Coastguard Worker header_opt = self.NDOptHeader(data) 1117*2f2c4c7aSAndroid Build Coastguard Worker self.assertNotEqual(header_opt.length, 0) 1118*2f2c4c7aSAndroid Build Coastguard Worker self.assertLessEqual(header_opt.length * 8, len(data)) 1119*2f2c4c7aSAndroid Build Coastguard Worker payload, data = data[:header_opt.length * 8], data[header_opt.length * 8:] 1120*2f2c4c7aSAndroid Build Coastguard Worker 1121*2f2c4c7aSAndroid Build Coastguard Worker # print("type=%d len=%d payload[%s]\n" % (header_opt.type, header_opt.length * 8, payload)) 1122*2f2c4c7aSAndroid Build Coastguard Worker 1123*2f2c4c7aSAndroid Build Coastguard Worker if header_opt.type == self.ND_OPT_PIO: 1124*2f2c4c7aSAndroid Build Coastguard Worker needPIO = False 1125*2f2c4c7aSAndroid Build Coastguard Worker elif header_opt.type == self.ND_OPT_PREF64: 1126*2f2c4c7aSAndroid Build Coastguard Worker needPref64 = False 1127*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(len(opt), len(payload)) 1128*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(opt, self.Pref64Option(payload)) 1129*2f2c4c7aSAndroid Build Coastguard Worker else: 1130*2f2c4c7aSAndroid Build Coastguard Worker # cannot happen: no other options we generate are currently considered user options 1131*2f2c4c7aSAndroid Build Coastguard Worker assert False 1132*2f2c4c7aSAndroid Build Coastguard Worker 1133*2f2c4c7aSAndroid Build Coastguard Worker # we only ever reach here if we find all options we need 1134*2f2c4c7aSAndroid Build Coastguard Worker s.close() 1135*2f2c4c7aSAndroid Build Coastguard Worker 1136*2f2c4c7aSAndroid Build Coastguard Worker def testRaFlags(self): 1137*2f2c4c7aSAndroid Build Coastguard Worker def GetInterfaceIpv6Flags(iface): 1138*2f2c4c7aSAndroid Build Coastguard Worker attrs = self.iproute.GetIflaAfSpecificData(iface, AF_INET6) 1139*2f2c4c7aSAndroid Build Coastguard Worker return int(attrs["IFLA_INET6_FLAGS"]) 1140*2f2c4c7aSAndroid Build Coastguard Worker 1141*2f2c4c7aSAndroid Build Coastguard Worker netid = random.choice(self.NETIDS) 1142*2f2c4c7aSAndroid Build Coastguard Worker iface = self.GetInterfaceName(netid) 1143*2f2c4c7aSAndroid Build Coastguard Worker expected = iproute.IF_RS_SENT | iproute.IF_RA_RCVD | iproute.IF_READY 1144*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(expected, GetInterfaceIpv6Flags(iface)) 1145*2f2c4c7aSAndroid Build Coastguard Worker 1146*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(netid, m=1, o=0) 1147*2f2c4c7aSAndroid Build Coastguard Worker expected |= iproute.IF_RA_MANAGED 1148*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(expected, GetInterfaceIpv6Flags(iface)) 1149*2f2c4c7aSAndroid Build Coastguard Worker 1150*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(netid, m=1, o=1) 1151*2f2c4c7aSAndroid Build Coastguard Worker expected |= iproute.IF_RA_OTHERCONF 1152*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(expected, GetInterfaceIpv6Flags(iface)) 1153*2f2c4c7aSAndroid Build Coastguard Worker 1154*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(netid, m=0, o=1) 1155*2f2c4c7aSAndroid Build Coastguard Worker expected &= ~iproute.IF_RA_MANAGED 1156*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(expected, GetInterfaceIpv6Flags(iface)) 1157*2f2c4c7aSAndroid Build Coastguard Worker 1158*2f2c4c7aSAndroid Build Coastguard Worker 1159*2f2c4c7aSAndroid Build Coastguard Workerclass PMTUTest(multinetwork_base.InboundMarkingTest): 1160*2f2c4c7aSAndroid Build Coastguard Worker 1161*2f2c4c7aSAndroid Build Coastguard Worker PAYLOAD_SIZE = 1400 1162*2f2c4c7aSAndroid Build Coastguard Worker dstaddrs = set() 1163*2f2c4c7aSAndroid Build Coastguard Worker 1164*2f2c4c7aSAndroid Build Coastguard Worker def GetSocketMTU(self, version, s): 1165*2f2c4c7aSAndroid Build Coastguard Worker if version == 6: 1166*2f2c4c7aSAndroid Build Coastguard Worker ip6_mtuinfo = s.getsockopt(net_test.SOL_IPV6, csocket.IPV6_PATHMTU, 32) 1167*2f2c4c7aSAndroid Build Coastguard Worker unused_sockaddr, mtu = struct.unpack("=28sI", ip6_mtuinfo) 1168*2f2c4c7aSAndroid Build Coastguard Worker return mtu 1169*2f2c4c7aSAndroid Build Coastguard Worker else: 1170*2f2c4c7aSAndroid Build Coastguard Worker return s.getsockopt(net_test.SOL_IP, csocket.IP_MTU) 1171*2f2c4c7aSAndroid Build Coastguard Worker 1172*2f2c4c7aSAndroid Build Coastguard Worker def DisableFragmentationAndReportErrors(self, version, s): 1173*2f2c4c7aSAndroid Build Coastguard Worker if version == 4: 1174*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IP, csocket.IP_MTU_DISCOVER, 1175*2f2c4c7aSAndroid Build Coastguard Worker csocket.IP_PMTUDISC_DO) 1176*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IP, net_test.IP_RECVERR, 1) 1177*2f2c4c7aSAndroid Build Coastguard Worker else: 1178*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, csocket.IPV6_DONTFRAG, 1) 1179*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_RECVERR, 1) 1180*2f2c4c7aSAndroid Build Coastguard Worker 1181*2f2c4c7aSAndroid Build Coastguard Worker def CheckPMTU(self, version, use_connect, modes): 1182*2f2c4c7aSAndroid Build Coastguard Worker 1183*2f2c4c7aSAndroid Build Coastguard Worker def SendBigPacket(version, s, dstaddr, netid, payload): 1184*2f2c4c7aSAndroid Build Coastguard Worker if use_connect: 1185*2f2c4c7aSAndroid Build Coastguard Worker s.send(payload) 1186*2f2c4c7aSAndroid Build Coastguard Worker else: 1187*2f2c4c7aSAndroid Build Coastguard Worker self.SendOnNetid(version, s, dstaddr, 1234, netid, payload, []) 1188*2f2c4c7aSAndroid Build Coastguard Worker 1189*2f2c4c7aSAndroid Build Coastguard Worker for netid in self.tuns: 1190*2f2c4c7aSAndroid Build Coastguard Worker for mode in modes: 1191*2f2c4c7aSAndroid Build Coastguard Worker s = self.BuildSocket(version, net_test.UDPSocket, netid, mode) 1192*2f2c4c7aSAndroid Build Coastguard Worker self.DisableFragmentationAndReportErrors(version, s) 1193*2f2c4c7aSAndroid Build Coastguard Worker 1194*2f2c4c7aSAndroid Build Coastguard Worker srcaddr = self.MyAddress(version, netid) 1195*2f2c4c7aSAndroid Build Coastguard Worker dst_prefix, intermediate = { 1196*2f2c4c7aSAndroid Build Coastguard Worker 4: ("172.19.", "172.16.9.12"), 1197*2f2c4c7aSAndroid Build Coastguard Worker 6: ("2001:db8::", "2001:db8::1") 1198*2f2c4c7aSAndroid Build Coastguard Worker }[version] 1199*2f2c4c7aSAndroid Build Coastguard Worker 1200*2f2c4c7aSAndroid Build Coastguard Worker # Run this test often enough (e.g., in presubmits), and eventually 1201*2f2c4c7aSAndroid Build Coastguard Worker # we'll be unlucky enough to pick the same address twice, in which 1202*2f2c4c7aSAndroid Build Coastguard Worker # case the test will fail because the kernel will already have seen 1203*2f2c4c7aSAndroid Build Coastguard Worker # the lower MTU. Don't do this. 1204*2f2c4c7aSAndroid Build Coastguard Worker dstaddr = self.GetRandomDestination(dst_prefix) 1205*2f2c4c7aSAndroid Build Coastguard Worker while dstaddr in self.dstaddrs: 1206*2f2c4c7aSAndroid Build Coastguard Worker dstaddr = self.GetRandomDestination(dst_prefix) 1207*2f2c4c7aSAndroid Build Coastguard Worker self.dstaddrs.add(dstaddr) 1208*2f2c4c7aSAndroid Build Coastguard Worker 1209*2f2c4c7aSAndroid Build Coastguard Worker if use_connect: 1210*2f2c4c7aSAndroid Build Coastguard Worker s.connect((dstaddr, 1234)) 1211*2f2c4c7aSAndroid Build Coastguard Worker 1212*2f2c4c7aSAndroid Build Coastguard Worker payload = self.PAYLOAD_SIZE * b"a" 1213*2f2c4c7aSAndroid Build Coastguard Worker 1214*2f2c4c7aSAndroid Build Coastguard Worker # Send a packet and receive a packet too big. 1215*2f2c4c7aSAndroid Build Coastguard Worker SendBigPacket(version, s, dstaddr, netid, payload) 1216*2f2c4c7aSAndroid Build Coastguard Worker received = self.ReadAllPacketsOn(netid) 1217*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(1, len(received), 1218*2f2c4c7aSAndroid Build Coastguard Worker "unexpected packets: %s" % received[1:]) 1219*2f2c4c7aSAndroid Build Coastguard Worker _, toobig = packets.ICMPPacketTooBig(version, intermediate, srcaddr, 1220*2f2c4c7aSAndroid Build Coastguard Worker received[0]) 1221*2f2c4c7aSAndroid Build Coastguard Worker self.ReceivePacketOn(netid, toobig) 1222*2f2c4c7aSAndroid Build Coastguard Worker 1223*2f2c4c7aSAndroid Build Coastguard Worker # Check that another send on the same socket returns EMSGSIZE. 1224*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno( 1225*2f2c4c7aSAndroid Build Coastguard Worker errno.EMSGSIZE, 1226*2f2c4c7aSAndroid Build Coastguard Worker SendBigPacket, version, s, dstaddr, netid, payload) 1227*2f2c4c7aSAndroid Build Coastguard Worker 1228*2f2c4c7aSAndroid Build Coastguard Worker # If this is a connected socket, make sure the socket MTU was set. 1229*2f2c4c7aSAndroid Build Coastguard Worker # Note that in IPv4 this only started working in Linux 3.6! 1230*2f2c4c7aSAndroid Build Coastguard Worker if use_connect: 1231*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(packets.PTB_MTU, self.GetSocketMTU(version, s)) 1232*2f2c4c7aSAndroid Build Coastguard Worker 1233*2f2c4c7aSAndroid Build Coastguard Worker s.close() 1234*2f2c4c7aSAndroid Build Coastguard Worker 1235*2f2c4c7aSAndroid Build Coastguard Worker # Check that other sockets pick up the PMTU we have been told about by 1236*2f2c4c7aSAndroid Build Coastguard Worker # connecting another socket to the same destination and getting its MTU. 1237*2f2c4c7aSAndroid Build Coastguard Worker # This new socket can use any method to select its outgoing interface; 1238*2f2c4c7aSAndroid Build Coastguard Worker # here we use a mark for simplicity. 1239*2f2c4c7aSAndroid Build Coastguard Worker s2 = self.BuildSocket(version, net_test.UDPSocket, netid, "mark") 1240*2f2c4c7aSAndroid Build Coastguard Worker s2.connect((dstaddr, 1234)) 1241*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(packets.PTB_MTU, self.GetSocketMTU(version, s2)) 1242*2f2c4c7aSAndroid Build Coastguard Worker 1243*2f2c4c7aSAndroid Build Coastguard Worker # Also check the MTU reported by ip route get, this time using the oif. 1244*2f2c4c7aSAndroid Build Coastguard Worker routes = self.iproute.GetRoutes(dstaddr, self.ifindices[netid], 0, None) 1245*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(routes) 1246*2f2c4c7aSAndroid Build Coastguard Worker route = routes[0] 1247*2f2c4c7aSAndroid Build Coastguard Worker rtmsg, attributes = route 1248*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(iproute.RTN_UNICAST, rtmsg.type) 1249*2f2c4c7aSAndroid Build Coastguard Worker metrics = attributes["RTA_METRICS"] 1250*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(packets.PTB_MTU, metrics["RTAX_MTU"]) 1251*2f2c4c7aSAndroid Build Coastguard Worker 1252*2f2c4c7aSAndroid Build Coastguard Worker s2.close() 1253*2f2c4c7aSAndroid Build Coastguard Worker 1254*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4BasicPMTU(self): 1255*2f2c4c7aSAndroid Build Coastguard Worker """Tests IPv4 path MTU discovery. 1256*2f2c4c7aSAndroid Build Coastguard Worker 1257*2f2c4c7aSAndroid Build Coastguard Worker Relevant kernel commits: 1258*2f2c4c7aSAndroid Build Coastguard Worker upstream net-next: 1259*2f2c4c7aSAndroid Build Coastguard Worker 6a66271 ipv4, fib: pass LOOPBACK_IFINDEX instead of 0 to flowi4_iif 1260*2f2c4c7aSAndroid Build Coastguard Worker 1261*2f2c4c7aSAndroid Build Coastguard Worker android-3.10: 1262*2f2c4c7aSAndroid Build Coastguard Worker 4bc64dd ipv4, fib: pass LOOPBACK_IFINDEX instead of 0 to flowi4_iif 1263*2f2c4c7aSAndroid Build Coastguard Worker """ 1264*2f2c4c7aSAndroid Build Coastguard Worker 1265*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPMTU(4, True, ["mark", "oif"]) 1266*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPMTU(4, False, ["mark", "oif"]) 1267*2f2c4c7aSAndroid Build Coastguard Worker 1268*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6BasicPMTU(self): 1269*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPMTU(6, True, ["mark", "oif"]) 1270*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPMTU(6, False, ["mark", "oif"]) 1271*2f2c4c7aSAndroid Build Coastguard Worker 1272*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4UIDPMTU(self): 1273*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPMTU(4, True, ["uid"]) 1274*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPMTU(4, False, ["uid"]) 1275*2f2c4c7aSAndroid Build Coastguard Worker 1276*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6UIDPMTU(self): 1277*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPMTU(6, True, ["uid"]) 1278*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPMTU(6, False, ["uid"]) 1279*2f2c4c7aSAndroid Build Coastguard Worker 1280*2f2c4c7aSAndroid Build Coastguard Worker # Making Path MTU Discovery work on unmarked sockets requires that mark 1281*2f2c4c7aSAndroid Build Coastguard Worker # reflection be enabled. Otherwise the kernel has no way to know what routing 1282*2f2c4c7aSAndroid Build Coastguard Worker # table the original packet used, and thus it won't be able to clone the 1283*2f2c4c7aSAndroid Build Coastguard Worker # correct route. 1284*2f2c4c7aSAndroid Build Coastguard Worker 1285*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4UnmarkedSocketPMTU(self): 1286*2f2c4c7aSAndroid Build Coastguard Worker self.SetMarkReflectSysctls(1) 1287*2f2c4c7aSAndroid Build Coastguard Worker try: 1288*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPMTU(4, False, [None]) 1289*2f2c4c7aSAndroid Build Coastguard Worker finally: 1290*2f2c4c7aSAndroid Build Coastguard Worker self.SetMarkReflectSysctls(0) 1291*2f2c4c7aSAndroid Build Coastguard Worker 1292*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6UnmarkedSocketPMTU(self): 1293*2f2c4c7aSAndroid Build Coastguard Worker self.SetMarkReflectSysctls(1) 1294*2f2c4c7aSAndroid Build Coastguard Worker try: 1295*2f2c4c7aSAndroid Build Coastguard Worker self.CheckPMTU(6, False, [None]) 1296*2f2c4c7aSAndroid Build Coastguard Worker finally: 1297*2f2c4c7aSAndroid Build Coastguard Worker self.SetMarkReflectSysctls(0) 1298*2f2c4c7aSAndroid Build Coastguard Worker 1299*2f2c4c7aSAndroid Build Coastguard Worker 1300*2f2c4c7aSAndroid Build Coastguard Workerclass UidRoutingTest(multinetwork_base.MultiNetworkBaseTest): 1301*2f2c4c7aSAndroid Build Coastguard Worker """Tests that per-UID routing works properly. 1302*2f2c4c7aSAndroid Build Coastguard Worker 1303*2f2c4c7aSAndroid Build Coastguard Worker Relevant kernel commits: 1304*2f2c4c7aSAndroid Build Coastguard Worker upstream net-next: 1305*2f2c4c7aSAndroid Build Coastguard Worker 7d99569460 net: ipv4: Don't crash if passing a null sk to ip_do_redirect. 1306*2f2c4c7aSAndroid Build Coastguard Worker d109e61bfe net: ipv4: Don't crash if passing a null sk to ip_rt_update_pmtu. 1307*2f2c4c7aSAndroid Build Coastguard Worker 35b80733b3 net: core: add missing check for uid_range in rule_exists. 1308*2f2c4c7aSAndroid Build Coastguard Worker e2d118a1cb net: inet: Support UID-based routing in IP protocols. 1309*2f2c4c7aSAndroid Build Coastguard Worker 622ec2c9d5 net: core: add UID to flows, rules, and routes 1310*2f2c4c7aSAndroid Build Coastguard Worker 86741ec254 net: core: Add a UID field to struct sock. 1311*2f2c4c7aSAndroid Build Coastguard Worker 1312*2f2c4c7aSAndroid Build Coastguard Worker android-3.18: 1313*2f2c4c7aSAndroid Build Coastguard Worker b004e79504 net: ipv4: Don't crash if passing a null sk to ip_rt_update_pmtu. 1314*2f2c4c7aSAndroid Build Coastguard Worker 04c0eace81 net: inet: Support UID-based routing in IP protocols. 1315*2f2c4c7aSAndroid Build Coastguard Worker 18c36d7b71 net: core: add UID to flows, rules, and routes 1316*2f2c4c7aSAndroid Build Coastguard Worker 80e3440721 net: core: Add a UID field to struct sock. 1317*2f2c4c7aSAndroid Build Coastguard Worker fa8cc2c30c Revert "net: core: Support UID-based routing." 1318*2f2c4c7aSAndroid Build Coastguard Worker b585141890 Revert "Handle 'sk' being NULL in UID-based routing." 1319*2f2c4c7aSAndroid Build Coastguard Worker 5115ab7514 Revert "net: core: fix UID-based routing build" 1320*2f2c4c7aSAndroid Build Coastguard Worker f9f4281f79 Revert "ANDROID: net: fib: remove duplicate assignment" 1321*2f2c4c7aSAndroid Build Coastguard Worker 1322*2f2c4c7aSAndroid Build Coastguard Worker android-4.4: 1323*2f2c4c7aSAndroid Build Coastguard Worker 341965cf10 net: ipv4: Don't crash if passing a null sk to ip_rt_update_pmtu. 1324*2f2c4c7aSAndroid Build Coastguard Worker 344afd627c net: inet: Support UID-based routing in IP protocols. 1325*2f2c4c7aSAndroid Build Coastguard Worker 03441d56d8 net: core: add UID to flows, rules, and routes 1326*2f2c4c7aSAndroid Build Coastguard Worker eb964bdba7 net: core: Add a UID field to struct sock. 1327*2f2c4c7aSAndroid Build Coastguard Worker 9789b697c6 Revert "net: core: Support UID-based routing." 1328*2f2c4c7aSAndroid Build Coastguard Worker """ 1329*2f2c4c7aSAndroid Build Coastguard Worker 1330*2f2c4c7aSAndroid Build Coastguard Worker def GetRulesAtPriority(self, version, priority): 1331*2f2c4c7aSAndroid Build Coastguard Worker rules = self.iproute.DumpRules(version) 1332*2f2c4c7aSAndroid Build Coastguard Worker out = [(rule, attributes) for rule, attributes in rules 1333*2f2c4c7aSAndroid Build Coastguard Worker if attributes.get("FRA_PRIORITY", 0) == priority] 1334*2f2c4c7aSAndroid Build Coastguard Worker return out 1335*2f2c4c7aSAndroid Build Coastguard Worker 1336*2f2c4c7aSAndroid Build Coastguard Worker def CheckInitialTablesHaveNoUIDs(self, version): 1337*2f2c4c7aSAndroid Build Coastguard Worker rules = [] 1338*2f2c4c7aSAndroid Build Coastguard Worker for priority in [0, 32766, 32767]: 1339*2f2c4c7aSAndroid Build Coastguard Worker rules.extend(self.GetRulesAtPriority(version, priority)) 1340*2f2c4c7aSAndroid Build Coastguard Worker for _, attributes in rules: 1341*2f2c4c7aSAndroid Build Coastguard Worker self.assertNotIn("FRA_UID_RANGE", attributes) 1342*2f2c4c7aSAndroid Build Coastguard Worker 1343*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4InitialTablesHaveNoUIDs(self): 1344*2f2c4c7aSAndroid Build Coastguard Worker self.CheckInitialTablesHaveNoUIDs(4) 1345*2f2c4c7aSAndroid Build Coastguard Worker 1346*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6InitialTablesHaveNoUIDs(self): 1347*2f2c4c7aSAndroid Build Coastguard Worker self.CheckInitialTablesHaveNoUIDs(6) 1348*2f2c4c7aSAndroid Build Coastguard Worker 1349*2f2c4c7aSAndroid Build Coastguard Worker @staticmethod 1350*2f2c4c7aSAndroid Build Coastguard Worker def _Random(): 1351*2f2c4c7aSAndroid Build Coastguard Worker return random.randint(1000000, 2000000) 1352*2f2c4c7aSAndroid Build Coastguard Worker 1353*2f2c4c7aSAndroid Build Coastguard Worker @staticmethod 1354*2f2c4c7aSAndroid Build Coastguard Worker def _RandomUid(cls): 1355*2f2c4c7aSAndroid Build Coastguard Worker return random.randint(cls.UID_RANGE_START, cls.UID_RANGE_END) 1356*2f2c4c7aSAndroid Build Coastguard Worker 1357*2f2c4c7aSAndroid Build Coastguard Worker def CheckGetAndSetRules(self, version): 1358*2f2c4c7aSAndroid Build Coastguard Worker start, end = tuple(sorted([self._Random(), self._Random()])) 1359*2f2c4c7aSAndroid Build Coastguard Worker table = self._Random() 1360*2f2c4c7aSAndroid Build Coastguard Worker priority = self._Random() 1361*2f2c4c7aSAndroid Build Coastguard Worker 1362*2f2c4c7aSAndroid Build Coastguard Worker # Can't create a UID range to UID -1 because -1 is INVALID_UID... 1363*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno( 1364*2f2c4c7aSAndroid Build Coastguard Worker errno.EINVAL, 1365*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule, version, True, 100, 0xffffffff, table, 1366*2f2c4c7aSAndroid Build Coastguard Worker priority) 1367*2f2c4c7aSAndroid Build Coastguard Worker 1368*2f2c4c7aSAndroid Build Coastguard Worker # ... but -2 is valid. 1369*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule(version, True, 100, 0xfffffffe, table, priority) 1370*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule(version, False, 100, 0xfffffffe, table, priority) 1371*2f2c4c7aSAndroid Build Coastguard Worker 1372*2f2c4c7aSAndroid Build Coastguard Worker try: 1373*2f2c4c7aSAndroid Build Coastguard Worker # Create a UID range rule. 1374*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule(version, True, start, end, table, priority) 1375*2f2c4c7aSAndroid Build Coastguard Worker 1376*2f2c4c7aSAndroid Build Coastguard Worker # Check that deleting the wrong UID range doesn't work. 1377*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno( 1378*2f2c4c7aSAndroid Build Coastguard Worker errno.ENOENT, 1379*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule, version, False, start, end + 1, table, 1380*2f2c4c7aSAndroid Build Coastguard Worker priority) 1381*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.ENOENT, 1382*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule, version, False, start + 1, end, table, 1383*2f2c4c7aSAndroid Build Coastguard Worker priority) 1384*2f2c4c7aSAndroid Build Coastguard Worker 1385*2f2c4c7aSAndroid Build Coastguard Worker # Check that the UID range appears in dumps. 1386*2f2c4c7aSAndroid Build Coastguard Worker rules = self.GetRulesAtPriority(version, priority) 1387*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(rules) 1388*2f2c4c7aSAndroid Build Coastguard Worker _, attributes = rules[-1] 1389*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(priority, attributes["FRA_PRIORITY"]) 1390*2f2c4c7aSAndroid Build Coastguard Worker uidrange = attributes["FRA_UID_RANGE"] 1391*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(start, uidrange.start) 1392*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(end, uidrange.end) 1393*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(table, attributes["FRA_TABLE"]) 1394*2f2c4c7aSAndroid Build Coastguard Worker finally: 1395*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule(version, False, start, end, table, priority) 1396*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno( 1397*2f2c4c7aSAndroid Build Coastguard Worker errno.ENOENT, 1398*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule, version, False, start, end, table, 1399*2f2c4c7aSAndroid Build Coastguard Worker priority) 1400*2f2c4c7aSAndroid Build Coastguard Worker 1401*2f2c4c7aSAndroid Build Coastguard Worker fwmask = 0xfefefefe 1402*2f2c4c7aSAndroid Build Coastguard Worker try: 1403*2f2c4c7aSAndroid Build Coastguard Worker # Create a rule without a UID range. 1404*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.FwmarkRule(version, True, 300, fwmask, 301, priority + 1) 1405*2f2c4c7aSAndroid Build Coastguard Worker 1406*2f2c4c7aSAndroid Build Coastguard Worker # Check it doesn't have a UID range. 1407*2f2c4c7aSAndroid Build Coastguard Worker rules = self.GetRulesAtPriority(version, priority + 1) 1408*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(rules) 1409*2f2c4c7aSAndroid Build Coastguard Worker for _, attributes in rules: 1410*2f2c4c7aSAndroid Build Coastguard Worker self.assertIn("FRA_TABLE", attributes) 1411*2f2c4c7aSAndroid Build Coastguard Worker self.assertNotIn("FRA_UID_RANGE", attributes) 1412*2f2c4c7aSAndroid Build Coastguard Worker finally: 1413*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.FwmarkRule(version, False, 300, fwmask, 301, priority + 1) 1414*2f2c4c7aSAndroid Build Coastguard Worker 1415*2f2c4c7aSAndroid Build Coastguard Worker # Test that EEXIST worksfor UID range rules too. 1416*2f2c4c7aSAndroid Build Coastguard Worker ranges = [(100, 101), (100, 102), (99, 101), (1234, 5678)] 1417*2f2c4c7aSAndroid Build Coastguard Worker dup = ranges[0] 1418*2f2c4c7aSAndroid Build Coastguard Worker try: 1419*2f2c4c7aSAndroid Build Coastguard Worker # Check that otherwise identical rules with different UID ranges can be 1420*2f2c4c7aSAndroid Build Coastguard Worker # created without EEXIST. 1421*2f2c4c7aSAndroid Build Coastguard Worker for start, end in ranges: 1422*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule(version, True, start, end, table, priority) 1423*2f2c4c7aSAndroid Build Coastguard Worker # ... but EEXIST is returned if the UID range is identical. 1424*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno( 1425*2f2c4c7aSAndroid Build Coastguard Worker errno.EEXIST, 1426*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule, version, True, dup[0], dup[1], table, 1427*2f2c4c7aSAndroid Build Coastguard Worker priority) 1428*2f2c4c7aSAndroid Build Coastguard Worker finally: 1429*2f2c4c7aSAndroid Build Coastguard Worker # Clean up. 1430*2f2c4c7aSAndroid Build Coastguard Worker for start, end in ranges + [dup]: 1431*2f2c4c7aSAndroid Build Coastguard Worker try: 1432*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule(version, False, start, end, table, 1433*2f2c4c7aSAndroid Build Coastguard Worker priority) 1434*2f2c4c7aSAndroid Build Coastguard Worker except IOError: 1435*2f2c4c7aSAndroid Build Coastguard Worker pass 1436*2f2c4c7aSAndroid Build Coastguard Worker 1437*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4GetAndSetRules(self): 1438*2f2c4c7aSAndroid Build Coastguard Worker self.CheckGetAndSetRules(4) 1439*2f2c4c7aSAndroid Build Coastguard Worker 1440*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6GetAndSetRules(self): 1441*2f2c4c7aSAndroid Build Coastguard Worker self.CheckGetAndSetRules(6) 1442*2f2c4c7aSAndroid Build Coastguard Worker 1443*2f2c4c7aSAndroid Build Coastguard Worker def testDeleteErrno(self): 1444*2f2c4c7aSAndroid Build Coastguard Worker for version in [4, 6]: 1445*2f2c4c7aSAndroid Build Coastguard Worker table = self._Random() 1446*2f2c4c7aSAndroid Build Coastguard Worker priority = self._Random() 1447*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno( 1448*2f2c4c7aSAndroid Build Coastguard Worker errno.EINVAL, 1449*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule, version, False, 100, 0xffffffff, table, 1450*2f2c4c7aSAndroid Build Coastguard Worker priority) 1451*2f2c4c7aSAndroid Build Coastguard Worker 1452*2f2c4c7aSAndroid Build Coastguard Worker def ExpectNoRoute(self, addr, oif, mark, uid): 1453*2f2c4c7aSAndroid Build Coastguard Worker # The lack of a route may be either an error, or an unreachable route. 1454*2f2c4c7aSAndroid Build Coastguard Worker try: 1455*2f2c4c7aSAndroid Build Coastguard Worker routes = self.iproute.GetRoutes(addr, oif, mark, uid) 1456*2f2c4c7aSAndroid Build Coastguard Worker rtmsg, _ = routes[0] 1457*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(iproute.RTN_UNREACHABLE, rtmsg.type) 1458*2f2c4c7aSAndroid Build Coastguard Worker except IOError as e: 1459*2f2c4c7aSAndroid Build Coastguard Worker if int(e.errno) != int(errno.ENETUNREACH): 1460*2f2c4c7aSAndroid Build Coastguard Worker raise e 1461*2f2c4c7aSAndroid Build Coastguard Worker 1462*2f2c4c7aSAndroid Build Coastguard Worker def ExpectRoute(self, addr, oif, mark, uid): 1463*2f2c4c7aSAndroid Build Coastguard Worker routes = self.iproute.GetRoutes(addr, oif, mark, uid) 1464*2f2c4c7aSAndroid Build Coastguard Worker rtmsg, _ = routes[0] 1465*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(iproute.RTN_UNICAST, rtmsg.type) 1466*2f2c4c7aSAndroid Build Coastguard Worker 1467*2f2c4c7aSAndroid Build Coastguard Worker def CheckGetRoute(self, version, addr): 1468*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNoRoute(addr, 0, 0, 0) 1469*2f2c4c7aSAndroid Build Coastguard Worker for netid in self.NETIDS: 1470*2f2c4c7aSAndroid Build Coastguard Worker uid = self.UidForNetid(netid) 1471*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectRoute(addr, 0, 0, uid) 1472*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNoRoute(addr, 0, 0, 0) 1473*2f2c4c7aSAndroid Build Coastguard Worker 1474*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4RouteGet(self): 1475*2f2c4c7aSAndroid Build Coastguard Worker self.CheckGetRoute(4, net_test.IPV4_ADDR) 1476*2f2c4c7aSAndroid Build Coastguard Worker 1477*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6RouteGet(self): 1478*2f2c4c7aSAndroid Build Coastguard Worker self.CheckGetRoute(6, net_test.IPV6_ADDR) 1479*2f2c4c7aSAndroid Build Coastguard Worker 1480*2f2c4c7aSAndroid Build Coastguard Worker def testChangeFdAttributes(self): 1481*2f2c4c7aSAndroid Build Coastguard Worker netid = random.choice(self.NETIDS) 1482*2f2c4c7aSAndroid Build Coastguard Worker uid = self._RandomUid(self) 1483*2f2c4c7aSAndroid Build Coastguard Worker table = self._TableForNetid(netid) 1484*2f2c4c7aSAndroid Build Coastguard Worker remoteaddr = self.GetRemoteAddress(6) 1485*2f2c4c7aSAndroid Build Coastguard Worker s = socket(AF_INET6, SOCK_DGRAM, 0) 1486*2f2c4c7aSAndroid Build Coastguard Worker 1487*2f2c4c7aSAndroid Build Coastguard Worker def CheckSendFails(): 1488*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.ENETUNREACH, 1489*2f2c4c7aSAndroid Build Coastguard Worker s.sendto, b"foo", (remoteaddr, 53)) 1490*2f2c4c7aSAndroid Build Coastguard Worker def CheckSendSucceeds(): 1491*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(len(b"foo"), s.sendto(b"foo", (remoteaddr, 53))) 1492*2f2c4c7aSAndroid Build Coastguard Worker 1493*2f2c4c7aSAndroid Build Coastguard Worker CheckSendFails() 1494*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule(6, True, uid, uid, table, self.PRIORITY_UID) 1495*2f2c4c7aSAndroid Build Coastguard Worker try: 1496*2f2c4c7aSAndroid Build Coastguard Worker CheckSendFails() 1497*2f2c4c7aSAndroid Build Coastguard Worker os.fchown(s.fileno(), uid, -1) 1498*2f2c4c7aSAndroid Build Coastguard Worker CheckSendSucceeds() 1499*2f2c4c7aSAndroid Build Coastguard Worker os.fchown(s.fileno(), -1, -1) 1500*2f2c4c7aSAndroid Build Coastguard Worker CheckSendSucceeds() 1501*2f2c4c7aSAndroid Build Coastguard Worker os.fchown(s.fileno(), -1, 12345) 1502*2f2c4c7aSAndroid Build Coastguard Worker CheckSendSucceeds() 1503*2f2c4c7aSAndroid Build Coastguard Worker os.fchmod(s.fileno(), 0o777) 1504*2f2c4c7aSAndroid Build Coastguard Worker CheckSendSucceeds() 1505*2f2c4c7aSAndroid Build Coastguard Worker os.fchown(s.fileno(), 0, -1) 1506*2f2c4c7aSAndroid Build Coastguard Worker CheckSendFails() 1507*2f2c4c7aSAndroid Build Coastguard Worker finally: 1508*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UidRangeRule(6, False, uid, uid, table, self.PRIORITY_UID) 1509*2f2c4c7aSAndroid Build Coastguard Worker s.close() 1510*2f2c4c7aSAndroid Build Coastguard Worker 1511*2f2c4c7aSAndroid Build Coastguard Worker 1512*2f2c4c7aSAndroid Build Coastguard Workerclass RulesTest(net_test.NetworkTest): 1513*2f2c4c7aSAndroid Build Coastguard Worker 1514*2f2c4c7aSAndroid Build Coastguard Worker RULE_PRIORITY = 99999 1515*2f2c4c7aSAndroid Build Coastguard Worker FWMASK = 0xffffffff 1516*2f2c4c7aSAndroid Build Coastguard Worker 1517*2f2c4c7aSAndroid Build Coastguard Worker def setUp(self): 1518*2f2c4c7aSAndroid Build Coastguard Worker self.iproute = iproute.IPRoute() 1519*2f2c4c7aSAndroid Build Coastguard Worker for version in [4, 6]: 1520*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.DeleteRulesAtPriority(version, self.RULE_PRIORITY) 1521*2f2c4c7aSAndroid Build Coastguard Worker 1522*2f2c4c7aSAndroid Build Coastguard Worker def tearDown(self): 1523*2f2c4c7aSAndroid Build Coastguard Worker for version in [4, 6]: 1524*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.DeleteRulesAtPriority(version, self.RULE_PRIORITY) 1525*2f2c4c7aSAndroid Build Coastguard Worker 1526*2f2c4c7aSAndroid Build Coastguard Worker def testRuleDeletionMatchesTable(self): 1527*2f2c4c7aSAndroid Build Coastguard Worker for version in [4, 6]: 1528*2f2c4c7aSAndroid Build Coastguard Worker # Add rules with mark 300 pointing at tables 301 and 302. 1529*2f2c4c7aSAndroid Build Coastguard Worker # This checks for a kernel bug where deletion request for tables > 256 1530*2f2c4c7aSAndroid Build Coastguard Worker # ignored the table. 1531*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.FwmarkRule(version, True, 300, self.FWMASK, 301, 1532*2f2c4c7aSAndroid Build Coastguard Worker priority=self.RULE_PRIORITY) 1533*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.FwmarkRule(version, True, 300, self.FWMASK, 302, 1534*2f2c4c7aSAndroid Build Coastguard Worker priority=self.RULE_PRIORITY) 1535*2f2c4c7aSAndroid Build Coastguard Worker # Delete rule with mark 300 pointing at table 302. 1536*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.FwmarkRule(version, False, 300, self.FWMASK, 302, 1537*2f2c4c7aSAndroid Build Coastguard Worker priority=self.RULE_PRIORITY) 1538*2f2c4c7aSAndroid Build Coastguard Worker # Check that the rule pointing at table 301 is still around. 1539*2f2c4c7aSAndroid Build Coastguard Worker attributes = [a for _, a in self.iproute.DumpRules(version) 1540*2f2c4c7aSAndroid Build Coastguard Worker if a.get("FRA_PRIORITY", 0) == self.RULE_PRIORITY] 1541*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(1, len(attributes)) 1542*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(301, attributes[0]["FRA_TABLE"]) 1543*2f2c4c7aSAndroid Build Coastguard Worker 1544*2f2c4c7aSAndroid Build Coastguard Worker 1545*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__": 1546*2f2c4c7aSAndroid Build Coastguard Worker unittest.main() 1547