1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3 2*2f2c4c7aSAndroid Build Coastguard Worker# 3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2014 The Android Open Source Project 4*2f2c4c7aSAndroid Build Coastguard Worker# 5*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*2f2c4c7aSAndroid Build Coastguard Worker# 9*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*2f2c4c7aSAndroid Build Coastguard Worker# 11*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License. 16*2f2c4c7aSAndroid Build Coastguard Worker 17*2f2c4c7aSAndroid Build Coastguard Worker# pylint: disable=g-bad-todo 18*2f2c4c7aSAndroid Build Coastguard Worker 19*2f2c4c7aSAndroid Build Coastguard Workerimport binascii 20*2f2c4c7aSAndroid Build Coastguard Workerimport errno 21*2f2c4c7aSAndroid Build Coastguard Workerimport os 22*2f2c4c7aSAndroid Build Coastguard Workerimport posix 23*2f2c4c7aSAndroid Build Coastguard Workerimport random 24*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import * # pylint: disable=g-importing-member,wildcard-import 25*2f2c4c7aSAndroid Build Coastguard Workerimport struct 26*2f2c4c7aSAndroid Build Coastguard Workerimport sys 27*2f2c4c7aSAndroid Build Coastguard Workerimport threading 28*2f2c4c7aSAndroid Build Coastguard Workerimport time 29*2f2c4c7aSAndroid Build Coastguard Workerimport unittest 30*2f2c4c7aSAndroid Build Coastguard Worker 31*2f2c4c7aSAndroid Build Coastguard Workerimport csocket 32*2f2c4c7aSAndroid Build Coastguard Workerimport multinetwork_base 33*2f2c4c7aSAndroid Build Coastguard Workerimport net_test 34*2f2c4c7aSAndroid Build Coastguard Workerfrom scapy import all as scapy 35*2f2c4c7aSAndroid Build Coastguard Worker 36*2f2c4c7aSAndroid Build Coastguard Worker 37*2f2c4c7aSAndroid Build Coastguard WorkerICMP_ECHO = 8 38*2f2c4c7aSAndroid Build Coastguard WorkerICMP_ECHOREPLY = 0 39*2f2c4c7aSAndroid Build Coastguard WorkerICMPV6_ECHO_REQUEST = 128 40*2f2c4c7aSAndroid Build Coastguard WorkerICMPV6_ECHO_REPLY = 129 41*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_MIN_MTU = 1280 42*2f2c4c7aSAndroid Build Coastguard WorkerICMPV6_HEADER_LEN = 8 43*2f2c4c7aSAndroid Build Coastguard WorkerICMPV6_PKT_TOOBIG = 2 44*2f2c4c7aSAndroid Build Coastguard Worker 45*2f2c4c7aSAndroid Build Coastguard Worker 46*2f2c4c7aSAndroid Build Coastguard Workerclass PingReplyThread(threading.Thread): 47*2f2c4c7aSAndroid Build Coastguard Worker 48*2f2c4c7aSAndroid Build Coastguard Worker MIN_TTL = 10 49*2f2c4c7aSAndroid Build Coastguard Worker INTERMEDIATE_IPV4 = "192.0.2.2" 50*2f2c4c7aSAndroid Build Coastguard Worker INTERMEDIATE_IPV6 = "2001:db8:1:2::ace:d00d" 51*2f2c4c7aSAndroid Build Coastguard Worker NEIGHBOURS = ["fe80::1"] 52*2f2c4c7aSAndroid Build Coastguard Worker LINK_MTU = 1300 53*2f2c4c7aSAndroid Build Coastguard Worker 54*2f2c4c7aSAndroid Build Coastguard Worker def __init__(self, tun, mymac, routermac, routeraddr): 55*2f2c4c7aSAndroid Build Coastguard Worker super(PingReplyThread, self).__init__() 56*2f2c4c7aSAndroid Build Coastguard Worker self._tun = tun 57*2f2c4c7aSAndroid Build Coastguard Worker self._started_flag = False 58*2f2c4c7aSAndroid Build Coastguard Worker self._stopped_flag = False 59*2f2c4c7aSAndroid Build Coastguard Worker self._mymac = mymac 60*2f2c4c7aSAndroid Build Coastguard Worker self._routermac = routermac 61*2f2c4c7aSAndroid Build Coastguard Worker self._routeraddr = routeraddr 62*2f2c4c7aSAndroid Build Coastguard Worker 63*2f2c4c7aSAndroid Build Coastguard Worker def IsStarted(self): 64*2f2c4c7aSAndroid Build Coastguard Worker return self._started_flag 65*2f2c4c7aSAndroid Build Coastguard Worker 66*2f2c4c7aSAndroid Build Coastguard Worker def Stop(self): 67*2f2c4c7aSAndroid Build Coastguard Worker self._stopped_flag = True 68*2f2c4c7aSAndroid Build Coastguard Worker 69*2f2c4c7aSAndroid Build Coastguard Worker def ChecksumValid(self, packet): 70*2f2c4c7aSAndroid Build Coastguard Worker # Get and clear the checksums. 71*2f2c4c7aSAndroid Build Coastguard Worker def GetAndClearChecksum(layer): 72*2f2c4c7aSAndroid Build Coastguard Worker if not layer: 73*2f2c4c7aSAndroid Build Coastguard Worker return 74*2f2c4c7aSAndroid Build Coastguard Worker try: 75*2f2c4c7aSAndroid Build Coastguard Worker checksum = layer.chksum 76*2f2c4c7aSAndroid Build Coastguard Worker del layer.chksum 77*2f2c4c7aSAndroid Build Coastguard Worker except AttributeError: 78*2f2c4c7aSAndroid Build Coastguard Worker checksum = layer.cksum 79*2f2c4c7aSAndroid Build Coastguard Worker del layer.cksum 80*2f2c4c7aSAndroid Build Coastguard Worker return checksum 81*2f2c4c7aSAndroid Build Coastguard Worker 82*2f2c4c7aSAndroid Build Coastguard Worker def GetChecksum(layer): 83*2f2c4c7aSAndroid Build Coastguard Worker try: 84*2f2c4c7aSAndroid Build Coastguard Worker return layer.chksum 85*2f2c4c7aSAndroid Build Coastguard Worker except AttributeError: 86*2f2c4c7aSAndroid Build Coastguard Worker return layer.cksum 87*2f2c4c7aSAndroid Build Coastguard Worker 88*2f2c4c7aSAndroid Build Coastguard Worker layers = ["IP", "ICMP", scapy.ICMPv6EchoRequest] 89*2f2c4c7aSAndroid Build Coastguard Worker sums = {} 90*2f2c4c7aSAndroid Build Coastguard Worker for name in layers: 91*2f2c4c7aSAndroid Build Coastguard Worker sums[name] = GetAndClearChecksum(packet.getlayer(name)) 92*2f2c4c7aSAndroid Build Coastguard Worker 93*2f2c4c7aSAndroid Build Coastguard Worker # Serialize the packet, so scapy recalculates the checksums, and compare 94*2f2c4c7aSAndroid Build Coastguard Worker # them with the ones in the packet. 95*2f2c4c7aSAndroid Build Coastguard Worker packet = packet.__class__(bytes(packet)) 96*2f2c4c7aSAndroid Build Coastguard Worker for name in layers: 97*2f2c4c7aSAndroid Build Coastguard Worker layer = packet.getlayer(name) 98*2f2c4c7aSAndroid Build Coastguard Worker if layer and GetChecksum(layer) != sums[name]: 99*2f2c4c7aSAndroid Build Coastguard Worker return False 100*2f2c4c7aSAndroid Build Coastguard Worker 101*2f2c4c7aSAndroid Build Coastguard Worker return True 102*2f2c4c7aSAndroid Build Coastguard Worker 103*2f2c4c7aSAndroid Build Coastguard Worker def SendTimeExceeded(self, version, packet): 104*2f2c4c7aSAndroid Build Coastguard Worker if version == 4: 105*2f2c4c7aSAndroid Build Coastguard Worker src = packet.getlayer(scapy.IP).src 106*2f2c4c7aSAndroid Build Coastguard Worker self.SendPacket( 107*2f2c4c7aSAndroid Build Coastguard Worker scapy.IP(src=self.INTERMEDIATE_IPV4, dst=src) / 108*2f2c4c7aSAndroid Build Coastguard Worker scapy.ICMP(type=11, code=0) / 109*2f2c4c7aSAndroid Build Coastguard Worker packet) 110*2f2c4c7aSAndroid Build Coastguard Worker elif version == 6: 111*2f2c4c7aSAndroid Build Coastguard Worker src = packet.getlayer(scapy.IPv6).src 112*2f2c4c7aSAndroid Build Coastguard Worker self.SendPacket( 113*2f2c4c7aSAndroid Build Coastguard Worker scapy.IPv6(src=self.INTERMEDIATE_IPV6, dst=src) / 114*2f2c4c7aSAndroid Build Coastguard Worker scapy.ICMPv6TimeExceeded(code=0) / 115*2f2c4c7aSAndroid Build Coastguard Worker packet) 116*2f2c4c7aSAndroid Build Coastguard Worker 117*2f2c4c7aSAndroid Build Coastguard Worker def SendPacketTooBig(self, packet): 118*2f2c4c7aSAndroid Build Coastguard Worker src = packet.getlayer(scapy.IPv6).src 119*2f2c4c7aSAndroid Build Coastguard Worker datalen = IPV6_MIN_MTU - ICMPV6_HEADER_LEN 120*2f2c4c7aSAndroid Build Coastguard Worker self.SendPacket( 121*2f2c4c7aSAndroid Build Coastguard Worker scapy.IPv6(src=self.INTERMEDIATE_IPV6, dst=src) / 122*2f2c4c7aSAndroid Build Coastguard Worker scapy.ICMPv6PacketTooBig(mtu=self.LINK_MTU) / 123*2f2c4c7aSAndroid Build Coastguard Worker bytes(packet)[:datalen]) 124*2f2c4c7aSAndroid Build Coastguard Worker 125*2f2c4c7aSAndroid Build Coastguard Worker def IPv4Packet(self, ip): 126*2f2c4c7aSAndroid Build Coastguard Worker icmp = ip.getlayer(scapy.ICMP) 127*2f2c4c7aSAndroid Build Coastguard Worker 128*2f2c4c7aSAndroid Build Coastguard Worker # We only support ping for now. 129*2f2c4c7aSAndroid Build Coastguard Worker if (ip.proto != IPPROTO_ICMP or 130*2f2c4c7aSAndroid Build Coastguard Worker icmp.type != ICMP_ECHO or 131*2f2c4c7aSAndroid Build Coastguard Worker icmp.code != 0): 132*2f2c4c7aSAndroid Build Coastguard Worker return 133*2f2c4c7aSAndroid Build Coastguard Worker 134*2f2c4c7aSAndroid Build Coastguard Worker # Check the checksums. 135*2f2c4c7aSAndroid Build Coastguard Worker if not self.ChecksumValid(ip): 136*2f2c4c7aSAndroid Build Coastguard Worker return 137*2f2c4c7aSAndroid Build Coastguard Worker 138*2f2c4c7aSAndroid Build Coastguard Worker if ip.ttl < self.MIN_TTL: 139*2f2c4c7aSAndroid Build Coastguard Worker self.SendTimeExceeded(4, ip) 140*2f2c4c7aSAndroid Build Coastguard Worker return 141*2f2c4c7aSAndroid Build Coastguard Worker 142*2f2c4c7aSAndroid Build Coastguard Worker icmp.type = ICMP_ECHOREPLY 143*2f2c4c7aSAndroid Build Coastguard Worker self.SwapAddresses(ip) 144*2f2c4c7aSAndroid Build Coastguard Worker self.SendPacket(ip) 145*2f2c4c7aSAndroid Build Coastguard Worker 146*2f2c4c7aSAndroid Build Coastguard Worker def IPv6Packet(self, ipv6): 147*2f2c4c7aSAndroid Build Coastguard Worker icmpv6 = ipv6.getlayer(scapy.ICMPv6EchoRequest) 148*2f2c4c7aSAndroid Build Coastguard Worker 149*2f2c4c7aSAndroid Build Coastguard Worker # We only support ping for now. 150*2f2c4c7aSAndroid Build Coastguard Worker if (ipv6.nh != IPPROTO_ICMPV6 or 151*2f2c4c7aSAndroid Build Coastguard Worker not icmpv6 or 152*2f2c4c7aSAndroid Build Coastguard Worker icmpv6.type != ICMPV6_ECHO_REQUEST or 153*2f2c4c7aSAndroid Build Coastguard Worker icmpv6.code != 0): 154*2f2c4c7aSAndroid Build Coastguard Worker return 155*2f2c4c7aSAndroid Build Coastguard Worker 156*2f2c4c7aSAndroid Build Coastguard Worker # Check the checksums. 157*2f2c4c7aSAndroid Build Coastguard Worker if not self.ChecksumValid(ipv6): 158*2f2c4c7aSAndroid Build Coastguard Worker return 159*2f2c4c7aSAndroid Build Coastguard Worker 160*2f2c4c7aSAndroid Build Coastguard Worker if ipv6.dst.startswith("ff02::"): 161*2f2c4c7aSAndroid Build Coastguard Worker ipv6.dst = ipv6.src 162*2f2c4c7aSAndroid Build Coastguard Worker for src in [self._routeraddr]: 163*2f2c4c7aSAndroid Build Coastguard Worker ipv6.src = src 164*2f2c4c7aSAndroid Build Coastguard Worker icmpv6.type = ICMPV6_ECHO_REPLY 165*2f2c4c7aSAndroid Build Coastguard Worker self.SendPacket(ipv6) 166*2f2c4c7aSAndroid Build Coastguard Worker elif ipv6.hlim < self.MIN_TTL: 167*2f2c4c7aSAndroid Build Coastguard Worker self.SendTimeExceeded(6, ipv6) 168*2f2c4c7aSAndroid Build Coastguard Worker elif ipv6.plen > self.LINK_MTU: 169*2f2c4c7aSAndroid Build Coastguard Worker self.SendPacketTooBig(ipv6) 170*2f2c4c7aSAndroid Build Coastguard Worker else: 171*2f2c4c7aSAndroid Build Coastguard Worker icmpv6.type = ICMPV6_ECHO_REPLY 172*2f2c4c7aSAndroid Build Coastguard Worker if ipv6.dst.startswith("fe80:") and ipv6.dst != self._routeraddr: 173*2f2c4c7aSAndroid Build Coastguard Worker return 174*2f2c4c7aSAndroid Build Coastguard Worker self.SwapAddresses(ipv6) 175*2f2c4c7aSAndroid Build Coastguard Worker self.SendPacket(ipv6) 176*2f2c4c7aSAndroid Build Coastguard Worker 177*2f2c4c7aSAndroid Build Coastguard Worker def SwapAddresses(self, packet): 178*2f2c4c7aSAndroid Build Coastguard Worker src = packet.src 179*2f2c4c7aSAndroid Build Coastguard Worker packet.src = packet.dst 180*2f2c4c7aSAndroid Build Coastguard Worker packet.dst = src 181*2f2c4c7aSAndroid Build Coastguard Worker 182*2f2c4c7aSAndroid Build Coastguard Worker def SendPacket(self, packet): 183*2f2c4c7aSAndroid Build Coastguard Worker packet = scapy.Ether(src=self._routermac, dst=self._mymac) / packet 184*2f2c4c7aSAndroid Build Coastguard Worker try: 185*2f2c4c7aSAndroid Build Coastguard Worker posix.write(self._tun.fileno(), bytes(packet)) 186*2f2c4c7aSAndroid Build Coastguard Worker except Exception as e: # pylint: disable=broad-exception-caught 187*2f2c4c7aSAndroid Build Coastguard Worker if not self._stopped_flag: 188*2f2c4c7aSAndroid Build Coastguard Worker raise e 189*2f2c4c7aSAndroid Build Coastguard Worker 190*2f2c4c7aSAndroid Build Coastguard Worker def run(self): 191*2f2c4c7aSAndroid Build Coastguard Worker self._started_flag = True 192*2f2c4c7aSAndroid Build Coastguard Worker while not self._stopped_flag: 193*2f2c4c7aSAndroid Build Coastguard Worker try: 194*2f2c4c7aSAndroid Build Coastguard Worker packet = posix.read(self._tun.fileno(), 4096) 195*2f2c4c7aSAndroid Build Coastguard Worker except OSError as e: 196*2f2c4c7aSAndroid Build Coastguard Worker if e.errno == errno.EAGAIN: 197*2f2c4c7aSAndroid Build Coastguard Worker continue 198*2f2c4c7aSAndroid Build Coastguard Worker else: 199*2f2c4c7aSAndroid Build Coastguard Worker break 200*2f2c4c7aSAndroid Build Coastguard Worker except ValueError as e: 201*2f2c4c7aSAndroid Build Coastguard Worker if not self._stopped_flag: 202*2f2c4c7aSAndroid Build Coastguard Worker raise e 203*2f2c4c7aSAndroid Build Coastguard Worker 204*2f2c4c7aSAndroid Build Coastguard Worker ether = scapy.Ether(packet) 205*2f2c4c7aSAndroid Build Coastguard Worker if ether.type == net_test.ETH_P_IPV6: 206*2f2c4c7aSAndroid Build Coastguard Worker self.IPv6Packet(ether.payload) 207*2f2c4c7aSAndroid Build Coastguard Worker elif ether.type == net_test.ETH_P_IP: 208*2f2c4c7aSAndroid Build Coastguard Worker self.IPv4Packet(ether.payload) 209*2f2c4c7aSAndroid Build Coastguard Worker 210*2f2c4c7aSAndroid Build Coastguard Worker 211*2f2c4c7aSAndroid Build Coastguard Workerclass Ping6Test(multinetwork_base.MultiNetworkBaseTest): 212*2f2c4c7aSAndroid Build Coastguard Worker 213*2f2c4c7aSAndroid Build Coastguard Worker @classmethod 214*2f2c4c7aSAndroid Build Coastguard Worker def WaitForReplyThreads(cls): 215*2f2c4c7aSAndroid Build Coastguard Worker # Wait 2s for the reply threads to start. If they don't, don't blow up, as 216*2f2c4c7aSAndroid Build Coastguard Worker # that would cause tearDownClass not to be called and thus not clean up 217*2f2c4c7aSAndroid Build Coastguard Worker # routing configuration, breaking subsequent tests. Instead, just let these 218*2f2c4c7aSAndroid Build Coastguard Worker # tests fail. 219*2f2c4c7aSAndroid Build Coastguard Worker interval = 0.1 220*2f2c4c7aSAndroid Build Coastguard Worker attempts = 20 221*2f2c4c7aSAndroid Build Coastguard Worker for _ in range(attempts): 222*2f2c4c7aSAndroid Build Coastguard Worker for _ in cls.NETIDS: 223*2f2c4c7aSAndroid Build Coastguard Worker if all(thrd.IsStarted() for thrd in list(cls.reply_threads.values())): 224*2f2c4c7aSAndroid Build Coastguard Worker return 225*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(interval) 226*2f2c4c7aSAndroid Build Coastguard Worker msg = "WARNING: reply threads not all started after %.1f seconds\n" % ( 227*2f2c4c7aSAndroid Build Coastguard Worker attempts * interval) 228*2f2c4c7aSAndroid Build Coastguard Worker sys.stderr.write(msg) 229*2f2c4c7aSAndroid Build Coastguard Worker 230*2f2c4c7aSAndroid Build Coastguard Worker @classmethod 231*2f2c4c7aSAndroid Build Coastguard Worker def StopReplyThreads(cls): 232*2f2c4c7aSAndroid Build Coastguard Worker for thread in list(cls.reply_threads.values()): 233*2f2c4c7aSAndroid Build Coastguard Worker thread.Stop() 234*2f2c4c7aSAndroid Build Coastguard Worker 235*2f2c4c7aSAndroid Build Coastguard Worker @classmethod 236*2f2c4c7aSAndroid Build Coastguard Worker def setUpClass(cls): 237*2f2c4c7aSAndroid Build Coastguard Worker super(Ping6Test, cls).setUpClass() 238*2f2c4c7aSAndroid Build Coastguard Worker cls.reply_threads = {} 239*2f2c4c7aSAndroid Build Coastguard Worker for netid in cls.NETIDS: 240*2f2c4c7aSAndroid Build Coastguard Worker cls.reply_threads[netid] = PingReplyThread( 241*2f2c4c7aSAndroid Build Coastguard Worker cls.tuns[netid], 242*2f2c4c7aSAndroid Build Coastguard Worker cls.MyMacAddress(netid), 243*2f2c4c7aSAndroid Build Coastguard Worker cls.RouterMacAddress(netid), 244*2f2c4c7aSAndroid Build Coastguard Worker cls._RouterAddress(netid, 6)) 245*2f2c4c7aSAndroid Build Coastguard Worker cls.reply_threads[netid].start() 246*2f2c4c7aSAndroid Build Coastguard Worker cls.WaitForReplyThreads() 247*2f2c4c7aSAndroid Build Coastguard Worker cls.netid = random.choice(cls.NETIDS) 248*2f2c4c7aSAndroid Build Coastguard Worker cls.SetDefaultNetwork(cls.netid) 249*2f2c4c7aSAndroid Build Coastguard Worker 250*2f2c4c7aSAndroid Build Coastguard Worker @classmethod 251*2f2c4c7aSAndroid Build Coastguard Worker def tearDownClass(cls): 252*2f2c4c7aSAndroid Build Coastguard Worker cls.StopReplyThreads() 253*2f2c4c7aSAndroid Build Coastguard Worker cls.ClearDefaultNetwork() 254*2f2c4c7aSAndroid Build Coastguard Worker super(Ping6Test, cls).tearDownClass() 255*2f2c4c7aSAndroid Build Coastguard Worker 256*2f2c4c7aSAndroid Build Coastguard Worker def setUp(self): 257*2f2c4c7aSAndroid Build Coastguard Worker super(Ping6Test, self).setUp() 258*2f2c4c7aSAndroid Build Coastguard Worker self.ifname = self.GetInterfaceName(self.netid) 259*2f2c4c7aSAndroid Build Coastguard Worker self.ifindex = self.ifindices[self.netid] 260*2f2c4c7aSAndroid Build Coastguard Worker self.lladdr = net_test.GetLinkAddress(self.ifname, True) 261*2f2c4c7aSAndroid Build Coastguard Worker self.globaladdr = net_test.GetLinkAddress(self.ifname, False) 262*2f2c4c7aSAndroid Build Coastguard Worker 263*2f2c4c7aSAndroid Build Coastguard Worker def assertValidPingResponse(self, s, data): 264*2f2c4c7aSAndroid Build Coastguard Worker family = s.family 265*2f2c4c7aSAndroid Build Coastguard Worker 266*2f2c4c7aSAndroid Build Coastguard Worker # Receive the reply. 267*2f2c4c7aSAndroid Build Coastguard Worker rcvd, src = s.recvfrom(32768) 268*2f2c4c7aSAndroid Build Coastguard Worker self.assertNotEqual(0, len(rcvd), "No data received") 269*2f2c4c7aSAndroid Build Coastguard Worker 270*2f2c4c7aSAndroid Build Coastguard Worker # If this is a dual-stack socket sending to a mapped IPv4 address, treat it 271*2f2c4c7aSAndroid Build Coastguard Worker # as IPv4. 272*2f2c4c7aSAndroid Build Coastguard Worker if src[0].startswith("::ffff:"): 273*2f2c4c7aSAndroid Build Coastguard Worker family = AF_INET 274*2f2c4c7aSAndroid Build Coastguard Worker src = (src[0].replace("::ffff:", ""), src[1:]) 275*2f2c4c7aSAndroid Build Coastguard Worker 276*2f2c4c7aSAndroid Build Coastguard Worker # Check the data being sent is valid. 277*2f2c4c7aSAndroid Build Coastguard Worker self.assertGreater(len(data), 7, "Not enough data for ping packet") 278*2f2c4c7aSAndroid Build Coastguard Worker if family == AF_INET: 279*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(data.startswith(b"\x08\x00"), "Not an IPv4 echo request") 280*2f2c4c7aSAndroid Build Coastguard Worker elif family == AF_INET6: 281*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(data.startswith(b"\x80\x00"), "Not an IPv6 echo request") 282*2f2c4c7aSAndroid Build Coastguard Worker else: 283*2f2c4c7aSAndroid Build Coastguard Worker self.fail("Unknown socket address family %d" * s.family) 284*2f2c4c7aSAndroid Build Coastguard Worker 285*2f2c4c7aSAndroid Build Coastguard Worker # Check address, ICMP type, and ICMP code. 286*2f2c4c7aSAndroid Build Coastguard Worker if family == AF_INET: 287*2f2c4c7aSAndroid Build Coastguard Worker addr, unused_port = src 288*2f2c4c7aSAndroid Build Coastguard Worker self.assertGreaterEqual(len(addr), len("1.1.1.1")) 289*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(rcvd.startswith(b"\x00\x00"), "Not an IPv4 echo reply") 290*2f2c4c7aSAndroid Build Coastguard Worker else: 291*2f2c4c7aSAndroid Build Coastguard Worker addr, unused_port, flowlabel, scope_id = src # pylint: disable=unbalanced-tuple-unpacking 292*2f2c4c7aSAndroid Build Coastguard Worker self.assertGreaterEqual(len(addr), len("::")) 293*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(rcvd.startswith(b"\x81\x00"), "Not an IPv6 echo reply") 294*2f2c4c7aSAndroid Build Coastguard Worker # Check that the flow label is zero and that the scope ID is sane. 295*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(flowlabel, 0) 296*2f2c4c7aSAndroid Build Coastguard Worker if addr.startswith("fe80::"): 297*2f2c4c7aSAndroid Build Coastguard Worker self.assertIn(scope_id, list(self.ifindices.values())) 298*2f2c4c7aSAndroid Build Coastguard Worker else: 299*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(0, scope_id) 300*2f2c4c7aSAndroid Build Coastguard Worker 301*2f2c4c7aSAndroid Build Coastguard Worker # TODO: check the checksum. We can't do this easily now for ICMPv6 because 302*2f2c4c7aSAndroid Build Coastguard Worker # we don't have the IP addresses so we can't construct the pseudoheader. 303*2f2c4c7aSAndroid Build Coastguard Worker 304*2f2c4c7aSAndroid Build Coastguard Worker # Check the sequence number and the data. 305*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(len(data), len(rcvd)) 306*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(binascii.hexlify(data[6:]), binascii.hexlify(rcvd[6:])) 307*2f2c4c7aSAndroid Build Coastguard Worker 308*2f2c4c7aSAndroid Build Coastguard Worker @staticmethod 309*2f2c4c7aSAndroid Build Coastguard Worker def IsAlmostEqual(expected, actual, delta): 310*2f2c4c7aSAndroid Build Coastguard Worker return abs(expected - actual) < delta 311*2f2c4c7aSAndroid Build Coastguard Worker 312*2f2c4c7aSAndroid Build Coastguard Worker def CheckSockStatFile(self, name, srcaddr, srcport, dstaddr, dstport, state, 313*2f2c4c7aSAndroid Build Coastguard Worker txmem=0, rxmem=0): 314*2f2c4c7aSAndroid Build Coastguard Worker expected = ["%s:%04X" % (net_test.FormatSockStatAddress(srcaddr), srcport), 315*2f2c4c7aSAndroid Build Coastguard Worker "%s:%04X" % (net_test.FormatSockStatAddress(dstaddr), dstport), 316*2f2c4c7aSAndroid Build Coastguard Worker "%02X" % state, 317*2f2c4c7aSAndroid Build Coastguard Worker "%08X:%08X" % (txmem, rxmem), 318*2f2c4c7aSAndroid Build Coastguard Worker str(os.getuid()), "ref", "0"] 319*2f2c4c7aSAndroid Build Coastguard Worker for actual in self.ReadProcNetSocket(name): 320*2f2c4c7aSAndroid Build Coastguard Worker # Check that rxmem and txmem don't differ too much from each other. 321*2f2c4c7aSAndroid Build Coastguard Worker actual_txmem, actual_rxmem = expected[3].split(":") 322*2f2c4c7aSAndroid Build Coastguard Worker if self.IsAlmostEqual(txmem, int(actual_txmem, 16), txmem / 4): 323*2f2c4c7aSAndroid Build Coastguard Worker return 324*2f2c4c7aSAndroid Build Coastguard Worker if self.IsAlmostEqual(rxmem, int(actual_rxmem, 16), rxmem / 4): 325*2f2c4c7aSAndroid Build Coastguard Worker return 326*2f2c4c7aSAndroid Build Coastguard Worker 327*2f2c4c7aSAndroid Build Coastguard Worker # Check all the parameters except rxmem and txmem. 328*2f2c4c7aSAndroid Build Coastguard Worker expected[3] = actual[3] 329*2f2c4c7aSAndroid Build Coastguard Worker # Don't check ref, it's always 2 on old kernels, but 1 for 'raw6' on 6.0+ 330*2f2c4c7aSAndroid Build Coastguard Worker expected[5] = actual[5] 331*2f2c4c7aSAndroid Build Coastguard Worker if expected == actual: 332*2f2c4c7aSAndroid Build Coastguard Worker return 333*2f2c4c7aSAndroid Build Coastguard Worker 334*2f2c4c7aSAndroid Build Coastguard Worker self.fail("Cound not find socket matching %s" % expected) 335*2f2c4c7aSAndroid Build Coastguard Worker 336*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4SendWithNoConnection(self): 337*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv4PingSocket() 338*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EDESTADDRREQ, s.send, net_test.IPV4_PING) 339*2f2c4c7aSAndroid Build Coastguard Worker s.close() 340*2f2c4c7aSAndroid Build Coastguard Worker 341*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6SendWithNoConnection(self): 342*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 343*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EDESTADDRREQ, s.send, net_test.IPV6_PING) 344*2f2c4c7aSAndroid Build Coastguard Worker s.close() 345*2f2c4c7aSAndroid Build Coastguard Worker 346*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4LoopbackPingWithConnect(self): 347*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv4PingSocket() 348*2f2c4c7aSAndroid Build Coastguard Worker s.connect(("127.0.0.1", 55)) 349*2f2c4c7aSAndroid Build Coastguard Worker data = net_test.IPV4_PING + b"foobarbaz" 350*2f2c4c7aSAndroid Build Coastguard Worker s.send(data) 351*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s, data) 352*2f2c4c7aSAndroid Build Coastguard Worker s.close() 353*2f2c4c7aSAndroid Build Coastguard Worker 354*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6LoopbackPingWithConnect(self): 355*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 356*2f2c4c7aSAndroid Build Coastguard Worker s.connect(("::1", 55)) 357*2f2c4c7aSAndroid Build Coastguard Worker s.send(net_test.IPV6_PING) 358*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s, net_test.IPV6_PING) 359*2f2c4c7aSAndroid Build Coastguard Worker s.close() 360*2f2c4c7aSAndroid Build Coastguard Worker 361*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4PingUsingSendto(self): 362*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv4PingSocket() 363*2f2c4c7aSAndroid Build Coastguard Worker written = s.sendto(net_test.IPV4_PING, (net_test.IPV4_ADDR, 55)) 364*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(len(net_test.IPV4_PING), written) 365*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s, net_test.IPV4_PING) 366*2f2c4c7aSAndroid Build Coastguard Worker s.close() 367*2f2c4c7aSAndroid Build Coastguard Worker 368*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6PingUsingSendto(self): 369*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 370*2f2c4c7aSAndroid Build Coastguard Worker written = s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 55)) 371*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(len(net_test.IPV6_PING), written) 372*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s, net_test.IPV6_PING) 373*2f2c4c7aSAndroid Build Coastguard Worker s.close() 374*2f2c4c7aSAndroid Build Coastguard Worker 375*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4NoCrash(self): 376*2f2c4c7aSAndroid Build Coastguard Worker # Python 2.x does not provide either read() or recvmsg. 377*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv4PingSocket() 378*2f2c4c7aSAndroid Build Coastguard Worker written = s.sendto(net_test.IPV4_PING, ("127.0.0.1", 55)) 379*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(len(net_test.IPV4_PING), written) 380*2f2c4c7aSAndroid Build Coastguard Worker fd = s.fileno() 381*2f2c4c7aSAndroid Build Coastguard Worker reply = posix.read(fd, 4096) 382*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(written, len(reply)) 383*2f2c4c7aSAndroid Build Coastguard Worker s.close() 384*2f2c4c7aSAndroid Build Coastguard Worker 385*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6NoCrash(self): 386*2f2c4c7aSAndroid Build Coastguard Worker # Python 2.x does not provide either read() or recvmsg. 387*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 388*2f2c4c7aSAndroid Build Coastguard Worker written = s.sendto(net_test.IPV6_PING, ("::1", 55)) 389*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(len(net_test.IPV6_PING), written) 390*2f2c4c7aSAndroid Build Coastguard Worker fd = s.fileno() 391*2f2c4c7aSAndroid Build Coastguard Worker reply = posix.read(fd, 4096) 392*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(written, len(reply)) 393*2f2c4c7aSAndroid Build Coastguard Worker s.close() 394*2f2c4c7aSAndroid Build Coastguard Worker 395*2f2c4c7aSAndroid Build Coastguard Worker def testCrossProtocolCrash(self): 396*2f2c4c7aSAndroid Build Coastguard Worker # Checks that an ICMP error containing a ping packet that matches the ID 397*2f2c4c7aSAndroid Build Coastguard Worker # of a socket of the wrong protocol (which can happen when using 464xlat) 398*2f2c4c7aSAndroid Build Coastguard Worker # doesn't crash the kernel. 399*2f2c4c7aSAndroid Build Coastguard Worker 400*2f2c4c7aSAndroid Build Coastguard Worker # We can only test this using IPv6 unreachables and IPv4 ping sockets, 401*2f2c4c7aSAndroid Build Coastguard Worker # because IPv4 packets sent by scapy.send() on loopback are not received by 402*2f2c4c7aSAndroid Build Coastguard Worker # the kernel. So we don't actually use this function yet. 403*2f2c4c7aSAndroid Build Coastguard Worker def GetIPv4Unreachable(port): # pylint: disable=unused-variable 404*2f2c4c7aSAndroid Build Coastguard Worker return (scapy.IP(src="192.0.2.1", dst="127.0.0.1") / 405*2f2c4c7aSAndroid Build Coastguard Worker scapy.ICMP(type=3, code=0) / 406*2f2c4c7aSAndroid Build Coastguard Worker scapy.IP(src="127.0.0.1", dst="127.0.0.1") / 407*2f2c4c7aSAndroid Build Coastguard Worker scapy.ICMP(type=8, id=port, seq=1)) 408*2f2c4c7aSAndroid Build Coastguard Worker 409*2f2c4c7aSAndroid Build Coastguard Worker def GetIPv6Unreachable(port): 410*2f2c4c7aSAndroid Build Coastguard Worker return (scapy.IPv6(src="::1", dst="::1") / 411*2f2c4c7aSAndroid Build Coastguard Worker scapy.ICMPv6DestUnreach() / 412*2f2c4c7aSAndroid Build Coastguard Worker scapy.IPv6(src="::1", dst="::1") / 413*2f2c4c7aSAndroid Build Coastguard Worker scapy.ICMPv6EchoRequest(id=port, seq=1, data="foobarbaz")) 414*2f2c4c7aSAndroid Build Coastguard Worker 415*2f2c4c7aSAndroid Build Coastguard Worker # An unreachable matching the ID of a socket of the wrong protocol 416*2f2c4c7aSAndroid Build Coastguard Worker # shouldn't crash. 417*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv4PingSocket() 418*2f2c4c7aSAndroid Build Coastguard Worker s.connect(("127.0.0.1", 12345)) 419*2f2c4c7aSAndroid Build Coastguard Worker _, port = s.getsockname() 420*2f2c4c7aSAndroid Build Coastguard Worker scapy.send(GetIPv6Unreachable(port), verbose=False) 421*2f2c4c7aSAndroid Build Coastguard Worker # No crash? Good. 422*2f2c4c7aSAndroid Build Coastguard Worker s.close() 423*2f2c4c7aSAndroid Build Coastguard Worker 424*2f2c4c7aSAndroid Build Coastguard Worker def testCrossProtocolCalls(self): 425*2f2c4c7aSAndroid Build Coastguard Worker """Tests that passing in the wrong family returns EAFNOSUPPORT. 426*2f2c4c7aSAndroid Build Coastguard Worker 427*2f2c4c7aSAndroid Build Coastguard Worker Relevant kernel commits: 428*2f2c4c7aSAndroid Build Coastguard Worker upstream net: 429*2f2c4c7aSAndroid Build Coastguard Worker 91a0b60 net/ping: handle protocol mismatching scenario 430*2f2c4c7aSAndroid Build Coastguard Worker 9145736d net: ping: Return EAFNOSUPPORT when appropriate. 431*2f2c4c7aSAndroid Build Coastguard Worker 432*2f2c4c7aSAndroid Build Coastguard Worker android-3.10: 433*2f2c4c7aSAndroid Build Coastguard Worker 78a6809 net/ping: handle protocol mismatching scenario 434*2f2c4c7aSAndroid Build Coastguard Worker 428e6d6 net: ping: Return EAFNOSUPPORT when appropriate. 435*2f2c4c7aSAndroid Build Coastguard Worker """ 436*2f2c4c7aSAndroid Build Coastguard Worker 437*2f2c4c7aSAndroid Build Coastguard Worker def CheckEAFNoSupport(function, *args): 438*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EAFNOSUPPORT, function, *args) 439*2f2c4c7aSAndroid Build Coastguard Worker 440*2f2c4c7aSAndroid Build Coastguard Worker ipv6sockaddr = csocket.Sockaddr((net_test.IPV6_ADDR, 53)) 441*2f2c4c7aSAndroid Build Coastguard Worker 442*2f2c4c7aSAndroid Build Coastguard Worker # In order to check that IPv6 socket calls return EAFNOSUPPORT when passed 443*2f2c4c7aSAndroid Build Coastguard Worker # IPv4 socket address structures, we need to pass down a socket address 444*2f2c4c7aSAndroid Build Coastguard Worker # length argument that's at least sizeof(sockaddr_in6). Otherwise, the calls 445*2f2c4c7aSAndroid Build Coastguard Worker # will fail immediately with EINVAL because the passed-in socket length is 446*2f2c4c7aSAndroid Build Coastguard Worker # too short. So create a sockaddr_in that's as long as a sockaddr_in6. 447*2f2c4c7aSAndroid Build Coastguard Worker ipv4sockaddr = csocket.Sockaddr((net_test.IPV4_ADDR, 53)) 448*2f2c4c7aSAndroid Build Coastguard Worker ipv4sockaddr = csocket.SockaddrIn6( 449*2f2c4c7aSAndroid Build Coastguard Worker ipv4sockaddr.Pack() + 450*2f2c4c7aSAndroid Build Coastguard Worker b"\x00" * (len(csocket.SockaddrIn6) - len(csocket.SockaddrIn))) 451*2f2c4c7aSAndroid Build Coastguard Worker 452*2f2c4c7aSAndroid Build Coastguard Worker s4 = net_test.IPv4PingSocket() 453*2f2c4c7aSAndroid Build Coastguard Worker s6 = net_test.IPv6PingSocket() 454*2f2c4c7aSAndroid Build Coastguard Worker 455*2f2c4c7aSAndroid Build Coastguard Worker # We can't just call s.connect(), s.bind() etc. with a tuple of the wrong 456*2f2c4c7aSAndroid Build Coastguard Worker # address family, because the Python implementation will just pass garbage 457*2f2c4c7aSAndroid Build Coastguard Worker # down to the kernel. So call the C functions directly. 458*2f2c4c7aSAndroid Build Coastguard Worker CheckEAFNoSupport(csocket.Bind, s4, ipv6sockaddr) 459*2f2c4c7aSAndroid Build Coastguard Worker CheckEAFNoSupport(csocket.Bind, s6, ipv4sockaddr) 460*2f2c4c7aSAndroid Build Coastguard Worker CheckEAFNoSupport(csocket.Connect, s4, ipv6sockaddr) 461*2f2c4c7aSAndroid Build Coastguard Worker CheckEAFNoSupport(csocket.Connect, s6, ipv4sockaddr) 462*2f2c4c7aSAndroid Build Coastguard Worker CheckEAFNoSupport(csocket.Sendmsg, 463*2f2c4c7aSAndroid Build Coastguard Worker s4, ipv6sockaddr, net_test.IPV4_PING, None, 0) 464*2f2c4c7aSAndroid Build Coastguard Worker CheckEAFNoSupport(csocket.Sendmsg, 465*2f2c4c7aSAndroid Build Coastguard Worker s6, ipv4sockaddr, net_test.IPV6_PING, None, 0) 466*2f2c4c7aSAndroid Build Coastguard Worker s4.close() 467*2f2c4c7aSAndroid Build Coastguard Worker s6.close() 468*2f2c4c7aSAndroid Build Coastguard Worker 469*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4Bind(self): 470*2f2c4c7aSAndroid Build Coastguard Worker # Bind to unspecified address. 471*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv4PingSocket() 472*2f2c4c7aSAndroid Build Coastguard Worker s.bind(("0.0.0.0", 544)) 473*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(("0.0.0.0", 544), s.getsockname()) 474*2f2c4c7aSAndroid Build Coastguard Worker s.close() 475*2f2c4c7aSAndroid Build Coastguard Worker 476*2f2c4c7aSAndroid Build Coastguard Worker # Bind to loopback. 477*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv4PingSocket() 478*2f2c4c7aSAndroid Build Coastguard Worker s.bind(("127.0.0.1", 99)) 479*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(("127.0.0.1", 99), s.getsockname()) 480*2f2c4c7aSAndroid Build Coastguard Worker 481*2f2c4c7aSAndroid Build Coastguard Worker # Binding twice is not allowed. 482*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EINVAL, s.bind, ("127.0.0.1", 22)) 483*2f2c4c7aSAndroid Build Coastguard Worker s.close() 484*2f2c4c7aSAndroid Build Coastguard Worker 485*2f2c4c7aSAndroid Build Coastguard Worker # But binding two different sockets to the same ID is allowed. 486*2f2c4c7aSAndroid Build Coastguard Worker s2 = net_test.IPv4PingSocket() 487*2f2c4c7aSAndroid Build Coastguard Worker s2.bind(("127.0.0.1", 99)) 488*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(("127.0.0.1", 99), s2.getsockname()) 489*2f2c4c7aSAndroid Build Coastguard Worker s3 = net_test.IPv4PingSocket() 490*2f2c4c7aSAndroid Build Coastguard Worker s3.bind(("127.0.0.1", 99)) 491*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(("127.0.0.1", 99), s3.getsockname()) 492*2f2c4c7aSAndroid Build Coastguard Worker s2.close() 493*2f2c4c7aSAndroid Build Coastguard Worker s3.close() 494*2f2c4c7aSAndroid Build Coastguard Worker 495*2f2c4c7aSAndroid Build Coastguard Worker # If two sockets bind to the same port, the first one to call read() gets 496*2f2c4c7aSAndroid Build Coastguard Worker # the response. 497*2f2c4c7aSAndroid Build Coastguard Worker s4 = net_test.IPv4PingSocket() 498*2f2c4c7aSAndroid Build Coastguard Worker s5 = net_test.IPv4PingSocket() 499*2f2c4c7aSAndroid Build Coastguard Worker s4.bind(("0.0.0.0", 167)) 500*2f2c4c7aSAndroid Build Coastguard Worker s5.bind(("0.0.0.0", 167)) 501*2f2c4c7aSAndroid Build Coastguard Worker s4.sendto(net_test.IPV4_PING, (net_test.IPV4_ADDR, 44)) 502*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s5, net_test.IPV4_PING) 503*2f2c4c7aSAndroid Build Coastguard Worker csocket.SetSocketTimeout(s4, 100) 504*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EAGAIN, s4.recv, 32768) 505*2f2c4c7aSAndroid Build Coastguard Worker 506*2f2c4c7aSAndroid Build Coastguard Worker # If SO_REUSEADDR is turned off, then we get EADDRINUSE. 507*2f2c4c7aSAndroid Build Coastguard Worker s6 = net_test.IPv4PingSocket() 508*2f2c4c7aSAndroid Build Coastguard Worker s4.setsockopt(SOL_SOCKET, SO_REUSEADDR, 0) 509*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EADDRINUSE, s6.bind, ("0.0.0.0", 167)) 510*2f2c4c7aSAndroid Build Coastguard Worker 511*2f2c4c7aSAndroid Build Coastguard Worker s4.close() 512*2f2c4c7aSAndroid Build Coastguard Worker s5.close() 513*2f2c4c7aSAndroid Build Coastguard Worker s6.close() 514*2f2c4c7aSAndroid Build Coastguard Worker 515*2f2c4c7aSAndroid Build Coastguard Worker # Can't bind after sendto. 516*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv4PingSocket() 517*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV4_PING, (net_test.IPV4_ADDR, 9132)) 518*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EINVAL, s.bind, ("0.0.0.0", 5429)) 519*2f2c4c7aSAndroid Build Coastguard Worker s.close() 520*2f2c4c7aSAndroid Build Coastguard Worker 521*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6Bind(self): 522*2f2c4c7aSAndroid Build Coastguard Worker # Bind to unspecified address. 523*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 524*2f2c4c7aSAndroid Build Coastguard Worker s.bind(("::", 769)) 525*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(("::", 769, 0, 0), s.getsockname()) 526*2f2c4c7aSAndroid Build Coastguard Worker s.close() 527*2f2c4c7aSAndroid Build Coastguard Worker 528*2f2c4c7aSAndroid Build Coastguard Worker # Bind to loopback. 529*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 530*2f2c4c7aSAndroid Build Coastguard Worker s.bind(("::1", 99)) 531*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(("::1", 99, 0, 0), s.getsockname()) 532*2f2c4c7aSAndroid Build Coastguard Worker 533*2f2c4c7aSAndroid Build Coastguard Worker # Binding twice is not allowed. 534*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EINVAL, s.bind, ("::1", 22)) 535*2f2c4c7aSAndroid Build Coastguard Worker s.close() 536*2f2c4c7aSAndroid Build Coastguard Worker 537*2f2c4c7aSAndroid Build Coastguard Worker # But binding two different sockets to the same ID is allowed. 538*2f2c4c7aSAndroid Build Coastguard Worker s2 = net_test.IPv6PingSocket() 539*2f2c4c7aSAndroid Build Coastguard Worker s2.bind(("::1", 99)) 540*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(("::1", 99, 0, 0), s2.getsockname()) 541*2f2c4c7aSAndroid Build Coastguard Worker s3 = net_test.IPv6PingSocket() 542*2f2c4c7aSAndroid Build Coastguard Worker s3.bind(("::1", 99)) 543*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(("::1", 99, 0, 0), s3.getsockname()) 544*2f2c4c7aSAndroid Build Coastguard Worker s2.close() 545*2f2c4c7aSAndroid Build Coastguard Worker s3.close() 546*2f2c4c7aSAndroid Build Coastguard Worker 547*2f2c4c7aSAndroid Build Coastguard Worker # Binding both IPv4 and IPv6 to the same socket works. 548*2f2c4c7aSAndroid Build Coastguard Worker s4 = net_test.IPv4PingSocket() 549*2f2c4c7aSAndroid Build Coastguard Worker s6 = net_test.IPv6PingSocket() 550*2f2c4c7aSAndroid Build Coastguard Worker s4.bind(("0.0.0.0", 444)) 551*2f2c4c7aSAndroid Build Coastguard Worker s6.bind(("::", 666, 0, 0)) 552*2f2c4c7aSAndroid Build Coastguard Worker s4.close() 553*2f2c4c7aSAndroid Build Coastguard Worker s6.close() 554*2f2c4c7aSAndroid Build Coastguard Worker 555*2f2c4c7aSAndroid Build Coastguard Worker # Can't bind after sendto. 556*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 557*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 9132)) 558*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EINVAL, s.bind, ("::", 5429)) 559*2f2c4c7aSAndroid Build Coastguard Worker s.close() 560*2f2c4c7aSAndroid Build Coastguard Worker 561*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4InvalidBind(self): 562*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv4PingSocket() 563*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EADDRNOTAVAIL, 564*2f2c4c7aSAndroid Build Coastguard Worker s.bind, ("255.255.255.255", 1026)) 565*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EADDRNOTAVAIL, 566*2f2c4c7aSAndroid Build Coastguard Worker s.bind, ("224.0.0.1", 651)) 567*2f2c4c7aSAndroid Build Coastguard Worker # Binding to an address we don't have only works with IP_TRANSPARENT. 568*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EADDRNOTAVAIL, 569*2f2c4c7aSAndroid Build Coastguard Worker s.bind, (net_test.IPV4_ADDR, 651)) 570*2f2c4c7aSAndroid Build Coastguard Worker try: 571*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(SOL_IP, net_test.IP_TRANSPARENT, 1) 572*2f2c4c7aSAndroid Build Coastguard Worker s.bind((net_test.IPV4_ADDR, 651)) 573*2f2c4c7aSAndroid Build Coastguard Worker except IOError as e: 574*2f2c4c7aSAndroid Build Coastguard Worker if e.errno == errno.EACCES: 575*2f2c4c7aSAndroid Build Coastguard Worker pass # We're not root. let it go for now. 576*2f2c4c7aSAndroid Build Coastguard Worker s.close() 577*2f2c4c7aSAndroid Build Coastguard Worker 578*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6InvalidBind(self): 579*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 580*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EINVAL, 581*2f2c4c7aSAndroid Build Coastguard Worker s.bind, ("ff02::2", 1026)) 582*2f2c4c7aSAndroid Build Coastguard Worker 583*2f2c4c7aSAndroid Build Coastguard Worker # Binding to an address we don't have only works with IPV6_TRANSPARENT. 584*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EADDRNOTAVAIL, 585*2f2c4c7aSAndroid Build Coastguard Worker s.bind, (net_test.IPV6_ADDR, 651)) 586*2f2c4c7aSAndroid Build Coastguard Worker try: 587*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_TRANSPARENT, 1) 588*2f2c4c7aSAndroid Build Coastguard Worker s.bind((net_test.IPV6_ADDR, 651)) 589*2f2c4c7aSAndroid Build Coastguard Worker except IOError as e: 590*2f2c4c7aSAndroid Build Coastguard Worker if e.errno == errno.EACCES: 591*2f2c4c7aSAndroid Build Coastguard Worker pass # We're not root. let it go for now. 592*2f2c4c7aSAndroid Build Coastguard Worker s.close() 593*2f2c4c7aSAndroid Build Coastguard Worker 594*2f2c4c7aSAndroid Build Coastguard Worker def testAfUnspecBind(self): 595*2f2c4c7aSAndroid Build Coastguard Worker # Binding to AF_UNSPEC is treated as IPv4 if the address is 0.0.0.0. 596*2f2c4c7aSAndroid Build Coastguard Worker s4 = net_test.IPv4PingSocket() 597*2f2c4c7aSAndroid Build Coastguard Worker sockaddr = csocket.Sockaddr(("0.0.0.0", 12996)) 598*2f2c4c7aSAndroid Build Coastguard Worker sockaddr.family = AF_UNSPEC 599*2f2c4c7aSAndroid Build Coastguard Worker csocket.Bind(s4, sockaddr) 600*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(("0.0.0.0", 12996), s4.getsockname()) 601*2f2c4c7aSAndroid Build Coastguard Worker 602*2f2c4c7aSAndroid Build Coastguard Worker # But not if the address is anything else. 603*2f2c4c7aSAndroid Build Coastguard Worker sockaddr = csocket.Sockaddr(("127.0.0.1", 58234)) 604*2f2c4c7aSAndroid Build Coastguard Worker sockaddr.family = AF_UNSPEC 605*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EAFNOSUPPORT, csocket.Bind, s4, sockaddr) 606*2f2c4c7aSAndroid Build Coastguard Worker s4.close() 607*2f2c4c7aSAndroid Build Coastguard Worker 608*2f2c4c7aSAndroid Build Coastguard Worker # This doesn't work for IPv6. 609*2f2c4c7aSAndroid Build Coastguard Worker s6 = net_test.IPv6PingSocket() 610*2f2c4c7aSAndroid Build Coastguard Worker sockaddr = csocket.Sockaddr(("::1", 58997)) 611*2f2c4c7aSAndroid Build Coastguard Worker sockaddr.family = AF_UNSPEC 612*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EAFNOSUPPORT, csocket.Bind, s6, sockaddr) 613*2f2c4c7aSAndroid Build Coastguard Worker s6.close() 614*2f2c4c7aSAndroid Build Coastguard Worker 615*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6ScopedBind(self): 616*2f2c4c7aSAndroid Build Coastguard Worker # Can't bind to a link-local address without a scope ID. 617*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 618*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EINVAL, 619*2f2c4c7aSAndroid Build Coastguard Worker s.bind, (self.lladdr, 1026, 0, 0)) 620*2f2c4c7aSAndroid Build Coastguard Worker 621*2f2c4c7aSAndroid Build Coastguard Worker # Binding to a link-local address with a scope ID works, and the scope ID is 622*2f2c4c7aSAndroid Build Coastguard Worker # returned by a subsequent getsockname. On Python 2, getsockname returns 623*2f2c4c7aSAndroid Build Coastguard Worker # "fe80:1%foo". Strip it off, since the ifindex field in the return value is 624*2f2c4c7aSAndroid Build Coastguard Worker # what matters. 625*2f2c4c7aSAndroid Build Coastguard Worker s.bind((self.lladdr, 4646, 0, self.ifindex)) 626*2f2c4c7aSAndroid Build Coastguard Worker sockname = s.getsockname() 627*2f2c4c7aSAndroid Build Coastguard Worker expected = self.lladdr 628*2f2c4c7aSAndroid Build Coastguard Worker if "%" in sockname[0]: 629*2f2c4c7aSAndroid Build Coastguard Worker expected += "%" + self.ifname 630*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual((expected, 4646, 0, self.ifindex), sockname) 631*2f2c4c7aSAndroid Build Coastguard Worker 632*2f2c4c7aSAndroid Build Coastguard Worker # Of course, for the above to work the address actually has to be configured 633*2f2c4c7aSAndroid Build Coastguard Worker # on the machine. 634*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EADDRNOTAVAIL, 635*2f2c4c7aSAndroid Build Coastguard Worker s.bind, ("fe80::f00", 1026, 0, 1)) 636*2f2c4c7aSAndroid Build Coastguard Worker s.close() 637*2f2c4c7aSAndroid Build Coastguard Worker 638*2f2c4c7aSAndroid Build Coastguard Worker # Scope IDs on non-link-local addresses are silently ignored. 639*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 640*2f2c4c7aSAndroid Build Coastguard Worker s.bind(("::1", 1234, 0, 1)) 641*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(("::1", 1234, 0, 0), s.getsockname()) 642*2f2c4c7aSAndroid Build Coastguard Worker s.close() 643*2f2c4c7aSAndroid Build Coastguard Worker 644*2f2c4c7aSAndroid Build Coastguard Worker def testBindAffectsIdentifier(self): 645*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 646*2f2c4c7aSAndroid Build Coastguard Worker s.bind((self.globaladdr, 0xf976)) 647*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 55)) 648*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(b"\xf9\x76", s.recv(32768)[4:6]) 649*2f2c4c7aSAndroid Build Coastguard Worker s.close() 650*2f2c4c7aSAndroid Build Coastguard Worker 651*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 652*2f2c4c7aSAndroid Build Coastguard Worker s.bind((self.globaladdr, 0xace)) 653*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 55)) 654*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(b"\x0a\xce", s.recv(32768)[4:6]) 655*2f2c4c7aSAndroid Build Coastguard Worker s.close() 656*2f2c4c7aSAndroid Build Coastguard Worker 657*2f2c4c7aSAndroid Build Coastguard Worker def testLinkLocalAddress(self): 658*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 659*2f2c4c7aSAndroid Build Coastguard Worker # Sending to a link-local address with no scope fails with EINVAL. 660*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EINVAL, 661*2f2c4c7aSAndroid Build Coastguard Worker s.sendto, net_test.IPV6_PING, ("fe80::1", 55)) 662*2f2c4c7aSAndroid Build Coastguard Worker # Sending to link-local address with a scope succeeds. Note that Python 663*2f2c4c7aSAndroid Build Coastguard Worker # doesn't understand the "fe80::1%lo" format, even though it returns it. 664*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV6_PING, ("fe80::1", 55, 0, self.ifindex)) 665*2f2c4c7aSAndroid Build Coastguard Worker # No exceptions? Good. 666*2f2c4c7aSAndroid Build Coastguard Worker s.close() 667*2f2c4c7aSAndroid Build Coastguard Worker 668*2f2c4c7aSAndroid Build Coastguard Worker def testLinkLocalOif(self): 669*2f2c4c7aSAndroid Build Coastguard Worker """Checks that ping to link-local addresses works correctly. 670*2f2c4c7aSAndroid Build Coastguard Worker 671*2f2c4c7aSAndroid Build Coastguard Worker Relevant kernel commits: 672*2f2c4c7aSAndroid Build Coastguard Worker upstream net: 673*2f2c4c7aSAndroid Build Coastguard Worker 5e45789 net: ipv6: Fix ping to link-local addresses. 674*2f2c4c7aSAndroid Build Coastguard Worker """ 675*2f2c4c7aSAndroid Build Coastguard Worker for mode in ["oif", "ucast_oif", None]: 676*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 677*2f2c4c7aSAndroid Build Coastguard Worker for netid in self.NETIDS: 678*2f2c4c7aSAndroid Build Coastguard Worker s2 = net_test.IPv6PingSocket() 679*2f2c4c7aSAndroid Build Coastguard Worker dst = self._RouterAddress(netid, 6) 680*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(dst.startswith("fe80:")) 681*2f2c4c7aSAndroid Build Coastguard Worker 682*2f2c4c7aSAndroid Build Coastguard Worker if mode: 683*2f2c4c7aSAndroid Build Coastguard Worker self.SelectInterface(s, netid, mode) 684*2f2c4c7aSAndroid Build Coastguard Worker self.SelectInterface(s2, netid, mode) 685*2f2c4c7aSAndroid Build Coastguard Worker scopeid = 0 686*2f2c4c7aSAndroid Build Coastguard Worker else: 687*2f2c4c7aSAndroid Build Coastguard Worker scopeid = self.ifindices[netid] 688*2f2c4c7aSAndroid Build Coastguard Worker 689*2f2c4c7aSAndroid Build Coastguard Worker if mode == "oif": 690*2f2c4c7aSAndroid Build Coastguard Worker # If SO_BINDTODEVICE has been set, any attempt to send on another 691*2f2c4c7aSAndroid Build Coastguard Worker # interface returns EINVAL. 692*2f2c4c7aSAndroid Build Coastguard Worker othernetid = self.NETIDS[(self.NETIDS.index(netid) + 1) 693*2f2c4c7aSAndroid Build Coastguard Worker % len(self.NETIDS)] 694*2f2c4c7aSAndroid Build Coastguard Worker otherscopeid = self.ifindices[othernetid] 695*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno( 696*2f2c4c7aSAndroid Build Coastguard Worker errno.EINVAL, 697*2f2c4c7aSAndroid Build Coastguard Worker s.sendto, net_test.IPV6_PING, (dst, 55, 0, otherscopeid)) 698*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno( 699*2f2c4c7aSAndroid Build Coastguard Worker errno.EINVAL, 700*2f2c4c7aSAndroid Build Coastguard Worker s.connect, (dst, 55, 0, otherscopeid)) 701*2f2c4c7aSAndroid Build Coastguard Worker 702*2f2c4c7aSAndroid Build Coastguard Worker # Try using both sendto and connect/send. 703*2f2c4c7aSAndroid Build Coastguard Worker # If we get a reply, we sent the packet out on the right interface. 704*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV6_PING, (dst, 123, 0, scopeid)) 705*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s, net_test.IPV6_PING) 706*2f2c4c7aSAndroid Build Coastguard Worker 707*2f2c4c7aSAndroid Build Coastguard Worker # IPV6_UNICAST_IF doesn't work on connected sockets. 708*2f2c4c7aSAndroid Build Coastguard Worker if mode != "ucast_oif": 709*2f2c4c7aSAndroid Build Coastguard Worker s2.connect((dst, 123, 0, scopeid)) 710*2f2c4c7aSAndroid Build Coastguard Worker s2.send(net_test.IPV6_PING) 711*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s2, net_test.IPV6_PING) 712*2f2c4c7aSAndroid Build Coastguard Worker s2.close() 713*2f2c4c7aSAndroid Build Coastguard Worker s.close() 714*2f2c4c7aSAndroid Build Coastguard Worker 715*2f2c4c7aSAndroid Build Coastguard Worker def testMappedAddressFails(self): 716*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 717*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 55)) 718*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s, net_test.IPV6_PING) 719*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV6_PING, ("2001:4860:4860::8844", 55)) 720*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s, net_test.IPV6_PING) 721*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EINVAL, s.sendto, net_test.IPV6_PING, 722*2f2c4c7aSAndroid Build Coastguard Worker ("::ffff:192.0.2.1", 55)) 723*2f2c4c7aSAndroid Build Coastguard Worker s.close() 724*2f2c4c7aSAndroid Build Coastguard Worker 725*2f2c4c7aSAndroid Build Coastguard Worker @unittest.skipUnless(False, "skipping: does not work yet") 726*2f2c4c7aSAndroid Build Coastguard Worker def testFlowLabel(self): 727*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 728*2f2c4c7aSAndroid Build Coastguard Worker 729*2f2c4c7aSAndroid Build Coastguard Worker # Specifying a flowlabel without having set IPV6_FLOWINFO_SEND succeeds but 730*2f2c4c7aSAndroid Build Coastguard Worker # the flow label in the packet is not set. 731*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 93, 0xdead, 0)) 732*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s, net_test.IPV6_PING) # Checks flow label==0. 733*2f2c4c7aSAndroid Build Coastguard Worker 734*2f2c4c7aSAndroid Build Coastguard Worker # If IPV6_FLOWINFO_SEND is set on the socket, attempting to set a flow label 735*2f2c4c7aSAndroid Build Coastguard Worker # that is not registered with the flow manager should return EINVAL... 736*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_FLOWINFO_SEND, 1) 737*2f2c4c7aSAndroid Build Coastguard Worker # ... but this doesn't work yet. 738*2f2c4c7aSAndroid Build Coastguard Worker if False: # pylint: disable=using-constant-test 739*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EINVAL, s.sendto, net_test.IPV6_PING, 740*2f2c4c7aSAndroid Build Coastguard Worker (net_test.IPV6_ADDR, 93, 0xdead, 0)) 741*2f2c4c7aSAndroid Build Coastguard Worker 742*2f2c4c7aSAndroid Build Coastguard Worker # After registering the flow label, it gets sent properly, appears in the 743*2f2c4c7aSAndroid Build Coastguard Worker # output packet, and is returned in the response. 744*2f2c4c7aSAndroid Build Coastguard Worker net_test.SetFlowLabel(s, net_test.IPV6_ADDR, 0xdead) 745*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(1, s.getsockopt(net_test.SOL_IPV6, 746*2f2c4c7aSAndroid Build Coastguard Worker net_test.IPV6_FLOWINFO_SEND)) 747*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 93, 0xdead, 0)) 748*2f2c4c7aSAndroid Build Coastguard Worker _, src = s.recvfrom(32768) 749*2f2c4c7aSAndroid Build Coastguard Worker _, _, flowlabel, _ = src 750*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(0xdead, flowlabel & 0xfffff) 751*2f2c4c7aSAndroid Build Coastguard Worker s.close() 752*2f2c4c7aSAndroid Build Coastguard Worker 753*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4Error(self): 754*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv4PingSocket() 755*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(SOL_IP, IP_TTL, 2) 756*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(SOL_IP, net_test.IP_RECVERR, 1) 757*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV4_PING, (net_test.IPV4_ADDR, 55)) 758*2f2c4c7aSAndroid Build Coastguard Worker # We can't check the actual error because Python 2.7 doesn't implement 759*2f2c4c7aSAndroid Build Coastguard Worker # recvmsg, but we can at least check that the socket returns an error. 760*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EHOSTUNREACH, s.recv, 32768) # No response. 761*2f2c4c7aSAndroid Build Coastguard Worker s.close() 762*2f2c4c7aSAndroid Build Coastguard Worker 763*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6Error(self): 764*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 765*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, IPV6_UNICAST_HOPS, 2) 766*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_RECVERR, 1) 767*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 55)) 768*2f2c4c7aSAndroid Build Coastguard Worker # We can't check the actual error because Python 2.7 doesn't implement 769*2f2c4c7aSAndroid Build Coastguard Worker # recvmsg, but we can at least check that the socket returns an error. 770*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EHOSTUNREACH, s.recv, 32768) # No response. 771*2f2c4c7aSAndroid Build Coastguard Worker s.close() 772*2f2c4c7aSAndroid Build Coastguard Worker 773*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6MulticastPing(self): 774*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 775*2f2c4c7aSAndroid Build Coastguard Worker # Send a multicast ping and check we get at least one duplicate. 776*2f2c4c7aSAndroid Build Coastguard Worker # The setsockopt should not be necessary, but ping_v6_sendmsg has a bug. 777*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_MULTICAST_IF, self.ifindex) 778*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV6_PING, ("ff02::1", 55, 0, self.ifindex)) 779*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s, net_test.IPV6_PING) 780*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s, net_test.IPV6_PING) 781*2f2c4c7aSAndroid Build Coastguard Worker s.close() 782*2f2c4c7aSAndroid Build Coastguard Worker 783*2f2c4c7aSAndroid Build Coastguard Worker def testIPv4LargePacket(self): 784*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv4PingSocket() 785*2f2c4c7aSAndroid Build Coastguard Worker data = net_test.IPV4_PING + 20000 * b"a" 786*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(data, ("127.0.0.1", 987)) 787*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s, data) 788*2f2c4c7aSAndroid Build Coastguard Worker s.close() 789*2f2c4c7aSAndroid Build Coastguard Worker 790*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6LargePacket(self): 791*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 792*2f2c4c7aSAndroid Build Coastguard Worker s.bind(("::", 0xace)) 793*2f2c4c7aSAndroid Build Coastguard Worker data = net_test.IPV6_PING + b"\x01" + 19994 * b"\x00" + b"aaaaa" 794*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(data, ("::1", 953)) 795*2f2c4c7aSAndroid Build Coastguard Worker s.close() 796*2f2c4c7aSAndroid Build Coastguard Worker 797*2f2c4c7aSAndroid Build Coastguard Worker def testIcmpSocketsNotInIcmp6(self): 798*2f2c4c7aSAndroid Build Coastguard Worker numrows = len(self.ReadProcNetSocket("icmp")) 799*2f2c4c7aSAndroid Build Coastguard Worker numrows6 = len(self.ReadProcNetSocket("icmp6")) 800*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.Socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP) 801*2f2c4c7aSAndroid Build Coastguard Worker s.bind(("127.0.0.1", 0xace)) 802*2f2c4c7aSAndroid Build Coastguard Worker s.connect(("127.0.0.1", 0xbeef)) 803*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(numrows + 1, len(self.ReadProcNetSocket("icmp"))) 804*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(numrows6, len(self.ReadProcNetSocket("icmp6"))) 805*2f2c4c7aSAndroid Build Coastguard Worker s.close() 806*2f2c4c7aSAndroid Build Coastguard Worker 807*2f2c4c7aSAndroid Build Coastguard Worker def testIcmp6SocketsNotInIcmp(self): 808*2f2c4c7aSAndroid Build Coastguard Worker numrows = len(self.ReadProcNetSocket("icmp")) 809*2f2c4c7aSAndroid Build Coastguard Worker numrows6 = len(self.ReadProcNetSocket("icmp6")) 810*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 811*2f2c4c7aSAndroid Build Coastguard Worker s.bind(("::1", 0xace)) 812*2f2c4c7aSAndroid Build Coastguard Worker s.connect(("::1", 0xbeef)) 813*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(numrows, len(self.ReadProcNetSocket("icmp"))) 814*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(numrows6 + 1, len(self.ReadProcNetSocket("icmp6"))) 815*2f2c4c7aSAndroid Build Coastguard Worker s.close() 816*2f2c4c7aSAndroid Build Coastguard Worker 817*2f2c4c7aSAndroid Build Coastguard Worker def testProcNetIcmp(self): 818*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.Socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP) 819*2f2c4c7aSAndroid Build Coastguard Worker s.bind(("127.0.0.1", 0xace)) 820*2f2c4c7aSAndroid Build Coastguard Worker s.connect(("127.0.0.1", 0xbeef)) 821*2f2c4c7aSAndroid Build Coastguard Worker self.CheckSockStatFile("icmp", "127.0.0.1", 0xace, "127.0.0.1", 0xbeef, 1) 822*2f2c4c7aSAndroid Build Coastguard Worker s.close() 823*2f2c4c7aSAndroid Build Coastguard Worker 824*2f2c4c7aSAndroid Build Coastguard Worker def testProcNetIcmp6(self): 825*2f2c4c7aSAndroid Build Coastguard Worker numrows6 = len(self.ReadProcNetSocket("icmp6")) 826*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 827*2f2c4c7aSAndroid Build Coastguard Worker s.bind(("::1", 0xace)) 828*2f2c4c7aSAndroid Build Coastguard Worker s.connect(("::1", 0xbeef)) 829*2f2c4c7aSAndroid Build Coastguard Worker self.CheckSockStatFile("icmp6", "::1", 0xace, "::1", 0xbeef, 1) 830*2f2c4c7aSAndroid Build Coastguard Worker 831*2f2c4c7aSAndroid Build Coastguard Worker # Check the row goes away when the socket is closed. 832*2f2c4c7aSAndroid Build Coastguard Worker s.close() 833*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(numrows6, len(self.ReadProcNetSocket("icmp6"))) 834*2f2c4c7aSAndroid Build Coastguard Worker 835*2f2c4c7aSAndroid Build Coastguard Worker # Try send, bind and connect to check the addresses and the state. 836*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 837*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(0, len(self.ReadProcNetSocket("icmp6"))) 838*2f2c4c7aSAndroid Build Coastguard Worker s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 12345)) 839*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(1, len(self.ReadProcNetSocket("icmp6"))) 840*2f2c4c7aSAndroid Build Coastguard Worker s.close() 841*2f2c4c7aSAndroid Build Coastguard Worker 842*2f2c4c7aSAndroid Build Coastguard Worker # Can't bind after sendto, apparently. 843*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 844*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(0, len(self.ReadProcNetSocket("icmp6"))) 845*2f2c4c7aSAndroid Build Coastguard Worker s.bind((self.lladdr, 0xd00d, 0, self.ifindex)) 846*2f2c4c7aSAndroid Build Coastguard Worker self.CheckSockStatFile("icmp6", self.lladdr, 0xd00d, "::", 0, 7) 847*2f2c4c7aSAndroid Build Coastguard Worker 848*2f2c4c7aSAndroid Build Coastguard Worker # Check receive bytes. 849*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_MULTICAST_IF, self.ifindex) 850*2f2c4c7aSAndroid Build Coastguard Worker s.connect(("ff02::1", 0xdead)) 851*2f2c4c7aSAndroid Build Coastguard Worker self.CheckSockStatFile("icmp6", self.lladdr, 0xd00d, "ff02::1", 0xdead, 1) 852*2f2c4c7aSAndroid Build Coastguard Worker s.send(net_test.IPV6_PING) 853*2f2c4c7aSAndroid Build Coastguard Worker s.recvfrom(32768, MSG_PEEK) # Wait until the receive thread replies. 854*2f2c4c7aSAndroid Build Coastguard Worker self.CheckSockStatFile("icmp6", self.lladdr, 0xd00d, "ff02::1", 0xdead, 1, 855*2f2c4c7aSAndroid Build Coastguard Worker txmem=0, rxmem=0x300) 856*2f2c4c7aSAndroid Build Coastguard Worker self.assertValidPingResponse(s, net_test.IPV6_PING) 857*2f2c4c7aSAndroid Build Coastguard Worker self.CheckSockStatFile("icmp6", self.lladdr, 0xd00d, "ff02::1", 0xdead, 1, 858*2f2c4c7aSAndroid Build Coastguard Worker txmem=0, rxmem=0) 859*2f2c4c7aSAndroid Build Coastguard Worker s.close() 860*2f2c4c7aSAndroid Build Coastguard Worker 861*2f2c4c7aSAndroid Build Coastguard Worker def testProcNetUdp6(self): 862*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.Socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP) 863*2f2c4c7aSAndroid Build Coastguard Worker s.bind(("::1", 0xace)) 864*2f2c4c7aSAndroid Build Coastguard Worker s.connect(("::1", 0xbeef)) 865*2f2c4c7aSAndroid Build Coastguard Worker self.CheckSockStatFile("udp6", "::1", 0xace, "::1", 0xbeef, 1) 866*2f2c4c7aSAndroid Build Coastguard Worker s.close() 867*2f2c4c7aSAndroid Build Coastguard Worker 868*2f2c4c7aSAndroid Build Coastguard Worker def testProcNetRaw6(self): 869*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.Socket(AF_INET6, SOCK_RAW, IPPROTO_RAW) 870*2f2c4c7aSAndroid Build Coastguard Worker s.bind(("::1", 0xace)) 871*2f2c4c7aSAndroid Build Coastguard Worker s.connect(("::1", 0xbeef)) 872*2f2c4c7aSAndroid Build Coastguard Worker self.CheckSockStatFile("raw6", "::1", 0xff, "::1", 0, 1) 873*2f2c4c7aSAndroid Build Coastguard Worker s.close() 874*2f2c4c7aSAndroid Build Coastguard Worker 875*2f2c4c7aSAndroid Build Coastguard Worker def testIPv6MTU(self): 876*2f2c4c7aSAndroid Build Coastguard Worker """Tests IPV6_RECVERR and path MTU discovery on ping sockets. 877*2f2c4c7aSAndroid Build Coastguard Worker 878*2f2c4c7aSAndroid Build Coastguard Worker Relevant kernel commits: 879*2f2c4c7aSAndroid Build Coastguard Worker upstream net-next: 880*2f2c4c7aSAndroid Build Coastguard Worker dcb94b8 ipv6: fix endianness error in icmpv6_err 881*2f2c4c7aSAndroid Build Coastguard Worker """ 882*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.IPv6PingSocket() 883*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, csocket.IPV6_DONTFRAG, 1) 884*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, csocket.IPV6_MTU_DISCOVER, 2) 885*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_RECVERR, 1) 886*2f2c4c7aSAndroid Build Coastguard Worker s.connect((net_test.IPV6_ADDR, 55)) 887*2f2c4c7aSAndroid Build Coastguard Worker pkt = net_test.IPV6_PING + (PingReplyThread.LINK_MTU + 100) * b"a" 888*2f2c4c7aSAndroid Build Coastguard Worker s.send(pkt) 889*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EMSGSIZE, s.recv, 32768) 890*2f2c4c7aSAndroid Build Coastguard Worker data, addr, cmsg = csocket.Recvmsg(s, 4096, 1024, csocket.MSG_ERRQUEUE) 891*2f2c4c7aSAndroid Build Coastguard Worker 892*2f2c4c7aSAndroid Build Coastguard Worker # Compare the offending packet with the one we sent. To do this we need to 893*2f2c4c7aSAndroid Build Coastguard Worker # calculate the ident of the packet we sent and blank out the checksum of 894*2f2c4c7aSAndroid Build Coastguard Worker # the one we received. 895*2f2c4c7aSAndroid Build Coastguard Worker ident = struct.pack("!H", s.getsockname()[1]) 896*2f2c4c7aSAndroid Build Coastguard Worker pkt = pkt[:4] + ident + pkt[6:] 897*2f2c4c7aSAndroid Build Coastguard Worker data = data[:2] + b"\x00\x00" + pkt[4:] 898*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(pkt, data) 899*2f2c4c7aSAndroid Build Coastguard Worker 900*2f2c4c7aSAndroid Build Coastguard Worker # Check the address that the packet was sent to. 901*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(csocket.Sockaddr(("2001:4860:4860::8888", 0)), addr) 902*2f2c4c7aSAndroid Build Coastguard Worker 903*2f2c4c7aSAndroid Build Coastguard Worker # Check the cmsg data, including the link MTU. 904*2f2c4c7aSAndroid Build Coastguard Worker mtu = PingReplyThread.LINK_MTU 905*2f2c4c7aSAndroid Build Coastguard Worker src = self.reply_threads[self.netid].INTERMEDIATE_IPV6 906*2f2c4c7aSAndroid Build Coastguard Worker msglist = [ 907*2f2c4c7aSAndroid Build Coastguard Worker (net_test.SOL_IPV6, net_test.IPV6_RECVERR, 908*2f2c4c7aSAndroid Build Coastguard Worker (csocket.SockExtendedErr((errno.EMSGSIZE, csocket.SO_ORIGIN_ICMP6, 909*2f2c4c7aSAndroid Build Coastguard Worker ICMPV6_PKT_TOOBIG, 0, mtu, 0)), 910*2f2c4c7aSAndroid Build Coastguard Worker csocket.Sockaddr((src, 0)))) 911*2f2c4c7aSAndroid Build Coastguard Worker ] 912*2f2c4c7aSAndroid Build Coastguard Worker 913*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(msglist, cmsg) 914*2f2c4c7aSAndroid Build Coastguard Worker s.close() 915*2f2c4c7aSAndroid Build Coastguard Worker 916*2f2c4c7aSAndroid Build Coastguard Worker 917*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__": 918*2f2c4c7aSAndroid Build Coastguard Worker unittest.main() 919