xref: /aosp_15_r20/kernel/tests/net/test/ping6_test.py (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3
2*2f2c4c7aSAndroid Build Coastguard Worker#
3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2014 The Android Open Source Project
4*2f2c4c7aSAndroid Build Coastguard Worker#
5*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*2f2c4c7aSAndroid Build Coastguard Worker#
9*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0
10*2f2c4c7aSAndroid Build Coastguard Worker#
11*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License.
16*2f2c4c7aSAndroid Build Coastguard Worker
17*2f2c4c7aSAndroid Build Coastguard 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