xref: /aosp_15_r20/kernel/tests/net/test/sock_diag_test.py (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3
2*2f2c4c7aSAndroid Build Coastguard Worker#
3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2015 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,g-bad-file-header,wildcard-import
18*2f2c4c7aSAndroid Build Coastguard Workerfrom errno import *  # pylint: disable=wildcard-import
19*2f2c4c7aSAndroid Build Coastguard Workerimport binascii
20*2f2c4c7aSAndroid Build Coastguard Workerimport os
21*2f2c4c7aSAndroid Build Coastguard Workerimport random
22*2f2c4c7aSAndroid Build Coastguard Workerimport select
23*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import *  # pylint: disable=wildcard-import
24*2f2c4c7aSAndroid Build Coastguard Workerimport struct
25*2f2c4c7aSAndroid Build Coastguard Workerimport threading
26*2f2c4c7aSAndroid Build Coastguard Workerimport time
27*2f2c4c7aSAndroid Build Coastguard Workerimport unittest
28*2f2c4c7aSAndroid Build Coastguard Worker
29*2f2c4c7aSAndroid Build Coastguard Workerimport cstruct
30*2f2c4c7aSAndroid Build Coastguard Workerimport multinetwork_base
31*2f2c4c7aSAndroid Build Coastguard Workerimport net_test
32*2f2c4c7aSAndroid Build Coastguard Workerimport packets
33*2f2c4c7aSAndroid Build Coastguard Workerimport sock_diag
34*2f2c4c7aSAndroid Build Coastguard Workerimport tcp_test
35*2f2c4c7aSAndroid Build Coastguard Worker
36*2f2c4c7aSAndroid Build Coastguard Worker# Mostly empty structure definition containing only the fields we currently use.
37*2f2c4c7aSAndroid Build Coastguard WorkerTcpInfo = cstruct.Struct("TcpInfo", "64xI", "tcpi_rcv_ssthresh")
38*2f2c4c7aSAndroid Build Coastguard Worker
39*2f2c4c7aSAndroid Build Coastguard WorkerNUM_SOCKETS = 30
40*2f2c4c7aSAndroid Build Coastguard WorkerNO_BYTECODE = b""
41*2f2c4c7aSAndroid Build Coastguard Worker
42*2f2c4c7aSAndroid Build Coastguard WorkerIPPROTO_SCTP = 132
43*2f2c4c7aSAndroid Build Coastguard Worker
44*2f2c4c7aSAndroid Build Coastguard Workerdef HaveSctp():
45*2f2c4c7aSAndroid Build Coastguard Worker  try:
46*2f2c4c7aSAndroid Build Coastguard Worker    s = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)
47*2f2c4c7aSAndroid Build Coastguard Worker    s.close()
48*2f2c4c7aSAndroid Build Coastguard Worker    return True
49*2f2c4c7aSAndroid Build Coastguard Worker  except IOError:
50*2f2c4c7aSAndroid Build Coastguard Worker    return False
51*2f2c4c7aSAndroid Build Coastguard Worker
52*2f2c4c7aSAndroid Build Coastguard WorkerHAVE_SCTP = HaveSctp()
53*2f2c4c7aSAndroid Build Coastguard Worker
54*2f2c4c7aSAndroid Build Coastguard Worker
55*2f2c4c7aSAndroid Build Coastguard Workerclass SockDiagBaseTest(multinetwork_base.MultiNetworkBaseTest):
56*2f2c4c7aSAndroid Build Coastguard Worker  """Basic tests for SOCK_DIAG functionality.
57*2f2c4c7aSAndroid Build Coastguard Worker
58*2f2c4c7aSAndroid Build Coastguard Worker    Relevant kernel commits:
59*2f2c4c7aSAndroid Build Coastguard Worker      android-3.4:
60*2f2c4c7aSAndroid Build Coastguard Worker        ab4a727 net: inet_diag: zero out uninitialized idiag_{src,dst} fields
61*2f2c4c7aSAndroid Build Coastguard Worker        99ee451 net: diag: support v4mapped sockets in inet_diag_find_one_icsk()
62*2f2c4c7aSAndroid Build Coastguard Worker
63*2f2c4c7aSAndroid Build Coastguard Worker      android-3.10:
64*2f2c4c7aSAndroid Build Coastguard Worker        3eb409b net: inet_diag: zero out uninitialized idiag_{src,dst} fields
65*2f2c4c7aSAndroid Build Coastguard Worker        f77e059 net: diag: support v4mapped sockets in inet_diag_find_one_icsk()
66*2f2c4c7aSAndroid Build Coastguard Worker
67*2f2c4c7aSAndroid Build Coastguard Worker      android-3.18:
68*2f2c4c7aSAndroid Build Coastguard Worker        e603010 net: diag: support v4mapped sockets in inet_diag_find_one_icsk()
69*2f2c4c7aSAndroid Build Coastguard Worker
70*2f2c4c7aSAndroid Build Coastguard Worker      android-4.4:
71*2f2c4c7aSAndroid Build Coastguard Worker        525ee59 net: diag: support v4mapped sockets in inet_diag_find_one_icsk()
72*2f2c4c7aSAndroid Build Coastguard Worker  """
73*2f2c4c7aSAndroid Build Coastguard Worker  @staticmethod
74*2f2c4c7aSAndroid Build Coastguard Worker  def _CreateLotsOfSockets(socktype):
75*2f2c4c7aSAndroid Build Coastguard Worker    # Dict mapping (addr, sport, dport) tuples to socketpairs.
76*2f2c4c7aSAndroid Build Coastguard Worker    socketpairs = {}
77*2f2c4c7aSAndroid Build Coastguard Worker    for _ in range(NUM_SOCKETS):
78*2f2c4c7aSAndroid Build Coastguard Worker      family, addr = random.choice([
79*2f2c4c7aSAndroid Build Coastguard Worker          (AF_INET, "127.0.0.1"),
80*2f2c4c7aSAndroid Build Coastguard Worker          (AF_INET6, "::1"),
81*2f2c4c7aSAndroid Build Coastguard Worker          (AF_INET6, "::ffff:127.0.0.1")])
82*2f2c4c7aSAndroid Build Coastguard Worker      socketpair = net_test.CreateSocketPair(family, socktype, addr)
83*2f2c4c7aSAndroid Build Coastguard Worker      sport, dport = (socketpair[0].getsockname()[1],
84*2f2c4c7aSAndroid Build Coastguard Worker                      socketpair[1].getsockname()[1])
85*2f2c4c7aSAndroid Build Coastguard Worker      socketpairs[(addr, sport, dport)] = socketpair
86*2f2c4c7aSAndroid Build Coastguard Worker    return socketpairs
87*2f2c4c7aSAndroid Build Coastguard Worker
88*2f2c4c7aSAndroid Build Coastguard Worker  def assertSocketClosed(self, sock):
89*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(ENOTCONN, sock.getpeername)
90*2f2c4c7aSAndroid Build Coastguard Worker
91*2f2c4c7aSAndroid Build Coastguard Worker  def assertSocketConnected(self, sock):
92*2f2c4c7aSAndroid Build Coastguard Worker    sock.getpeername()  # No errors? Socket is alive and connected.
93*2f2c4c7aSAndroid Build Coastguard Worker
94*2f2c4c7aSAndroid Build Coastguard Worker  def assertSocketsClosed(self, socketpair):
95*2f2c4c7aSAndroid Build Coastguard Worker    for sock in socketpair:
96*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketClosed(sock)
97*2f2c4c7aSAndroid Build Coastguard Worker
98*2f2c4c7aSAndroid Build Coastguard Worker  def assertMarkIs(self, mark, attrs):
99*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(mark, attrs.get("INET_DIAG_MARK", None))
100*2f2c4c7aSAndroid Build Coastguard Worker
101*2f2c4c7aSAndroid Build Coastguard Worker  def assertSockInfoMatchesSocket(self, s, info):
102*2f2c4c7aSAndroid Build Coastguard Worker    diag_msg, attrs = info
103*2f2c4c7aSAndroid Build Coastguard Worker    family = s.getsockopt(net_test.SOL_SOCKET, net_test.SO_DOMAIN)
104*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(diag_msg.family, family)
105*2f2c4c7aSAndroid Build Coastguard Worker
106*2f2c4c7aSAndroid Build Coastguard Worker    src, sport = s.getsockname()[0:2]
107*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(diag_msg.id.src, self.sock_diag.PaddedAddress(src))
108*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(diag_msg.id.sport, sport)
109*2f2c4c7aSAndroid Build Coastguard Worker
110*2f2c4c7aSAndroid Build Coastguard Worker    if self.sock_diag.GetDestinationAddress(diag_msg) not in ["0.0.0.0", "::"]:
111*2f2c4c7aSAndroid Build Coastguard Worker      dst, dport = s.getpeername()[0:2]
112*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(diag_msg.id.dst, self.sock_diag.PaddedAddress(dst))
113*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(diag_msg.id.dport, dport)
114*2f2c4c7aSAndroid Build Coastguard Worker    else:
115*2f2c4c7aSAndroid Build Coastguard Worker      self.assertRaisesErrno(ENOTCONN, s.getpeername)
116*2f2c4c7aSAndroid Build Coastguard Worker
117*2f2c4c7aSAndroid Build Coastguard Worker    mark = s.getsockopt(SOL_SOCKET, net_test.SO_MARK)
118*2f2c4c7aSAndroid Build Coastguard Worker    self.assertMarkIs(mark, attrs)
119*2f2c4c7aSAndroid Build Coastguard Worker
120*2f2c4c7aSAndroid Build Coastguard Worker  def PackAndCheckBytecode(self, instructions):
121*2f2c4c7aSAndroid Build Coastguard Worker    bytecode = self.sock_diag.PackBytecode(instructions)
122*2f2c4c7aSAndroid Build Coastguard Worker    decoded = self.sock_diag.DecodeBytecode(bytecode)
123*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(len(instructions), len(decoded))
124*2f2c4c7aSAndroid Build Coastguard Worker    self.assertFalse("???" in decoded)
125*2f2c4c7aSAndroid Build Coastguard Worker    return bytecode
126*2f2c4c7aSAndroid Build Coastguard Worker
127*2f2c4c7aSAndroid Build Coastguard Worker  def _EventDuringBlockingCall(self, sock, call, expected_errno, event):
128*2f2c4c7aSAndroid Build Coastguard Worker    """Simulates an external event during a blocking call on sock.
129*2f2c4c7aSAndroid Build Coastguard Worker
130*2f2c4c7aSAndroid Build Coastguard Worker    Args:
131*2f2c4c7aSAndroid Build Coastguard Worker      sock: The socket to use.
132*2f2c4c7aSAndroid Build Coastguard Worker      call: A function, the call to make. Takes one parameter, sock.
133*2f2c4c7aSAndroid Build Coastguard Worker      expected_errno: The value that call is expected to fail with, or None if
134*2f2c4c7aSAndroid Build Coastguard Worker        call is expected to succeed.
135*2f2c4c7aSAndroid Build Coastguard Worker      event: A function, the event that will happen during the blocking call.
136*2f2c4c7aSAndroid Build Coastguard Worker        Takes one parameter, sock.
137*2f2c4c7aSAndroid Build Coastguard Worker    """
138*2f2c4c7aSAndroid Build Coastguard Worker    thread = SocketExceptionThread(sock, call)
139*2f2c4c7aSAndroid Build Coastguard Worker    thread.start()
140*2f2c4c7aSAndroid Build Coastguard Worker    time.sleep(0.1)
141*2f2c4c7aSAndroid Build Coastguard Worker    event(sock)
142*2f2c4c7aSAndroid Build Coastguard Worker    thread.join(1)
143*2f2c4c7aSAndroid Build Coastguard Worker    self.assertFalse(thread.is_alive())
144*2f2c4c7aSAndroid Build Coastguard Worker    if expected_errno is not None:
145*2f2c4c7aSAndroid Build Coastguard Worker      self.assertIsNotNone(thread.exception)
146*2f2c4c7aSAndroid Build Coastguard Worker      self.assertTrue(isinstance(thread.exception, IOError),
147*2f2c4c7aSAndroid Build Coastguard Worker                      "Expected IOError, got %s" % thread.exception)
148*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(expected_errno, thread.exception.errno)
149*2f2c4c7aSAndroid Build Coastguard Worker    else:
150*2f2c4c7aSAndroid Build Coastguard Worker      self.assertIsNone(thread.exception)
151*2f2c4c7aSAndroid Build Coastguard Worker    self.assertSocketClosed(sock)
152*2f2c4c7aSAndroid Build Coastguard Worker
153*2f2c4c7aSAndroid Build Coastguard Worker  def CloseDuringBlockingCall(self, sock, call, expected_errno):
154*2f2c4c7aSAndroid Build Coastguard Worker    self._EventDuringBlockingCall(
155*2f2c4c7aSAndroid Build Coastguard Worker        sock, call, expected_errno,
156*2f2c4c7aSAndroid Build Coastguard Worker        lambda sock: self.sock_diag.CloseSocketFromFd(sock))
157*2f2c4c7aSAndroid Build Coastguard Worker
158*2f2c4c7aSAndroid Build Coastguard Worker  def setUp(self):
159*2f2c4c7aSAndroid Build Coastguard Worker    super(SockDiagBaseTest, self).setUp()
160*2f2c4c7aSAndroid Build Coastguard Worker    self.sock_diag = sock_diag.SockDiag()
161*2f2c4c7aSAndroid Build Coastguard Worker    self.socketpairs = {}
162*2f2c4c7aSAndroid Build Coastguard Worker
163*2f2c4c7aSAndroid Build Coastguard Worker  def tearDown(self):
164*2f2c4c7aSAndroid Build Coastguard Worker    for socketpair in list(self.socketpairs.values()):
165*2f2c4c7aSAndroid Build Coastguard Worker      for s in socketpair:
166*2f2c4c7aSAndroid Build Coastguard Worker        s.close()
167*2f2c4c7aSAndroid Build Coastguard Worker    super(SockDiagBaseTest, self).tearDown()
168*2f2c4c7aSAndroid Build Coastguard Worker
169*2f2c4c7aSAndroid Build Coastguard Worker
170*2f2c4c7aSAndroid Build Coastguard Workerclass SockDiagTest(SockDiagBaseTest):
171*2f2c4c7aSAndroid Build Coastguard Worker
172*2f2c4c7aSAndroid Build Coastguard Worker  def testFindsMappedSockets(self):
173*2f2c4c7aSAndroid Build Coastguard Worker    """Tests that inet_diag_find_one_icsk can find mapped sockets."""
174*2f2c4c7aSAndroid Build Coastguard Worker    socketpair = net_test.CreateSocketPair(AF_INET6, SOCK_STREAM,
175*2f2c4c7aSAndroid Build Coastguard Worker                                           "::ffff:127.0.0.1")
176*2f2c4c7aSAndroid Build Coastguard Worker    for sock in socketpair:
177*2f2c4c7aSAndroid Build Coastguard Worker      diag_msg = self.sock_diag.FindSockDiagFromFd(sock)
178*2f2c4c7aSAndroid Build Coastguard Worker      diag_req = self.sock_diag.DiagReqFromDiagMsg(diag_msg, IPPROTO_TCP)
179*2f2c4c7aSAndroid Build Coastguard Worker      self.sock_diag.GetSockInfo(diag_req)
180*2f2c4c7aSAndroid Build Coastguard Worker      # No errors? Good.
181*2f2c4c7aSAndroid Build Coastguard Worker
182*2f2c4c7aSAndroid Build Coastguard Worker    for sock in socketpair:
183*2f2c4c7aSAndroid Build Coastguard Worker      sock.close()
184*2f2c4c7aSAndroid Build Coastguard Worker
185*2f2c4c7aSAndroid Build Coastguard Worker  def CheckFindsAllMySockets(self, socktype, proto):
186*2f2c4c7aSAndroid Build Coastguard Worker    """Tests that basic socket dumping works."""
187*2f2c4c7aSAndroid Build Coastguard Worker    self.socketpairs = self._CreateLotsOfSockets(socktype)
188*2f2c4c7aSAndroid Build Coastguard Worker    sockets = self.sock_diag.DumpAllInetSockets(proto, NO_BYTECODE)
189*2f2c4c7aSAndroid Build Coastguard Worker    self.assertGreaterEqual(len(sockets), NUM_SOCKETS)
190*2f2c4c7aSAndroid Build Coastguard Worker
191*2f2c4c7aSAndroid Build Coastguard Worker    # Find the cookies for all of our sockets.
192*2f2c4c7aSAndroid Build Coastguard Worker    cookies = {}
193*2f2c4c7aSAndroid Build Coastguard Worker    for diag_msg, unused_attrs in sockets:
194*2f2c4c7aSAndroid Build Coastguard Worker      addr = self.sock_diag.GetSourceAddress(diag_msg)
195*2f2c4c7aSAndroid Build Coastguard Worker      sport = diag_msg.id.sport
196*2f2c4c7aSAndroid Build Coastguard Worker      dport = diag_msg.id.dport
197*2f2c4c7aSAndroid Build Coastguard Worker      if (addr, sport, dport) in self.socketpairs:
198*2f2c4c7aSAndroid Build Coastguard Worker        cookies[(addr, sport, dport)] = diag_msg.id.cookie
199*2f2c4c7aSAndroid Build Coastguard Worker      elif (addr, dport, sport) in self.socketpairs:
200*2f2c4c7aSAndroid Build Coastguard Worker        cookies[(addr, sport, dport)] = diag_msg.id.cookie
201*2f2c4c7aSAndroid Build Coastguard Worker
202*2f2c4c7aSAndroid Build Coastguard Worker    # Did we find all the cookies?
203*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(2 * NUM_SOCKETS, len(cookies))
204*2f2c4c7aSAndroid Build Coastguard Worker
205*2f2c4c7aSAndroid Build Coastguard Worker    socketpairs = list(self.socketpairs.values())
206*2f2c4c7aSAndroid Build Coastguard Worker    random.shuffle(socketpairs)
207*2f2c4c7aSAndroid Build Coastguard Worker    for socketpair in socketpairs:
208*2f2c4c7aSAndroid Build Coastguard Worker      for sock in socketpair:
209*2f2c4c7aSAndroid Build Coastguard Worker        # Check that we can find a diag_msg by scanning a dump.
210*2f2c4c7aSAndroid Build Coastguard Worker        self.assertSockInfoMatchesSocket(
211*2f2c4c7aSAndroid Build Coastguard Worker            sock,
212*2f2c4c7aSAndroid Build Coastguard Worker            self.sock_diag.FindSockInfoFromFd(sock))
213*2f2c4c7aSAndroid Build Coastguard Worker        cookie = self.sock_diag.FindSockDiagFromFd(sock).id.cookie
214*2f2c4c7aSAndroid Build Coastguard Worker
215*2f2c4c7aSAndroid Build Coastguard Worker        # Check that we can find a diag_msg once we know the cookie.
216*2f2c4c7aSAndroid Build Coastguard Worker        req = self.sock_diag.DiagReqFromSocket(sock)
217*2f2c4c7aSAndroid Build Coastguard Worker        req.id.cookie = cookie
218*2f2c4c7aSAndroid Build Coastguard Worker        if proto == IPPROTO_UDP:
219*2f2c4c7aSAndroid Build Coastguard Worker          # Kernel bug: for UDP sockets, the order of arguments must be swapped.
220*2f2c4c7aSAndroid Build Coastguard Worker          # See testDemonstrateUdpGetSockIdBug.
221*2f2c4c7aSAndroid Build Coastguard Worker          req.id.sport, req.id.dport = req.id.dport, req.id.sport
222*2f2c4c7aSAndroid Build Coastguard Worker          req.id.src, req.id.dst = req.id.dst, req.id.src
223*2f2c4c7aSAndroid Build Coastguard Worker        info = self.sock_diag.GetSockInfo(req)
224*2f2c4c7aSAndroid Build Coastguard Worker        self.assertSockInfoMatchesSocket(sock, info)
225*2f2c4c7aSAndroid Build Coastguard Worker
226*2f2c4c7aSAndroid Build Coastguard Worker    for socketpair in socketpairs:
227*2f2c4c7aSAndroid Build Coastguard Worker      for sock in socketpair:
228*2f2c4c7aSAndroid Build Coastguard Worker        sock.close()
229*2f2c4c7aSAndroid Build Coastguard Worker
230*2f2c4c7aSAndroid Build Coastguard Worker  def assertItemsEqual(self, expected, actual):
231*2f2c4c7aSAndroid Build Coastguard Worker    try:
232*2f2c4c7aSAndroid Build Coastguard Worker      super(SockDiagTest, self).assertItemsEqual(expected, actual)
233*2f2c4c7aSAndroid Build Coastguard Worker    except AttributeError:
234*2f2c4c7aSAndroid Build Coastguard Worker      # This was renamed in python3 but has the same behaviour.
235*2f2c4c7aSAndroid Build Coastguard Worker      super(SockDiagTest, self).assertCountEqual(expected, actual)
236*2f2c4c7aSAndroid Build Coastguard Worker
237*2f2c4c7aSAndroid Build Coastguard Worker  def testFindsAllMySocketsTcp(self):
238*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckFindsAllMySockets(SOCK_STREAM, IPPROTO_TCP)
239*2f2c4c7aSAndroid Build Coastguard Worker
240*2f2c4c7aSAndroid Build Coastguard Worker  def testFindsAllMySocketsUdp(self):
241*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckFindsAllMySockets(SOCK_DGRAM, IPPROTO_UDP)
242*2f2c4c7aSAndroid Build Coastguard Worker
243*2f2c4c7aSAndroid Build Coastguard Worker  def testBytecodeCompilation(self):
244*2f2c4c7aSAndroid Build Coastguard Worker    # pylint: disable=bad-whitespace
245*2f2c4c7aSAndroid Build Coastguard Worker    instructions = [
246*2f2c4c7aSAndroid Build Coastguard Worker        (sock_diag.INET_DIAG_BC_S_GE,   1, 8, 0),                      # 0
247*2f2c4c7aSAndroid Build Coastguard Worker        (sock_diag.INET_DIAG_BC_D_LE,   1, 7, 0xffff),                 # 8
248*2f2c4c7aSAndroid Build Coastguard Worker        (sock_diag.INET_DIAG_BC_S_COND, 1, 2, ("::1", 128, -1)),       # 16
249*2f2c4c7aSAndroid Build Coastguard Worker        (sock_diag.INET_DIAG_BC_JMP,    1, 3, None),                   # 44
250*2f2c4c7aSAndroid Build Coastguard Worker        (sock_diag.INET_DIAG_BC_S_COND, 2, 4, ("127.0.0.1", 32, -1)),  # 48
251*2f2c4c7aSAndroid Build Coastguard Worker        (sock_diag.INET_DIAG_BC_D_LE,   1, 3, 0x6665),  # not used     # 64
252*2f2c4c7aSAndroid Build Coastguard Worker        (sock_diag.INET_DIAG_BC_NOP,    1, 1, None),                   # 72
253*2f2c4c7aSAndroid Build Coastguard Worker                                                                       # 76 acc
254*2f2c4c7aSAndroid Build Coastguard Worker                                                                       # 80 rej
255*2f2c4c7aSAndroid Build Coastguard Worker    ]
256*2f2c4c7aSAndroid Build Coastguard Worker    # pylint: enable=bad-whitespace
257*2f2c4c7aSAndroid Build Coastguard Worker    bytecode = self.PackAndCheckBytecode(instructions)
258*2f2c4c7aSAndroid Build Coastguard Worker    expected = (
259*2f2c4c7aSAndroid Build Coastguard Worker        b"0208500000000000"
260*2f2c4c7aSAndroid Build Coastguard Worker        b"050848000000ffff"
261*2f2c4c7aSAndroid Build Coastguard Worker        b"071c20000a800000ffffffff00000000000000000000000000000001"
262*2f2c4c7aSAndroid Build Coastguard Worker        b"01041c00"
263*2f2c4c7aSAndroid Build Coastguard Worker        b"0718200002200000ffffffff7f000001"
264*2f2c4c7aSAndroid Build Coastguard Worker        b"0508100000006566"
265*2f2c4c7aSAndroid Build Coastguard Worker        b"00040400"
266*2f2c4c7aSAndroid Build Coastguard Worker    )
267*2f2c4c7aSAndroid Build Coastguard Worker    states = 1 << tcp_test.TCP_ESTABLISHED
268*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected, binascii.hexlify(bytecode))
269*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(76, len(bytecode))
270*2f2c4c7aSAndroid Build Coastguard Worker    self.socketpairs = self._CreateLotsOfSockets(SOCK_STREAM)
271*2f2c4c7aSAndroid Build Coastguard Worker    filteredsockets = self.sock_diag.DumpAllInetSockets(IPPROTO_TCP, bytecode,
272*2f2c4c7aSAndroid Build Coastguard Worker                                                        states=states)
273*2f2c4c7aSAndroid Build Coastguard Worker    allsockets = self.sock_diag.DumpAllInetSockets(IPPROTO_TCP, NO_BYTECODE,
274*2f2c4c7aSAndroid Build Coastguard Worker                                                   states=states)
275*2f2c4c7aSAndroid Build Coastguard Worker    self.assertItemsEqual(allsockets, filteredsockets)
276*2f2c4c7aSAndroid Build Coastguard Worker
277*2f2c4c7aSAndroid Build Coastguard Worker    # Pick a few sockets in hash table order, and check that the bytecode we
278*2f2c4c7aSAndroid Build Coastguard Worker    # compiled selects them properly.
279*2f2c4c7aSAndroid Build Coastguard Worker    for socketpair in list(self.socketpairs.values())[:20]:
280*2f2c4c7aSAndroid Build Coastguard Worker      for s in socketpair:
281*2f2c4c7aSAndroid Build Coastguard Worker        diag_msg = self.sock_diag.FindSockDiagFromFd(s)
282*2f2c4c7aSAndroid Build Coastguard Worker        instructions = [
283*2f2c4c7aSAndroid Build Coastguard Worker            (sock_diag.INET_DIAG_BC_S_GE, 1, 5, diag_msg.id.sport),
284*2f2c4c7aSAndroid Build Coastguard Worker            (sock_diag.INET_DIAG_BC_S_LE, 1, 4, diag_msg.id.sport),
285*2f2c4c7aSAndroid Build Coastguard Worker            (sock_diag.INET_DIAG_BC_D_GE, 1, 3, diag_msg.id.dport),
286*2f2c4c7aSAndroid Build Coastguard Worker            (sock_diag.INET_DIAG_BC_D_LE, 1, 2, diag_msg.id.dport),
287*2f2c4c7aSAndroid Build Coastguard Worker        ]
288*2f2c4c7aSAndroid Build Coastguard Worker        bytecode = self.PackAndCheckBytecode(instructions)
289*2f2c4c7aSAndroid Build Coastguard Worker        self.assertEqual(32, len(bytecode))
290*2f2c4c7aSAndroid Build Coastguard Worker        sockets = self.sock_diag.DumpAllInetSockets(IPPROTO_TCP, bytecode)
291*2f2c4c7aSAndroid Build Coastguard Worker        self.assertEqual(1, len(sockets))
292*2f2c4c7aSAndroid Build Coastguard Worker
293*2f2c4c7aSAndroid Build Coastguard Worker        # TODO: why doesn't comparing the cstructs work?
294*2f2c4c7aSAndroid Build Coastguard Worker        self.assertEqual(diag_msg.Pack(), sockets[0][0].Pack())
295*2f2c4c7aSAndroid Build Coastguard Worker
296*2f2c4c7aSAndroid Build Coastguard Worker  def testCrossFamilyBytecode(self):
297*2f2c4c7aSAndroid Build Coastguard Worker    """Checks for a cross-family bug in inet_diag_hostcond matching.
298*2f2c4c7aSAndroid Build Coastguard Worker
299*2f2c4c7aSAndroid Build Coastguard Worker    Relevant kernel commits:
300*2f2c4c7aSAndroid Build Coastguard Worker      android-3.4:
301*2f2c4c7aSAndroid Build Coastguard Worker        f67caec inet_diag: avoid unsafe and nonsensical prefix matches in inet_diag_bc_run()
302*2f2c4c7aSAndroid Build Coastguard Worker    """
303*2f2c4c7aSAndroid Build Coastguard Worker    # TODO: this is only here because the test fails if there are any open
304*2f2c4c7aSAndroid Build Coastguard Worker    # sockets other than the ones it creates itself. Make the bytecode more
305*2f2c4c7aSAndroid Build Coastguard Worker    # specific and remove it.
306*2f2c4c7aSAndroid Build Coastguard Worker    states = 1 << tcp_test.TCP_ESTABLISHED
307*2f2c4c7aSAndroid Build Coastguard Worker    self.assertFalse(self.sock_diag.DumpAllInetSockets(IPPROTO_TCP, NO_BYTECODE,
308*2f2c4c7aSAndroid Build Coastguard Worker                                                       states=states))
309*2f2c4c7aSAndroid Build Coastguard Worker
310*2f2c4c7aSAndroid Build Coastguard Worker    unused_pair4 = net_test.CreateSocketPair(AF_INET, SOCK_STREAM, "127.0.0.1")
311*2f2c4c7aSAndroid Build Coastguard Worker    unused_pair6 = net_test.CreateSocketPair(AF_INET6, SOCK_STREAM, "::1")
312*2f2c4c7aSAndroid Build Coastguard Worker
313*2f2c4c7aSAndroid Build Coastguard Worker    bytecode4 = self.PackAndCheckBytecode([
314*2f2c4c7aSAndroid Build Coastguard Worker        (sock_diag.INET_DIAG_BC_S_COND, 1, 2, ("0.0.0.0", 0, -1))])
315*2f2c4c7aSAndroid Build Coastguard Worker    bytecode6 = self.PackAndCheckBytecode([
316*2f2c4c7aSAndroid Build Coastguard Worker        (sock_diag.INET_DIAG_BC_S_COND, 1, 2, ("::", 0, -1))])
317*2f2c4c7aSAndroid Build Coastguard Worker
318*2f2c4c7aSAndroid Build Coastguard Worker    # IPv4/v6 filters must never match IPv6/IPv4 sockets...
319*2f2c4c7aSAndroid Build Coastguard Worker    v4socks = self.sock_diag.DumpAllInetSockets(IPPROTO_TCP, bytecode4,
320*2f2c4c7aSAndroid Build Coastguard Worker                                                  states=states)
321*2f2c4c7aSAndroid Build Coastguard Worker    self.assertTrue(v4socks)
322*2f2c4c7aSAndroid Build Coastguard Worker    self.assertTrue(all(d.family == AF_INET for d, _ in v4socks))
323*2f2c4c7aSAndroid Build Coastguard Worker
324*2f2c4c7aSAndroid Build Coastguard Worker    v6socks = self.sock_diag.DumpAllInetSockets(IPPROTO_TCP, bytecode6,
325*2f2c4c7aSAndroid Build Coastguard Worker                                                  states=states)
326*2f2c4c7aSAndroid Build Coastguard Worker    self.assertTrue(v6socks)
327*2f2c4c7aSAndroid Build Coastguard Worker    self.assertTrue(all(d.family == AF_INET6 for d, _ in v6socks))
328*2f2c4c7aSAndroid Build Coastguard Worker
329*2f2c4c7aSAndroid Build Coastguard Worker    # Except for mapped addresses, which match both IPv4 and IPv6.
330*2f2c4c7aSAndroid Build Coastguard Worker    pair5 = net_test.CreateSocketPair(AF_INET6, SOCK_STREAM,
331*2f2c4c7aSAndroid Build Coastguard Worker                                      "::ffff:127.0.0.1")
332*2f2c4c7aSAndroid Build Coastguard Worker    diag_msgs = [self.sock_diag.FindSockDiagFromFd(s) for s in pair5]
333*2f2c4c7aSAndroid Build Coastguard Worker    v4socks = [d for d, _ in self.sock_diag.DumpAllInetSockets(IPPROTO_TCP,
334*2f2c4c7aSAndroid Build Coastguard Worker                                                               bytecode4,
335*2f2c4c7aSAndroid Build Coastguard Worker                                                               states=states)]
336*2f2c4c7aSAndroid Build Coastguard Worker    v6socks = [d for d, _ in self.sock_diag.DumpAllInetSockets(IPPROTO_TCP,
337*2f2c4c7aSAndroid Build Coastguard Worker                                                               bytecode6,
338*2f2c4c7aSAndroid Build Coastguard Worker                                                               states=states)]
339*2f2c4c7aSAndroid Build Coastguard Worker    self.assertTrue(all(d in v4socks for d in diag_msgs))
340*2f2c4c7aSAndroid Build Coastguard Worker    self.assertTrue(all(d in v6socks for d in diag_msgs))
341*2f2c4c7aSAndroid Build Coastguard Worker
342*2f2c4c7aSAndroid Build Coastguard Worker    for sock in unused_pair4:
343*2f2c4c7aSAndroid Build Coastguard Worker      sock.close()
344*2f2c4c7aSAndroid Build Coastguard Worker
345*2f2c4c7aSAndroid Build Coastguard Worker    for sock in unused_pair6:
346*2f2c4c7aSAndroid Build Coastguard Worker      sock.close()
347*2f2c4c7aSAndroid Build Coastguard Worker
348*2f2c4c7aSAndroid Build Coastguard Worker    for sock in pair5:
349*2f2c4c7aSAndroid Build Coastguard Worker      sock.close()
350*2f2c4c7aSAndroid Build Coastguard Worker
351*2f2c4c7aSAndroid Build Coastguard Worker  def testPortComparisonValidation(self):
352*2f2c4c7aSAndroid Build Coastguard Worker    """Checks for a bug in validating port comparison bytecode.
353*2f2c4c7aSAndroid Build Coastguard Worker
354*2f2c4c7aSAndroid Build Coastguard Worker    Relevant kernel commits:
355*2f2c4c7aSAndroid Build Coastguard Worker      android-3.4:
356*2f2c4c7aSAndroid Build Coastguard Worker        5e1f542 inet_diag: validate port comparison byte code to prevent unsafe reads
357*2f2c4c7aSAndroid Build Coastguard Worker    """
358*2f2c4c7aSAndroid Build Coastguard Worker    bytecode = sock_diag.InetDiagBcOp((sock_diag.INET_DIAG_BC_D_GE, 4, 8))
359*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual("???",
360*2f2c4c7aSAndroid Build Coastguard Worker                      self.sock_diag.DecodeBytecode(bytecode))
361*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(
362*2f2c4c7aSAndroid Build Coastguard Worker        EINVAL,
363*2f2c4c7aSAndroid Build Coastguard Worker        self.sock_diag.DumpAllInetSockets, IPPROTO_TCP, bytecode.Pack())
364*2f2c4c7aSAndroid Build Coastguard Worker
365*2f2c4c7aSAndroid Build Coastguard Worker  def testNonSockDiagCommand(self):
366*2f2c4c7aSAndroid Build Coastguard Worker    def DiagDump(code):
367*2f2c4c7aSAndroid Build Coastguard Worker      sock_id = self.sock_diag._EmptyInetDiagSockId()
368*2f2c4c7aSAndroid Build Coastguard Worker      req = sock_diag.InetDiagReqV2((AF_INET6, IPPROTO_TCP, 0, 0xffffffff,
369*2f2c4c7aSAndroid Build Coastguard Worker                                     sock_id))
370*2f2c4c7aSAndroid Build Coastguard Worker      self.sock_diag._Dump(code, req, sock_diag.InetDiagMsg)
371*2f2c4c7aSAndroid Build Coastguard Worker
372*2f2c4c7aSAndroid Build Coastguard Worker    op = sock_diag.SOCK_DIAG_BY_FAMILY
373*2f2c4c7aSAndroid Build Coastguard Worker    DiagDump(op)  # No errors? Good.
374*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(EINVAL, DiagDump, op + 17)
375*2f2c4c7aSAndroid Build Coastguard Worker
376*2f2c4c7aSAndroid Build Coastguard Worker  def CheckSocketCookie(self, inet, addr):
377*2f2c4c7aSAndroid Build Coastguard Worker    """Tests that getsockopt SO_COOKIE can get cookie for all sockets."""
378*2f2c4c7aSAndroid Build Coastguard Worker    socketpair = net_test.CreateSocketPair(inet, SOCK_STREAM, addr)
379*2f2c4c7aSAndroid Build Coastguard Worker    for sock in socketpair:
380*2f2c4c7aSAndroid Build Coastguard Worker      diag_msg = self.sock_diag.FindSockDiagFromFd(sock)
381*2f2c4c7aSAndroid Build Coastguard Worker      cookie = sock.getsockopt(net_test.SOL_SOCKET, net_test.SO_COOKIE, 8)
382*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(diag_msg.id.cookie, cookie)
383*2f2c4c7aSAndroid Build Coastguard Worker
384*2f2c4c7aSAndroid Build Coastguard Worker    for sock in socketpair:
385*2f2c4c7aSAndroid Build Coastguard Worker      sock.close()
386*2f2c4c7aSAndroid Build Coastguard Worker
387*2f2c4c7aSAndroid Build Coastguard Worker  def testGetsockoptcookie(self):
388*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckSocketCookie(AF_INET, "127.0.0.1")
389*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckSocketCookie(AF_INET6, "::1")
390*2f2c4c7aSAndroid Build Coastguard Worker
391*2f2c4c7aSAndroid Build Coastguard Worker  def testDemonstrateUdpGetSockIdBug(self):
392*2f2c4c7aSAndroid Build Coastguard Worker    # TODO: this is because udp_dump_one mistakenly uses __udp[46]_lib_lookup
393*2f2c4c7aSAndroid Build Coastguard Worker    # by passing the source address as the source address argument.
394*2f2c4c7aSAndroid Build Coastguard Worker    # Unfortunately those functions are intended to match local sockets based
395*2f2c4c7aSAndroid Build Coastguard Worker    # on received packets, and the argument that ends up being compared with
396*2f2c4c7aSAndroid Build Coastguard Worker    # e.g., sk_daddr is actually saddr, not daddr. udp_diag_destroy does not
397*2f2c4c7aSAndroid Build Coastguard Worker    # have this bug.  Upstream has confirmed that this will not be fixed:
398*2f2c4c7aSAndroid Build Coastguard Worker    # https://www.mail-archive.com/[email protected]/msg248638.html
399*2f2c4c7aSAndroid Build Coastguard Worker    """Documents a bug: getting UDP sockets requires swapping src and dst."""
400*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 5, 6]:
401*2f2c4c7aSAndroid Build Coastguard Worker      family = net_test.GetAddressFamily(version)
402*2f2c4c7aSAndroid Build Coastguard Worker      s = socket(family, SOCK_DGRAM, 0)
403*2f2c4c7aSAndroid Build Coastguard Worker      self.SelectInterface(s, self.RandomNetid(), "mark")
404*2f2c4c7aSAndroid Build Coastguard Worker      s.connect((self.GetRemoteSocketAddress(version), 53))
405*2f2c4c7aSAndroid Build Coastguard Worker
406*2f2c4c7aSAndroid Build Coastguard Worker      # Create a fully-specified diag req from our socket, including cookie if
407*2f2c4c7aSAndroid Build Coastguard Worker      # we can get it.
408*2f2c4c7aSAndroid Build Coastguard Worker      req = self.sock_diag.DiagReqFromSocket(s)
409*2f2c4c7aSAndroid Build Coastguard Worker      req.id.cookie = s.getsockopt(net_test.SOL_SOCKET, net_test.SO_COOKIE, 8)
410*2f2c4c7aSAndroid Build Coastguard Worker
411*2f2c4c7aSAndroid Build Coastguard Worker      # As is, this request does not find anything.
412*2f2c4c7aSAndroid Build Coastguard Worker      with self.assertRaisesErrno(ENOENT):
413*2f2c4c7aSAndroid Build Coastguard Worker        self.sock_diag.GetSockInfo(req)
414*2f2c4c7aSAndroid Build Coastguard Worker
415*2f2c4c7aSAndroid Build Coastguard Worker      # But if we swap src and dst, the kernel finds our socket.
416*2f2c4c7aSAndroid Build Coastguard Worker      req.id.sport, req.id.dport = req.id.dport, req.id.sport
417*2f2c4c7aSAndroid Build Coastguard Worker      req.id.src, req.id.dst = req.id.dst, req.id.src
418*2f2c4c7aSAndroid Build Coastguard Worker
419*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSockInfoMatchesSocket(s, self.sock_diag.GetSockInfo(req))
420*2f2c4c7aSAndroid Build Coastguard Worker
421*2f2c4c7aSAndroid Build Coastguard Worker      s.close()
422*2f2c4c7aSAndroid Build Coastguard Worker
423*2f2c4c7aSAndroid Build Coastguard Worker
424*2f2c4c7aSAndroid Build Coastguard Workerclass SockDestroyTest(SockDiagBaseTest):
425*2f2c4c7aSAndroid Build Coastguard Worker  """Tests that SOCK_DESTROY works correctly.
426*2f2c4c7aSAndroid Build Coastguard Worker
427*2f2c4c7aSAndroid Build Coastguard Worker  Relevant kernel commits:
428*2f2c4c7aSAndroid Build Coastguard Worker    net-next:
429*2f2c4c7aSAndroid Build Coastguard Worker      b613f56 net: diag: split inet_diag_dump_one_icsk into two
430*2f2c4c7aSAndroid Build Coastguard Worker      64be0ae net: diag: Add the ability to destroy a socket.
431*2f2c4c7aSAndroid Build Coastguard Worker      6eb5d2e net: diag: Support SOCK_DESTROY for inet sockets.
432*2f2c4c7aSAndroid Build Coastguard Worker      c1e64e2 net: diag: Support destroying TCP sockets.
433*2f2c4c7aSAndroid Build Coastguard Worker      2010b93 net: tcp: deal with listen sockets properly in tcp_abort.
434*2f2c4c7aSAndroid Build Coastguard Worker
435*2f2c4c7aSAndroid Build Coastguard Worker    android-3.4:
436*2f2c4c7aSAndroid Build Coastguard Worker      d48ec88 net: diag: split inet_diag_dump_one_icsk into two
437*2f2c4c7aSAndroid Build Coastguard Worker      2438189 net: diag: Add the ability to destroy a socket.
438*2f2c4c7aSAndroid Build Coastguard Worker      7a2ddbc net: diag: Support SOCK_DESTROY for inet sockets.
439*2f2c4c7aSAndroid Build Coastguard Worker      44047b2 net: diag: Support destroying TCP sockets.
440*2f2c4c7aSAndroid Build Coastguard Worker      200dae7 net: tcp: deal with listen sockets properly in tcp_abort.
441*2f2c4c7aSAndroid Build Coastguard Worker
442*2f2c4c7aSAndroid Build Coastguard Worker    android-3.10:
443*2f2c4c7aSAndroid Build Coastguard Worker      9eaff90 net: diag: split inet_diag_dump_one_icsk into two
444*2f2c4c7aSAndroid Build Coastguard Worker      d60326c net: diag: Add the ability to destroy a socket.
445*2f2c4c7aSAndroid Build Coastguard Worker      3d4ce85 net: diag: Support SOCK_DESTROY for inet sockets.
446*2f2c4c7aSAndroid Build Coastguard Worker      529dfc6 net: diag: Support destroying TCP sockets.
447*2f2c4c7aSAndroid Build Coastguard Worker      9c712fe net: tcp: deal with listen sockets properly in tcp_abort.
448*2f2c4c7aSAndroid Build Coastguard Worker
449*2f2c4c7aSAndroid Build Coastguard Worker    android-3.18:
450*2f2c4c7aSAndroid Build Coastguard Worker      100263d net: diag: split inet_diag_dump_one_icsk into two
451*2f2c4c7aSAndroid Build Coastguard Worker      194c5f3 net: diag: Add the ability to destroy a socket.
452*2f2c4c7aSAndroid Build Coastguard Worker      8387ea2 net: diag: Support SOCK_DESTROY for inet sockets.
453*2f2c4c7aSAndroid Build Coastguard Worker      b80585a net: diag: Support destroying TCP sockets.
454*2f2c4c7aSAndroid Build Coastguard Worker      476c6ce net: tcp: deal with listen sockets properly in tcp_abort.
455*2f2c4c7aSAndroid Build Coastguard Worker
456*2f2c4c7aSAndroid Build Coastguard Worker    android-4.1:
457*2f2c4c7aSAndroid Build Coastguard Worker      56eebf8 net: diag: split inet_diag_dump_one_icsk into two
458*2f2c4c7aSAndroid Build Coastguard Worker      fb486c9 net: diag: Add the ability to destroy a socket.
459*2f2c4c7aSAndroid Build Coastguard Worker      0c02b7e net: diag: Support SOCK_DESTROY for inet sockets.
460*2f2c4c7aSAndroid Build Coastguard Worker      67c71d8 net: diag: Support destroying TCP sockets.
461*2f2c4c7aSAndroid Build Coastguard Worker      a76e0ec net: tcp: deal with listen sockets properly in tcp_abort.
462*2f2c4c7aSAndroid Build Coastguard Worker      e6e277b net: diag: support v4mapped sockets in inet_diag_find_one_icsk()
463*2f2c4c7aSAndroid Build Coastguard Worker
464*2f2c4c7aSAndroid Build Coastguard Worker    android-4.4:
465*2f2c4c7aSAndroid Build Coastguard Worker      76c83a9 net: diag: split inet_diag_dump_one_icsk into two
466*2f2c4c7aSAndroid Build Coastguard Worker      f7cf791 net: diag: Add the ability to destroy a socket.
467*2f2c4c7aSAndroid Build Coastguard Worker      1c42248 net: diag: Support SOCK_DESTROY for inet sockets.
468*2f2c4c7aSAndroid Build Coastguard Worker      c9e8440d net: diag: Support destroying TCP sockets.
469*2f2c4c7aSAndroid Build Coastguard Worker      3d9502c tcp: diag: add support for request sockets to tcp_abort()
470*2f2c4c7aSAndroid Build Coastguard Worker      001cf75 net: tcp: deal with listen sockets properly in tcp_abort.
471*2f2c4c7aSAndroid Build Coastguard Worker  """
472*2f2c4c7aSAndroid Build Coastguard Worker
473*2f2c4c7aSAndroid Build Coastguard Worker  def testClosesSockets(self):
474*2f2c4c7aSAndroid Build Coastguard Worker    self.socketpairs = self._CreateLotsOfSockets(SOCK_STREAM)
475*2f2c4c7aSAndroid Build Coastguard Worker    for _, socketpair in self.socketpairs.items():
476*2f2c4c7aSAndroid Build Coastguard Worker      # Close one of the sockets.
477*2f2c4c7aSAndroid Build Coastguard Worker      # This will send a RST that will close the other side as well.
478*2f2c4c7aSAndroid Build Coastguard Worker      s = random.choice(socketpair)
479*2f2c4c7aSAndroid Build Coastguard Worker      if random.randrange(0, 2) == 1:
480*2f2c4c7aSAndroid Build Coastguard Worker        self.sock_diag.CloseSocketFromFd(s)
481*2f2c4c7aSAndroid Build Coastguard Worker      else:
482*2f2c4c7aSAndroid Build Coastguard Worker        diag_msg = self.sock_diag.FindSockDiagFromFd(s)
483*2f2c4c7aSAndroid Build Coastguard Worker
484*2f2c4c7aSAndroid Build Coastguard Worker        # Get the cookie wrong and ensure that we get an error and the socket
485*2f2c4c7aSAndroid Build Coastguard Worker        # is not closed.
486*2f2c4c7aSAndroid Build Coastguard Worker        real_cookie = diag_msg.id.cookie
487*2f2c4c7aSAndroid Build Coastguard Worker        diag_msg.id.cookie = os.urandom(len(real_cookie))
488*2f2c4c7aSAndroid Build Coastguard Worker        req = self.sock_diag.DiagReqFromDiagMsg(diag_msg, IPPROTO_TCP)
489*2f2c4c7aSAndroid Build Coastguard Worker        self.assertRaisesErrno(ENOENT, self.sock_diag.CloseSocket, req)
490*2f2c4c7aSAndroid Build Coastguard Worker        self.assertSocketConnected(s)
491*2f2c4c7aSAndroid Build Coastguard Worker
492*2f2c4c7aSAndroid Build Coastguard Worker        # Now close it with the correct cookie.
493*2f2c4c7aSAndroid Build Coastguard Worker        req.id.cookie = real_cookie
494*2f2c4c7aSAndroid Build Coastguard Worker        self.sock_diag.CloseSocket(req)
495*2f2c4c7aSAndroid Build Coastguard Worker
496*2f2c4c7aSAndroid Build Coastguard Worker      # Check that both sockets in the pair are closed.
497*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketsClosed(socketpair)
498*2f2c4c7aSAndroid Build Coastguard Worker
499*2f2c4c7aSAndroid Build Coastguard Worker  # TODO:
500*2f2c4c7aSAndroid Build Coastguard Worker  # Test that killing unix sockets returns EOPNOTSUPP.
501*2f2c4c7aSAndroid Build Coastguard Worker
502*2f2c4c7aSAndroid Build Coastguard Worker
503*2f2c4c7aSAndroid Build Coastguard Workerclass SocketExceptionThread(threading.Thread):
504*2f2c4c7aSAndroid Build Coastguard Worker
505*2f2c4c7aSAndroid Build Coastguard Worker  def __init__(self, sock, operation):
506*2f2c4c7aSAndroid Build Coastguard Worker    self.exception = None
507*2f2c4c7aSAndroid Build Coastguard Worker    super(SocketExceptionThread, self).__init__()
508*2f2c4c7aSAndroid Build Coastguard Worker    self.daemon = True
509*2f2c4c7aSAndroid Build Coastguard Worker    self.sock = sock
510*2f2c4c7aSAndroid Build Coastguard Worker    self.operation = operation
511*2f2c4c7aSAndroid Build Coastguard Worker
512*2f2c4c7aSAndroid Build Coastguard Worker  def run(self):
513*2f2c4c7aSAndroid Build Coastguard Worker    try:
514*2f2c4c7aSAndroid Build Coastguard Worker      self.operation(self.sock)
515*2f2c4c7aSAndroid Build Coastguard Worker    except (IOError, AssertionError) as e:
516*2f2c4c7aSAndroid Build Coastguard Worker      self.exception = e
517*2f2c4c7aSAndroid Build Coastguard Worker
518*2f2c4c7aSAndroid Build Coastguard Worker
519*2f2c4c7aSAndroid Build Coastguard Workerclass SockDiagTcpTest(tcp_test.TcpBaseTest, SockDiagBaseTest):
520*2f2c4c7aSAndroid Build Coastguard Worker
521*2f2c4c7aSAndroid Build Coastguard Worker  def testIpv4MappedSynRecvSocket(self):
522*2f2c4c7aSAndroid Build Coastguard Worker    """Tests for the absence of a bug with AF_INET6 TCP SYN-RECV sockets.
523*2f2c4c7aSAndroid Build Coastguard Worker
524*2f2c4c7aSAndroid Build Coastguard Worker    Relevant kernel commits:
525*2f2c4c7aSAndroid Build Coastguard Worker         android-3.4:
526*2f2c4c7aSAndroid Build Coastguard Worker           457a04b inet_diag: fix oops for IPv4 AF_INET6 TCP SYN-RECV state
527*2f2c4c7aSAndroid Build Coastguard Worker    """
528*2f2c4c7aSAndroid Build Coastguard Worker    netid = random.choice(list(self.tuns.keys()))
529*2f2c4c7aSAndroid Build Coastguard Worker    self.IncomingConnection(5, tcp_test.TCP_SYN_RECV, netid)
530*2f2c4c7aSAndroid Build Coastguard Worker    sock_id = self.sock_diag._EmptyInetDiagSockId()
531*2f2c4c7aSAndroid Build Coastguard Worker    sock_id.sport = self.port
532*2f2c4c7aSAndroid Build Coastguard Worker    states = 1 << tcp_test.TCP_SYN_RECV
533*2f2c4c7aSAndroid Build Coastguard Worker    req = sock_diag.InetDiagReqV2((AF_INET6, IPPROTO_TCP, 0, states, sock_id))
534*2f2c4c7aSAndroid Build Coastguard Worker    children = self.sock_diag.Dump(req, NO_BYTECODE)
535*2f2c4c7aSAndroid Build Coastguard Worker
536*2f2c4c7aSAndroid Build Coastguard Worker    self.assertTrue(children)
537*2f2c4c7aSAndroid Build Coastguard Worker    for child, unused_args in children:
538*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(tcp_test.TCP_SYN_RECV, child.state)
539*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(self.sock_diag.PaddedAddress(self.remotesockaddr),
540*2f2c4c7aSAndroid Build Coastguard Worker                       child.id.dst)
541*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(self.sock_diag.PaddedAddress(self.mysockaddr),
542*2f2c4c7aSAndroid Build Coastguard Worker                       child.id.src)
543*2f2c4c7aSAndroid Build Coastguard Worker
544*2f2c4c7aSAndroid Build Coastguard Worker
545*2f2c4c7aSAndroid Build Coastguard Workerclass TcpRcvWindowTest(tcp_test.TcpBaseTest, SockDiagBaseTest):
546*2f2c4c7aSAndroid Build Coastguard Worker
547*2f2c4c7aSAndroid Build Coastguard Worker  RWND_SIZE = 64000
548*2f2c4c7aSAndroid Build Coastguard Worker  TCP_DEFAULT_INIT_RWND = "/proc/sys/net/ipv4/tcp_default_init_rwnd"
549*2f2c4c7aSAndroid Build Coastguard Worker
550*2f2c4c7aSAndroid Build Coastguard Worker  def setUp(self):
551*2f2c4c7aSAndroid Build Coastguard Worker    super(TcpRcvWindowTest, self).setUp()
552*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(ENOENT, open, self.TCP_DEFAULT_INIT_RWND, "w")
553*2f2c4c7aSAndroid Build Coastguard Worker
554*2f2c4c7aSAndroid Build Coastguard Worker  def checkInitRwndSize(self, version, netid):
555*2f2c4c7aSAndroid Build Coastguard Worker    self.IncomingConnection(version, tcp_test.TCP_ESTABLISHED, netid)
556*2f2c4c7aSAndroid Build Coastguard Worker    tcpInfo = TcpInfo(self.accepted.getsockopt(net_test.SOL_TCP,
557*2f2c4c7aSAndroid Build Coastguard Worker                                               net_test.TCP_INFO, len(TcpInfo)))
558*2f2c4c7aSAndroid Build Coastguard Worker    self.assertLess(self.RWND_SIZE, tcpInfo.tcpi_rcv_ssthresh,
559*2f2c4c7aSAndroid Build Coastguard Worker                    "Tcp rwnd of netid=%d, version=%d is not enough. "
560*2f2c4c7aSAndroid Build Coastguard Worker                    "Expect: %d, actual: %d" % (netid, version, self.RWND_SIZE,
561*2f2c4c7aSAndroid Build Coastguard Worker                                                tcpInfo.tcpi_rcv_ssthresh))
562*2f2c4c7aSAndroid Build Coastguard Worker    self.CloseSockets()
563*2f2c4c7aSAndroid Build Coastguard Worker
564*2f2c4c7aSAndroid Build Coastguard Worker  def checkSynPacketWindowSize(self, version, netid):
565*2f2c4c7aSAndroid Build Coastguard Worker    s = self.BuildSocket(version, net_test.TCPSocket, netid, "mark")
566*2f2c4c7aSAndroid Build Coastguard Worker    myaddr = self.MyAddress(version, netid)
567*2f2c4c7aSAndroid Build Coastguard Worker    dstaddr = self.GetRemoteAddress(version)
568*2f2c4c7aSAndroid Build Coastguard Worker    dstsockaddr = self.GetRemoteSocketAddress(version)
569*2f2c4c7aSAndroid Build Coastguard Worker    desc, expected = packets.SYN(53, version, myaddr, dstaddr,
570*2f2c4c7aSAndroid Build Coastguard Worker                                 sport=None, seq=None)
571*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(EINPROGRESS, s.connect, (dstsockaddr, 53))
572*2f2c4c7aSAndroid Build Coastguard Worker    msg = "IPv%s TCP connect: expected %s on %s" % (
573*2f2c4c7aSAndroid Build Coastguard Worker        version, desc, self.GetInterfaceName(netid))
574*2f2c4c7aSAndroid Build Coastguard Worker    syn = self.ExpectPacketOn(netid, msg, expected)
575*2f2c4c7aSAndroid Build Coastguard Worker    self.assertLess(self.RWND_SIZE, syn.window)
576*2f2c4c7aSAndroid Build Coastguard Worker    s.close()
577*2f2c4c7aSAndroid Build Coastguard Worker
578*2f2c4c7aSAndroid Build Coastguard Worker  def testTcpCwndSize(self):
579*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 5, 6]:
580*2f2c4c7aSAndroid Build Coastguard Worker      for netid in self.NETIDS:
581*2f2c4c7aSAndroid Build Coastguard Worker        self.checkInitRwndSize(version, netid)
582*2f2c4c7aSAndroid Build Coastguard Worker        self.checkSynPacketWindowSize(version, netid)
583*2f2c4c7aSAndroid Build Coastguard Worker
584*2f2c4c7aSAndroid Build Coastguard Worker
585*2f2c4c7aSAndroid Build Coastguard Workerclass SockDestroyTcpTest(tcp_test.TcpBaseTest, SockDiagBaseTest):
586*2f2c4c7aSAndroid Build Coastguard Worker
587*2f2c4c7aSAndroid Build Coastguard Worker  def setUp(self):
588*2f2c4c7aSAndroid Build Coastguard Worker    super(SockDestroyTcpTest, self).setUp()
589*2f2c4c7aSAndroid Build Coastguard Worker    self.netid = random.choice(list(self.tuns.keys()))
590*2f2c4c7aSAndroid Build Coastguard Worker
591*2f2c4c7aSAndroid Build Coastguard Worker  def ExpectRst(self, msg):
592*2f2c4c7aSAndroid Build Coastguard Worker    desc, rst = self.RstPacket()
593*2f2c4c7aSAndroid Build Coastguard Worker    msg = "%s: expecting %s: " % (msg, desc)
594*2f2c4c7aSAndroid Build Coastguard Worker    self.ExpectPacketOn(self.netid, msg, rst)
595*2f2c4c7aSAndroid Build Coastguard Worker
596*2f2c4c7aSAndroid Build Coastguard Worker  def CheckRstOnClose(self, sock, req, expect_reset, msg, do_close=True):
597*2f2c4c7aSAndroid Build Coastguard Worker    """Closes the socket and checks whether a RST is sent or not."""
598*2f2c4c7aSAndroid Build Coastguard Worker    if sock is not None:
599*2f2c4c7aSAndroid Build Coastguard Worker      self.assertIsNone(req, "Must specify sock or req, not both")
600*2f2c4c7aSAndroid Build Coastguard Worker      self.sock_diag.CloseSocketFromFd(sock)
601*2f2c4c7aSAndroid Build Coastguard Worker      self.assertRaisesErrno(EINVAL, sock.accept)
602*2f2c4c7aSAndroid Build Coastguard Worker    else:
603*2f2c4c7aSAndroid Build Coastguard Worker      self.assertIsNone(sock, "Must specify sock or req, not both")
604*2f2c4c7aSAndroid Build Coastguard Worker      self.sock_diag.CloseSocket(req)
605*2f2c4c7aSAndroid Build Coastguard Worker
606*2f2c4c7aSAndroid Build Coastguard Worker    if expect_reset:
607*2f2c4c7aSAndroid Build Coastguard Worker      self.ExpectRst(msg)
608*2f2c4c7aSAndroid Build Coastguard Worker    else:
609*2f2c4c7aSAndroid Build Coastguard Worker      msg = "%s: " % msg
610*2f2c4c7aSAndroid Build Coastguard Worker      self.ExpectNoPacketsOn(self.netid, msg)
611*2f2c4c7aSAndroid Build Coastguard Worker
612*2f2c4c7aSAndroid Build Coastguard Worker    if sock is not None and do_close:
613*2f2c4c7aSAndroid Build Coastguard Worker      sock.close()
614*2f2c4c7aSAndroid Build Coastguard Worker
615*2f2c4c7aSAndroid Build Coastguard Worker  def CheckTcpReset(self, state, statename):
616*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 5, 6]:
617*2f2c4c7aSAndroid Build Coastguard Worker      msg = "Closing incoming IPv%d %s socket" % (version, statename)
618*2f2c4c7aSAndroid Build Coastguard Worker      self.IncomingConnection(version, state, self.netid)
619*2f2c4c7aSAndroid Build Coastguard Worker      self.CheckRstOnClose(self.s, None, False, msg)
620*2f2c4c7aSAndroid Build Coastguard Worker      if state != tcp_test.TCP_LISTEN:
621*2f2c4c7aSAndroid Build Coastguard Worker        msg = "Closing accepted IPv%d %s socket" % (version, statename)
622*2f2c4c7aSAndroid Build Coastguard Worker        self.CheckRstOnClose(self.accepted, None, True, msg)
623*2f2c4c7aSAndroid Build Coastguard Worker        self.CloseSockets()
624*2f2c4c7aSAndroid Build Coastguard Worker
625*2f2c4c7aSAndroid Build Coastguard Worker  def testTcpResets(self):
626*2f2c4c7aSAndroid Build Coastguard Worker    """Checks that closing sockets in appropriate states sends a RST."""
627*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckTcpReset(tcp_test.TCP_LISTEN, "TCP_LISTEN")
628*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckTcpReset(tcp_test.TCP_ESTABLISHED, "TCP_ESTABLISHED")
629*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckTcpReset(tcp_test.TCP_CLOSE_WAIT, "TCP_CLOSE_WAIT")
630*2f2c4c7aSAndroid Build Coastguard Worker
631*2f2c4c7aSAndroid Build Coastguard Worker  def testFinWait1Socket(self):
632*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 5, 6]:
633*2f2c4c7aSAndroid Build Coastguard Worker      self.IncomingConnection(version, tcp_test.TCP_ESTABLISHED, self.netid)
634*2f2c4c7aSAndroid Build Coastguard Worker
635*2f2c4c7aSAndroid Build Coastguard Worker      # Get the cookie so we can find this socket after we close it.
636*2f2c4c7aSAndroid Build Coastguard Worker      diag_msg = self.sock_diag.FindSockDiagFromFd(self.accepted)
637*2f2c4c7aSAndroid Build Coastguard Worker      diag_req = self.sock_diag.DiagReqFromDiagMsg(diag_msg, IPPROTO_TCP)
638*2f2c4c7aSAndroid Build Coastguard Worker
639*2f2c4c7aSAndroid Build Coastguard Worker      # Close the socket and check that it goes into FIN_WAIT1 and sends a FIN.
640*2f2c4c7aSAndroid Build Coastguard Worker      net_test.EnableFinWait(self.accepted)
641*2f2c4c7aSAndroid Build Coastguard Worker      self.accepted.close()
642*2f2c4c7aSAndroid Build Coastguard Worker      self.accepted = None
643*2f2c4c7aSAndroid Build Coastguard Worker      diag_req.states = 1 << tcp_test.TCP_FIN_WAIT1
644*2f2c4c7aSAndroid Build Coastguard Worker      diag_msg, attrs = self.sock_diag.GetSockInfo(diag_req)
645*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(tcp_test.TCP_FIN_WAIT1, diag_msg.state)
646*2f2c4c7aSAndroid Build Coastguard Worker      desc, fin = self.FinPacket()
647*2f2c4c7aSAndroid Build Coastguard Worker      msg = "Closing FIN_WAIT1 socket"
648*2f2c4c7aSAndroid Build Coastguard Worker      self.ExpectPacketOn(self.netid, msg, fin)
649*2f2c4c7aSAndroid Build Coastguard Worker
650*2f2c4c7aSAndroid Build Coastguard Worker      # Destroy the socket.
651*2f2c4c7aSAndroid Build Coastguard Worker      self.sock_diag.CloseSocketFromFd(self.s)
652*2f2c4c7aSAndroid Build Coastguard Worker      self.assertRaisesErrno(EINVAL, self.s.accept)
653*2f2c4c7aSAndroid Build Coastguard Worker      try:
654*2f2c4c7aSAndroid Build Coastguard Worker        diag_msg, attrs = self.sock_diag.GetSockInfo(diag_req)
655*2f2c4c7aSAndroid Build Coastguard Worker      except Error as e:
656*2f2c4c7aSAndroid Build Coastguard Worker        # Newer kernels will have closed the socket and sent a RST.
657*2f2c4c7aSAndroid Build Coastguard Worker        self.assertEqual(ENOENT, e.errno)
658*2f2c4c7aSAndroid Build Coastguard Worker        self.ExpectRst(msg)
659*2f2c4c7aSAndroid Build Coastguard Worker        self.CloseSockets()
660*2f2c4c7aSAndroid Build Coastguard Worker        return
661*2f2c4c7aSAndroid Build Coastguard Worker
662*2f2c4c7aSAndroid Build Coastguard Worker      # Older kernels don't support closing FIN_WAIT1 sockets.
663*2f2c4c7aSAndroid Build Coastguard Worker      # Check that no RST is sent and that the socket is still in FIN_WAIT1, and
664*2f2c4c7aSAndroid Build Coastguard Worker      # advances to FIN_WAIT2 if the FIN is ACked.
665*2f2c4c7aSAndroid Build Coastguard Worker      msg = "%s: " % msg
666*2f2c4c7aSAndroid Build Coastguard Worker      self.ExpectNoPacketsOn(self.netid, msg)
667*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(tcp_test.TCP_FIN_WAIT1, diag_msg.state)
668*2f2c4c7aSAndroid Build Coastguard Worker
669*2f2c4c7aSAndroid Build Coastguard Worker      # ACK the FIN so we don't trip over retransmits in future tests.
670*2f2c4c7aSAndroid Build Coastguard Worker      finversion = 4 if version == 5 else version
671*2f2c4c7aSAndroid Build Coastguard Worker      desc, finack = packets.ACK(finversion, self.remoteaddr, self.myaddr, fin)
672*2f2c4c7aSAndroid Build Coastguard Worker      diag_msg, attrs = self.sock_diag.GetSockInfo(diag_req)
673*2f2c4c7aSAndroid Build Coastguard Worker      self.ReceivePacketOn(self.netid, finack)
674*2f2c4c7aSAndroid Build Coastguard Worker
675*2f2c4c7aSAndroid Build Coastguard Worker      # See if we can find the resulting FIN_WAIT2 socket.
676*2f2c4c7aSAndroid Build Coastguard Worker      diag_req.states = 1 << tcp_test.TCP_FIN_WAIT2
677*2f2c4c7aSAndroid Build Coastguard Worker      infos = self.sock_diag.Dump(diag_req, NO_BYTECODE)
678*2f2c4c7aSAndroid Build Coastguard Worker      self.assertTrue(any(diag_msg.state == tcp_test.TCP_FIN_WAIT2
679*2f2c4c7aSAndroid Build Coastguard Worker                          for diag_msg, attrs in infos),
680*2f2c4c7aSAndroid Build Coastguard Worker                      "Expected to find FIN_WAIT2 socket in %s" % infos)
681*2f2c4c7aSAndroid Build Coastguard Worker
682*2f2c4c7aSAndroid Build Coastguard Worker      self.CloseSockets()
683*2f2c4c7aSAndroid Build Coastguard Worker
684*2f2c4c7aSAndroid Build Coastguard Worker  def FindChildSockets(self, s):
685*2f2c4c7aSAndroid Build Coastguard Worker    """Finds the SYN_RECV child sockets of a given listening socket."""
686*2f2c4c7aSAndroid Build Coastguard Worker    d = self.sock_diag.FindSockDiagFromFd(self.s)
687*2f2c4c7aSAndroid Build Coastguard Worker    req = self.sock_diag.DiagReqFromDiagMsg(d, IPPROTO_TCP)
688*2f2c4c7aSAndroid Build Coastguard Worker    req.states = 1 << tcp_test.TCP_SYN_RECV | 1 << tcp_test.TCP_ESTABLISHED
689*2f2c4c7aSAndroid Build Coastguard Worker    req.id.cookie = b"\x00" * 8
690*2f2c4c7aSAndroid Build Coastguard Worker
691*2f2c4c7aSAndroid Build Coastguard Worker    bad_bytecode = self.PackAndCheckBytecode(
692*2f2c4c7aSAndroid Build Coastguard Worker        [(sock_diag.INET_DIAG_BC_MARK_COND, 1, 2, (0xffff, 0xffff))])
693*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual([], self.sock_diag.Dump(req, bad_bytecode))
694*2f2c4c7aSAndroid Build Coastguard Worker
695*2f2c4c7aSAndroid Build Coastguard Worker    bytecode = self.PackAndCheckBytecode(
696*2f2c4c7aSAndroid Build Coastguard Worker        [(sock_diag.INET_DIAG_BC_MARK_COND, 1, 2, (self.netid, 0xffff))])
697*2f2c4c7aSAndroid Build Coastguard Worker    children = self.sock_diag.Dump(req, bytecode)
698*2f2c4c7aSAndroid Build Coastguard Worker    return [self.sock_diag.DiagReqFromDiagMsg(d, IPPROTO_TCP)
699*2f2c4c7aSAndroid Build Coastguard Worker            for d, _ in children]
700*2f2c4c7aSAndroid Build Coastguard Worker
701*2f2c4c7aSAndroid Build Coastguard Worker  def CheckChildSocket(self, version, statename, parent_first):
702*2f2c4c7aSAndroid Build Coastguard Worker    state = getattr(tcp_test, statename)
703*2f2c4c7aSAndroid Build Coastguard Worker
704*2f2c4c7aSAndroid Build Coastguard Worker    self.IncomingConnection(version, state, self.netid)
705*2f2c4c7aSAndroid Build Coastguard Worker
706*2f2c4c7aSAndroid Build Coastguard Worker    d = self.sock_diag.FindSockDiagFromFd(self.s)
707*2f2c4c7aSAndroid Build Coastguard Worker    parent = self.sock_diag.DiagReqFromDiagMsg(d, IPPROTO_TCP)
708*2f2c4c7aSAndroid Build Coastguard Worker    children = self.FindChildSockets(self.s)
709*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(1, len(children))
710*2f2c4c7aSAndroid Build Coastguard Worker
711*2f2c4c7aSAndroid Build Coastguard Worker    is_established = (state == tcp_test.TCP_NOT_YET_ACCEPTED)
712*2f2c4c7aSAndroid Build Coastguard Worker    expected_state = tcp_test.TCP_ESTABLISHED if is_established else state
713*2f2c4c7aSAndroid Build Coastguard Worker
714*2f2c4c7aSAndroid Build Coastguard Worker    for child in children:
715*2f2c4c7aSAndroid Build Coastguard Worker      diag_msg, attrs = self.sock_diag.GetSockInfo(child)
716*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(diag_msg.state, expected_state)
717*2f2c4c7aSAndroid Build Coastguard Worker      self.assertMarkIs(self.netid, attrs)
718*2f2c4c7aSAndroid Build Coastguard Worker
719*2f2c4c7aSAndroid Build Coastguard Worker    def CloseParent(expect_reset):
720*2f2c4c7aSAndroid Build Coastguard Worker      msg = "Closing parent IPv%d %s socket %s child" % (
721*2f2c4c7aSAndroid Build Coastguard Worker          version, statename, "before" if parent_first else "after")
722*2f2c4c7aSAndroid Build Coastguard Worker      self.CheckRstOnClose(self.s, None, expect_reset, msg)
723*2f2c4c7aSAndroid Build Coastguard Worker      self.assertRaisesErrno(ENOENT, self.sock_diag.GetSockInfo, parent)
724*2f2c4c7aSAndroid Build Coastguard Worker
725*2f2c4c7aSAndroid Build Coastguard Worker    def CheckChildrenClosed():
726*2f2c4c7aSAndroid Build Coastguard Worker      for child in children:
727*2f2c4c7aSAndroid Build Coastguard Worker        self.assertRaisesErrno(ENOENT, self.sock_diag.GetSockInfo, child)
728*2f2c4c7aSAndroid Build Coastguard Worker
729*2f2c4c7aSAndroid Build Coastguard Worker    def CloseChildren():
730*2f2c4c7aSAndroid Build Coastguard Worker      for child in children:
731*2f2c4c7aSAndroid Build Coastguard Worker        msg = "Closing child IPv%d %s socket %s parent" % (
732*2f2c4c7aSAndroid Build Coastguard Worker            version, statename, "after" if parent_first else "before")
733*2f2c4c7aSAndroid Build Coastguard Worker        self.sock_diag.GetSockInfo(child)
734*2f2c4c7aSAndroid Build Coastguard Worker        self.CheckRstOnClose(None, child, is_established, msg)
735*2f2c4c7aSAndroid Build Coastguard Worker        self.assertRaisesErrno(ENOENT, self.sock_diag.GetSockInfo, child)
736*2f2c4c7aSAndroid Build Coastguard Worker      CheckChildrenClosed()
737*2f2c4c7aSAndroid Build Coastguard Worker
738*2f2c4c7aSAndroid Build Coastguard Worker    if parent_first:
739*2f2c4c7aSAndroid Build Coastguard Worker      # Closing the parent will close child sockets, which will send a RST,
740*2f2c4c7aSAndroid Build Coastguard Worker      # iff they are already established.
741*2f2c4c7aSAndroid Build Coastguard Worker      CloseParent(is_established)
742*2f2c4c7aSAndroid Build Coastguard Worker      if is_established:
743*2f2c4c7aSAndroid Build Coastguard Worker        CheckChildrenClosed()
744*2f2c4c7aSAndroid Build Coastguard Worker      else:
745*2f2c4c7aSAndroid Build Coastguard Worker        CloseChildren()
746*2f2c4c7aSAndroid Build Coastguard Worker        CheckChildrenClosed()
747*2f2c4c7aSAndroid Build Coastguard Worker    else:
748*2f2c4c7aSAndroid Build Coastguard Worker      CloseChildren()
749*2f2c4c7aSAndroid Build Coastguard Worker      CloseParent(False)
750*2f2c4c7aSAndroid Build Coastguard Worker
751*2f2c4c7aSAndroid Build Coastguard Worker    self.CloseSockets()
752*2f2c4c7aSAndroid Build Coastguard Worker
753*2f2c4c7aSAndroid Build Coastguard Worker  def testChildSockets(self):
754*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 5, 6]:
755*2f2c4c7aSAndroid Build Coastguard Worker      self.CheckChildSocket(version, "TCP_SYN_RECV", False)
756*2f2c4c7aSAndroid Build Coastguard Worker      self.CheckChildSocket(version, "TCP_SYN_RECV", True)
757*2f2c4c7aSAndroid Build Coastguard Worker      self.CheckChildSocket(version, "TCP_NOT_YET_ACCEPTED", False)
758*2f2c4c7aSAndroid Build Coastguard Worker      self.CheckChildSocket(version, "TCP_NOT_YET_ACCEPTED", True)
759*2f2c4c7aSAndroid Build Coastguard Worker
760*2f2c4c7aSAndroid Build Coastguard Worker  def testAcceptInterrupted(self):
761*2f2c4c7aSAndroid Build Coastguard Worker    """Tests that accept() is interrupted by SOCK_DESTROY."""
762*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 5, 6]:
763*2f2c4c7aSAndroid Build Coastguard Worker      self.IncomingConnection(version, tcp_test.TCP_LISTEN, self.netid)
764*2f2c4c7aSAndroid Build Coastguard Worker      self.assertRaisesErrno(ENOTCONN, self.s.recv, 4096)
765*2f2c4c7aSAndroid Build Coastguard Worker      self.CloseDuringBlockingCall(self.s, lambda sock: sock.accept(), EINVAL)
766*2f2c4c7aSAndroid Build Coastguard Worker      self.assertRaisesErrno(ECONNABORTED, self.s.send, b"foo")
767*2f2c4c7aSAndroid Build Coastguard Worker      self.assertRaisesErrno(EINVAL, self.s.accept)
768*2f2c4c7aSAndroid Build Coastguard Worker      # TODO: this should really return an error such as ENOTCONN...
769*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(b"", self.s.recv(4096))
770*2f2c4c7aSAndroid Build Coastguard Worker      self.CloseSockets()
771*2f2c4c7aSAndroid Build Coastguard Worker
772*2f2c4c7aSAndroid Build Coastguard Worker  def testReadInterrupted(self):
773*2f2c4c7aSAndroid Build Coastguard Worker    """Tests that read() is interrupted by SOCK_DESTROY."""
774*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 5, 6]:
775*2f2c4c7aSAndroid Build Coastguard Worker      self.IncomingConnection(version, tcp_test.TCP_ESTABLISHED, self.netid)
776*2f2c4c7aSAndroid Build Coastguard Worker      self.CloseDuringBlockingCall(self.accepted, lambda sock: sock.recv(4096),
777*2f2c4c7aSAndroid Build Coastguard Worker                                   ECONNABORTED)
778*2f2c4c7aSAndroid Build Coastguard Worker      # Writing returns EPIPE, and reading returns EOF.
779*2f2c4c7aSAndroid Build Coastguard Worker      self.assertRaisesErrno(EPIPE, self.accepted.send, b"foo")
780*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(b"", self.accepted.recv(4096))
781*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(b"", self.accepted.recv(4096))
782*2f2c4c7aSAndroid Build Coastguard Worker      self.CloseSockets()
783*2f2c4c7aSAndroid Build Coastguard Worker
784*2f2c4c7aSAndroid Build Coastguard Worker  def testConnectInterrupted(self):
785*2f2c4c7aSAndroid Build Coastguard Worker    """Tests that connect() is interrupted by SOCK_DESTROY."""
786*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 5, 6]:
787*2f2c4c7aSAndroid Build Coastguard Worker      family = {4: AF_INET, 5: AF_INET6, 6: AF_INET6}[version]
788*2f2c4c7aSAndroid Build Coastguard Worker      s = net_test.Socket(family, SOCK_STREAM, IPPROTO_TCP)
789*2f2c4c7aSAndroid Build Coastguard Worker      self.SelectInterface(s, self.netid, "mark")
790*2f2c4c7aSAndroid Build Coastguard Worker
791*2f2c4c7aSAndroid Build Coastguard Worker      remotesockaddr = self.GetRemoteSocketAddress(version)
792*2f2c4c7aSAndroid Build Coastguard Worker      remoteaddr = self.GetRemoteAddress(version)
793*2f2c4c7aSAndroid Build Coastguard Worker      s.bind(("", 0))
794*2f2c4c7aSAndroid Build Coastguard Worker      _, sport = s.getsockname()[:2]
795*2f2c4c7aSAndroid Build Coastguard Worker      self.CloseDuringBlockingCall(
796*2f2c4c7aSAndroid Build Coastguard Worker          s, lambda sock: sock.connect((remotesockaddr, 53)), ECONNABORTED)
797*2f2c4c7aSAndroid Build Coastguard Worker      desc, syn = packets.SYN(53, version, self.MyAddress(version, self.netid),
798*2f2c4c7aSAndroid Build Coastguard Worker                              remoteaddr, sport=sport, seq=None)
799*2f2c4c7aSAndroid Build Coastguard Worker      self.ExpectPacketOn(self.netid, desc, syn)
800*2f2c4c7aSAndroid Build Coastguard Worker      msg = "SOCK_DESTROY of socket in connect, expected no RST"
801*2f2c4c7aSAndroid Build Coastguard Worker      self.ExpectNoPacketsOn(self.netid, msg)
802*2f2c4c7aSAndroid Build Coastguard Worker      s.close()
803*2f2c4c7aSAndroid Build Coastguard Worker
804*2f2c4c7aSAndroid Build Coastguard Worker
805*2f2c4c7aSAndroid Build Coastguard Workerclass PollOnCloseTest(tcp_test.TcpBaseTest, SockDiagBaseTest):
806*2f2c4c7aSAndroid Build Coastguard Worker  """Tests that the effect of SOCK_DESTROY on poll matches TCP RSTs.
807*2f2c4c7aSAndroid Build Coastguard Worker
808*2f2c4c7aSAndroid Build Coastguard Worker  The behaviour of poll() in these cases is not what we might expect: if only
809*2f2c4c7aSAndroid Build Coastguard Worker  POLLIN is specified, it will return POLLIN|POLLERR|POLLHUP, but if POLLOUT
810*2f2c4c7aSAndroid Build Coastguard Worker  is (also) specified, it will only return POLLOUT.
811*2f2c4c7aSAndroid Build Coastguard Worker  """
812*2f2c4c7aSAndroid Build Coastguard Worker
813*2f2c4c7aSAndroid Build Coastguard Worker  POLLIN_OUT = select.POLLIN | select.POLLOUT
814*2f2c4c7aSAndroid Build Coastguard Worker  POLLIN_ERR_HUP = select.POLLIN | select.POLLERR | select.POLLHUP
815*2f2c4c7aSAndroid Build Coastguard Worker
816*2f2c4c7aSAndroid Build Coastguard Worker  def setUp(self):
817*2f2c4c7aSAndroid Build Coastguard Worker    super(PollOnCloseTest, self).setUp()
818*2f2c4c7aSAndroid Build Coastguard Worker    self.netid = random.choice(list(self.tuns.keys()))
819*2f2c4c7aSAndroid Build Coastguard Worker
820*2f2c4c7aSAndroid Build Coastguard Worker  POLL_FLAGS = [(select.POLLIN, "IN"), (select.POLLOUT, "OUT"),
821*2f2c4c7aSAndroid Build Coastguard Worker                (select.POLLERR, "ERR"), (select.POLLHUP, "HUP")]
822*2f2c4c7aSAndroid Build Coastguard Worker
823*2f2c4c7aSAndroid Build Coastguard Worker  def PollResultToString(self, poll_events, ignoremask):
824*2f2c4c7aSAndroid Build Coastguard Worker    out = []
825*2f2c4c7aSAndroid Build Coastguard Worker    for fd, event in poll_events:
826*2f2c4c7aSAndroid Build Coastguard Worker      flags = [name for (flag, name) in self.POLL_FLAGS
827*2f2c4c7aSAndroid Build Coastguard Worker               if event & flag & ~ignoremask != 0]
828*2f2c4c7aSAndroid Build Coastguard Worker      out.append((fd, "|".join(flags)))
829*2f2c4c7aSAndroid Build Coastguard Worker    return out
830*2f2c4c7aSAndroid Build Coastguard Worker
831*2f2c4c7aSAndroid Build Coastguard Worker  def BlockingPoll(self, sock, mask, expected, ignoremask):
832*2f2c4c7aSAndroid Build Coastguard Worker    p = select.poll()
833*2f2c4c7aSAndroid Build Coastguard Worker    p.register(sock, mask)
834*2f2c4c7aSAndroid Build Coastguard Worker    expected_fds = [(sock.fileno(), expected)]
835*2f2c4c7aSAndroid Build Coastguard Worker    # Don't block forever or we'll hang continuous test runs on failure.
836*2f2c4c7aSAndroid Build Coastguard Worker    # A 5-second timeout should be long enough not to be flaky.
837*2f2c4c7aSAndroid Build Coastguard Worker    actual_fds = p.poll(5000)
838*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(self.PollResultToString(expected_fds, ignoremask),
839*2f2c4c7aSAndroid Build Coastguard Worker                     self.PollResultToString(actual_fds, ignoremask))
840*2f2c4c7aSAndroid Build Coastguard Worker
841*2f2c4c7aSAndroid Build Coastguard Worker  def RstDuringBlockingCall(self, sock, call, expected_errno):
842*2f2c4c7aSAndroid Build Coastguard Worker    self._EventDuringBlockingCall(
843*2f2c4c7aSAndroid Build Coastguard Worker        sock, call, expected_errno,
844*2f2c4c7aSAndroid Build Coastguard Worker        lambda _: self.ReceiveRstPacketOn(self.netid))
845*2f2c4c7aSAndroid Build Coastguard Worker
846*2f2c4c7aSAndroid Build Coastguard Worker  def assertSocketErrors(self, errno):
847*2f2c4c7aSAndroid Build Coastguard Worker    # The first operation returns the expected errno.
848*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(errno, self.accepted.recv, 4096)
849*2f2c4c7aSAndroid Build Coastguard Worker
850*2f2c4c7aSAndroid Build Coastguard Worker    # Subsequent operations behave as normal.
851*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaisesErrno(EPIPE, self.accepted.send, b"foo")
852*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(b"", self.accepted.recv(4096))
853*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(b"", self.accepted.recv(4096))
854*2f2c4c7aSAndroid Build Coastguard Worker
855*2f2c4c7aSAndroid Build Coastguard Worker  def CheckPollDestroy(self, mask, expected, ignoremask):
856*2f2c4c7aSAndroid Build Coastguard Worker    """Interrupts a poll() with SOCK_DESTROY."""
857*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 5, 6]:
858*2f2c4c7aSAndroid Build Coastguard Worker      self.IncomingConnection(version, tcp_test.TCP_ESTABLISHED, self.netid)
859*2f2c4c7aSAndroid Build Coastguard Worker      self.CloseDuringBlockingCall(
860*2f2c4c7aSAndroid Build Coastguard Worker          self.accepted,
861*2f2c4c7aSAndroid Build Coastguard Worker          lambda sock: self.BlockingPoll(sock, mask, expected, ignoremask),
862*2f2c4c7aSAndroid Build Coastguard Worker          None)
863*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketErrors(ECONNABORTED)
864*2f2c4c7aSAndroid Build Coastguard Worker      self.CloseSockets()
865*2f2c4c7aSAndroid Build Coastguard Worker
866*2f2c4c7aSAndroid Build Coastguard Worker  def CheckPollRst(self, mask, expected, ignoremask):
867*2f2c4c7aSAndroid Build Coastguard Worker    """Interrupts a poll() by receiving a TCP RST."""
868*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 5, 6]:
869*2f2c4c7aSAndroid Build Coastguard Worker      self.IncomingConnection(version, tcp_test.TCP_ESTABLISHED, self.netid)
870*2f2c4c7aSAndroid Build Coastguard Worker      self.RstDuringBlockingCall(
871*2f2c4c7aSAndroid Build Coastguard Worker          self.accepted,
872*2f2c4c7aSAndroid Build Coastguard Worker          lambda sock: self.BlockingPoll(sock, mask, expected, ignoremask),
873*2f2c4c7aSAndroid Build Coastguard Worker          None)
874*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketErrors(ECONNRESET)
875*2f2c4c7aSAndroid Build Coastguard Worker      self.CloseSockets()
876*2f2c4c7aSAndroid Build Coastguard Worker
877*2f2c4c7aSAndroid Build Coastguard Worker  def testReadPollRst(self):
878*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckPollRst(select.POLLIN, self.POLLIN_ERR_HUP, 0)
879*2f2c4c7aSAndroid Build Coastguard Worker
880*2f2c4c7aSAndroid Build Coastguard Worker  def testWritePollRst(self):
881*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckPollRst(select.POLLOUT, select.POLLOUT, 0)
882*2f2c4c7aSAndroid Build Coastguard Worker
883*2f2c4c7aSAndroid Build Coastguard Worker  def testReadWritePollRst(self):
884*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckPollRst(self.POLLIN_OUT, select.POLLOUT, 0)
885*2f2c4c7aSAndroid Build Coastguard Worker
886*2f2c4c7aSAndroid Build Coastguard Worker  def testReadPollDestroy(self):
887*2f2c4c7aSAndroid Build Coastguard Worker    # tcp_abort has the same race that tcp_reset has, but it's not fixed yet.
888*2f2c4c7aSAndroid Build Coastguard Worker    ignoremask = select.POLLIN | select.POLLHUP
889*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckPollDestroy(select.POLLIN, self.POLLIN_ERR_HUP, ignoremask)
890*2f2c4c7aSAndroid Build Coastguard Worker
891*2f2c4c7aSAndroid Build Coastguard Worker  def testWritePollDestroy(self):
892*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckPollDestroy(select.POLLOUT, select.POLLOUT, 0)
893*2f2c4c7aSAndroid Build Coastguard Worker
894*2f2c4c7aSAndroid Build Coastguard Worker  def testReadWritePollDestroy(self):
895*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckPollDestroy(self.POLLIN_OUT, select.POLLOUT, 0)
896*2f2c4c7aSAndroid Build Coastguard Worker
897*2f2c4c7aSAndroid Build Coastguard Worker
898*2f2c4c7aSAndroid Build Coastguard Workerclass SockDestroyUdpTest(SockDiagBaseTest):
899*2f2c4c7aSAndroid Build Coastguard Worker
900*2f2c4c7aSAndroid Build Coastguard Worker  """Tests SOCK_DESTROY on UDP sockets.
901*2f2c4c7aSAndroid Build Coastguard Worker
902*2f2c4c7aSAndroid Build Coastguard Worker    Relevant kernel commits:
903*2f2c4c7aSAndroid Build Coastguard Worker      upstream net-next:
904*2f2c4c7aSAndroid Build Coastguard Worker        5d77dca net: diag: support SOCK_DESTROY for UDP sockets
905*2f2c4c7aSAndroid Build Coastguard Worker        f95bf34 net: diag: make udp_diag_destroy work for mapped addresses.
906*2f2c4c7aSAndroid Build Coastguard Worker  """
907*2f2c4c7aSAndroid Build Coastguard Worker
908*2f2c4c7aSAndroid Build Coastguard Worker  def testClosesUdpSockets(self):
909*2f2c4c7aSAndroid Build Coastguard Worker    self.socketpairs = self._CreateLotsOfSockets(SOCK_DGRAM)
910*2f2c4c7aSAndroid Build Coastguard Worker    for _, socketpair in self.socketpairs.items():
911*2f2c4c7aSAndroid Build Coastguard Worker      s1, s2 = socketpair
912*2f2c4c7aSAndroid Build Coastguard Worker
913*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketConnected(s1)
914*2f2c4c7aSAndroid Build Coastguard Worker      self.sock_diag.CloseSocketFromFd(s1)
915*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketClosed(s1)
916*2f2c4c7aSAndroid Build Coastguard Worker
917*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketConnected(s2)
918*2f2c4c7aSAndroid Build Coastguard Worker      self.sock_diag.CloseSocketFromFd(s2)
919*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketClosed(s2)
920*2f2c4c7aSAndroid Build Coastguard Worker
921*2f2c4c7aSAndroid Build Coastguard Worker  def BindToRandomPort(self, s, addr):
922*2f2c4c7aSAndroid Build Coastguard Worker    ATTEMPTS = 20
923*2f2c4c7aSAndroid Build Coastguard Worker    for i in range(20):
924*2f2c4c7aSAndroid Build Coastguard Worker      port = random.randrange(1024, 65535)
925*2f2c4c7aSAndroid Build Coastguard Worker      try:
926*2f2c4c7aSAndroid Build Coastguard Worker        s.bind((addr, port))
927*2f2c4c7aSAndroid Build Coastguard Worker        return port
928*2f2c4c7aSAndroid Build Coastguard Worker      except error as e:
929*2f2c4c7aSAndroid Build Coastguard Worker        if e.errno != EADDRINUSE:
930*2f2c4c7aSAndroid Build Coastguard Worker          raise e
931*2f2c4c7aSAndroid Build Coastguard Worker    raise ValueError("Could not find a free port on %s after %d attempts" %
932*2f2c4c7aSAndroid Build Coastguard Worker                     (addr, ATTEMPTS))
933*2f2c4c7aSAndroid Build Coastguard Worker
934*2f2c4c7aSAndroid Build Coastguard Worker  def testSocketAddressesAfterClose(self):
935*2f2c4c7aSAndroid Build Coastguard Worker    for version in 4, 5, 6:
936*2f2c4c7aSAndroid Build Coastguard Worker      netid = random.choice(self.NETIDS)
937*2f2c4c7aSAndroid Build Coastguard Worker      dst = self.GetRemoteSocketAddress(version)
938*2f2c4c7aSAndroid Build Coastguard Worker      family = {4: AF_INET, 5: AF_INET6, 6: AF_INET6}[version]
939*2f2c4c7aSAndroid Build Coastguard Worker      unspec = {4: "0.0.0.0", 5: "::", 6: "::"}[version]
940*2f2c4c7aSAndroid Build Coastguard Worker
941*2f2c4c7aSAndroid Build Coastguard Worker      # Closing a socket that was not explicitly bound (i.e., bound via
942*2f2c4c7aSAndroid Build Coastguard Worker      # connect(), not bind()) clears the source address and port.
943*2f2c4c7aSAndroid Build Coastguard Worker      s = self.BuildSocket(version, net_test.UDPSocket, netid, "mark")
944*2f2c4c7aSAndroid Build Coastguard Worker      self.SelectInterface(s, netid, "mark")
945*2f2c4c7aSAndroid Build Coastguard Worker      s.connect((dst, 53))
946*2f2c4c7aSAndroid Build Coastguard Worker      self.sock_diag.CloseSocketFromFd(s)
947*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual((unspec, 0), s.getsockname()[:2])
948*2f2c4c7aSAndroid Build Coastguard Worker      s.close()
949*2f2c4c7aSAndroid Build Coastguard Worker
950*2f2c4c7aSAndroid Build Coastguard Worker      # Closing a socket bound to an IP address leaves the address as is.
951*2f2c4c7aSAndroid Build Coastguard Worker      s = self.BuildSocket(version, net_test.UDPSocket, netid, "mark")
952*2f2c4c7aSAndroid Build Coastguard Worker      src = self.MySocketAddress(version, netid)
953*2f2c4c7aSAndroid Build Coastguard Worker      s.bind((src, 0))
954*2f2c4c7aSAndroid Build Coastguard Worker      s.connect((dst, 53))
955*2f2c4c7aSAndroid Build Coastguard Worker      port = s.getsockname()[1]
956*2f2c4c7aSAndroid Build Coastguard Worker      self.sock_diag.CloseSocketFromFd(s)
957*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual((src, 0), s.getsockname()[:2])
958*2f2c4c7aSAndroid Build Coastguard Worker      s.close()
959*2f2c4c7aSAndroid Build Coastguard Worker
960*2f2c4c7aSAndroid Build Coastguard Worker      # Closing a socket bound to a port leaves the port as is.
961*2f2c4c7aSAndroid Build Coastguard Worker      s = self.BuildSocket(version, net_test.UDPSocket, netid, "mark")
962*2f2c4c7aSAndroid Build Coastguard Worker      port = self.BindToRandomPort(s, "")
963*2f2c4c7aSAndroid Build Coastguard Worker      s.connect((dst, 53))
964*2f2c4c7aSAndroid Build Coastguard Worker      self.sock_diag.CloseSocketFromFd(s)
965*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual((unspec, port), s.getsockname()[:2])
966*2f2c4c7aSAndroid Build Coastguard Worker      s.close()
967*2f2c4c7aSAndroid Build Coastguard Worker
968*2f2c4c7aSAndroid Build Coastguard Worker      # Closing a socket bound to IP address and port leaves both as is.
969*2f2c4c7aSAndroid Build Coastguard Worker      s = self.BuildSocket(version, net_test.UDPSocket, netid, "mark")
970*2f2c4c7aSAndroid Build Coastguard Worker      src = self.MySocketAddress(version, netid)
971*2f2c4c7aSAndroid Build Coastguard Worker      port = self.BindToRandomPort(s, src)
972*2f2c4c7aSAndroid Build Coastguard Worker      self.sock_diag.CloseSocketFromFd(s)
973*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual((src, port), s.getsockname()[:2])
974*2f2c4c7aSAndroid Build Coastguard Worker      s.close()
975*2f2c4c7aSAndroid Build Coastguard Worker
976*2f2c4c7aSAndroid Build Coastguard Worker  def testReadInterrupted(self):
977*2f2c4c7aSAndroid Build Coastguard Worker    """Tests that read() is interrupted by SOCK_DESTROY."""
978*2f2c4c7aSAndroid Build Coastguard Worker    for version in [4, 5, 6]:
979*2f2c4c7aSAndroid Build Coastguard Worker      family = {4: AF_INET, 5: AF_INET6, 6: AF_INET6}[version]
980*2f2c4c7aSAndroid Build Coastguard Worker      s = net_test.UDPSocket(family)
981*2f2c4c7aSAndroid Build Coastguard Worker      self.SelectInterface(s, random.choice(self.NETIDS), "mark")
982*2f2c4c7aSAndroid Build Coastguard Worker      addr = self.GetRemoteSocketAddress(version)
983*2f2c4c7aSAndroid Build Coastguard Worker
984*2f2c4c7aSAndroid Build Coastguard Worker      # Check that reads on connected sockets are interrupted.
985*2f2c4c7aSAndroid Build Coastguard Worker      s.connect((addr, 53))
986*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(3, s.send(b"foo"))
987*2f2c4c7aSAndroid Build Coastguard Worker      self.CloseDuringBlockingCall(s, lambda sock: sock.recv(4096),
988*2f2c4c7aSAndroid Build Coastguard Worker                                   ECONNABORTED)
989*2f2c4c7aSAndroid Build Coastguard Worker
990*2f2c4c7aSAndroid Build Coastguard Worker      # A destroyed socket is no longer connected, but still usable.
991*2f2c4c7aSAndroid Build Coastguard Worker      self.assertRaisesErrno(EDESTADDRREQ, s.send, b"foo")
992*2f2c4c7aSAndroid Build Coastguard Worker      self.assertEqual(3, s.sendto(b"foo", (addr, 53)))
993*2f2c4c7aSAndroid Build Coastguard Worker
994*2f2c4c7aSAndroid Build Coastguard Worker      # Check that reads on unconnected sockets are also interrupted.
995*2f2c4c7aSAndroid Build Coastguard Worker      self.CloseDuringBlockingCall(s, lambda sock: sock.recv(4096),
996*2f2c4c7aSAndroid Build Coastguard Worker                                   ECONNABORTED)
997*2f2c4c7aSAndroid Build Coastguard Worker
998*2f2c4c7aSAndroid Build Coastguard Worker      s.close()
999*2f2c4c7aSAndroid Build Coastguard Worker
1000*2f2c4c7aSAndroid Build Coastguard Workerclass SockDestroyPermissionTest(SockDiagBaseTest):
1001*2f2c4c7aSAndroid Build Coastguard Worker
1002*2f2c4c7aSAndroid Build Coastguard Worker  def CheckPermissions(self, socktype):
1003*2f2c4c7aSAndroid Build Coastguard Worker    s = socket(AF_INET6, socktype, 0)
1004*2f2c4c7aSAndroid Build Coastguard Worker    self.SelectInterface(s, random.choice(self.NETIDS), "mark")
1005*2f2c4c7aSAndroid Build Coastguard Worker    if socktype == SOCK_STREAM:
1006*2f2c4c7aSAndroid Build Coastguard Worker      s.listen(1)
1007*2f2c4c7aSAndroid Build Coastguard Worker      expectedstate = tcp_test.TCP_LISTEN
1008*2f2c4c7aSAndroid Build Coastguard Worker    else:
1009*2f2c4c7aSAndroid Build Coastguard Worker      s.connect((self.GetRemoteAddress(6), 53))
1010*2f2c4c7aSAndroid Build Coastguard Worker      expectedstate = tcp_test.TCP_ESTABLISHED
1011*2f2c4c7aSAndroid Build Coastguard Worker
1012*2f2c4c7aSAndroid Build Coastguard Worker    with net_test.RunAsUid(12345):
1013*2f2c4c7aSAndroid Build Coastguard Worker      self.assertRaisesErrno(
1014*2f2c4c7aSAndroid Build Coastguard Worker          EPERM, self.sock_diag.CloseSocketFromFd, s)
1015*2f2c4c7aSAndroid Build Coastguard Worker
1016*2f2c4c7aSAndroid Build Coastguard Worker    self.sock_diag.CloseSocketFromFd(s)
1017*2f2c4c7aSAndroid Build Coastguard Worker    self.assertRaises(ValueError, self.sock_diag.CloseSocketFromFd, s)
1018*2f2c4c7aSAndroid Build Coastguard Worker
1019*2f2c4c7aSAndroid Build Coastguard Worker    s.close()
1020*2f2c4c7aSAndroid Build Coastguard Worker
1021*2f2c4c7aSAndroid Build Coastguard Worker
1022*2f2c4c7aSAndroid Build Coastguard Worker  def testUdp(self):
1023*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckPermissions(SOCK_DGRAM)
1024*2f2c4c7aSAndroid Build Coastguard Worker
1025*2f2c4c7aSAndroid Build Coastguard Worker  def testTcp(self):
1026*2f2c4c7aSAndroid Build Coastguard Worker    self.CheckPermissions(SOCK_STREAM)
1027*2f2c4c7aSAndroid Build Coastguard Worker
1028*2f2c4c7aSAndroid Build Coastguard Worker
1029*2f2c4c7aSAndroid Build Coastguard Workerclass SockDiagMarkTest(tcp_test.TcpBaseTest, SockDiagBaseTest):
1030*2f2c4c7aSAndroid Build Coastguard Worker
1031*2f2c4c7aSAndroid Build Coastguard Worker  """Tests SOCK_DIAG bytecode filters that use marks.
1032*2f2c4c7aSAndroid Build Coastguard Worker
1033*2f2c4c7aSAndroid Build Coastguard Worker    Relevant kernel commits:
1034*2f2c4c7aSAndroid Build Coastguard Worker      upstream net-next:
1035*2f2c4c7aSAndroid Build Coastguard Worker        627cc4a net: diag: slightly refactor the inet_diag_bc_audit error checks.
1036*2f2c4c7aSAndroid Build Coastguard Worker        a52e95a net: diag: allow socket bytecode filters to match socket marks
1037*2f2c4c7aSAndroid Build Coastguard Worker        d545cac net: inet: diag: expose the socket mark to privileged processes.
1038*2f2c4c7aSAndroid Build Coastguard Worker  """
1039*2f2c4c7aSAndroid Build Coastguard Worker
1040*2f2c4c7aSAndroid Build Coastguard Worker  def FilterEstablishedSockets(self, mark, mask):
1041*2f2c4c7aSAndroid Build Coastguard Worker    instructions = [(sock_diag.INET_DIAG_BC_MARK_COND, 1, 2, (mark, mask))]
1042*2f2c4c7aSAndroid Build Coastguard Worker    bytecode = self.sock_diag.PackBytecode(instructions)
1043*2f2c4c7aSAndroid Build Coastguard Worker    return self.sock_diag.DumpAllInetSockets(
1044*2f2c4c7aSAndroid Build Coastguard Worker        IPPROTO_TCP, bytecode, states=(1 << tcp_test.TCP_ESTABLISHED))
1045*2f2c4c7aSAndroid Build Coastguard Worker
1046*2f2c4c7aSAndroid Build Coastguard Worker  def assertSamePorts(self, ports, diag_msgs):
1047*2f2c4c7aSAndroid Build Coastguard Worker    expected = sorted(ports)
1048*2f2c4c7aSAndroid Build Coastguard Worker    actual = sorted([msg[0].id.sport for msg in diag_msgs])
1049*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(expected, actual)
1050*2f2c4c7aSAndroid Build Coastguard Worker
1051*2f2c4c7aSAndroid Build Coastguard Worker  def SockInfoMatchesSocket(self, s, info):
1052*2f2c4c7aSAndroid Build Coastguard Worker    try:
1053*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSockInfoMatchesSocket(s, info)
1054*2f2c4c7aSAndroid Build Coastguard Worker      return True
1055*2f2c4c7aSAndroid Build Coastguard Worker    except AssertionError:
1056*2f2c4c7aSAndroid Build Coastguard Worker      return False
1057*2f2c4c7aSAndroid Build Coastguard Worker
1058*2f2c4c7aSAndroid Build Coastguard Worker  @staticmethod
1059*2f2c4c7aSAndroid Build Coastguard Worker  def SocketDescription(s):
1060*2f2c4c7aSAndroid Build Coastguard Worker    return "%s -> %s" % (str(s.getsockname()), str(s.getpeername()))
1061*2f2c4c7aSAndroid Build Coastguard Worker
1062*2f2c4c7aSAndroid Build Coastguard Worker  def assertFoundSockets(self, infos, sockets):
1063*2f2c4c7aSAndroid Build Coastguard Worker    matches = {}
1064*2f2c4c7aSAndroid Build Coastguard Worker    for s in sockets:
1065*2f2c4c7aSAndroid Build Coastguard Worker      match = None
1066*2f2c4c7aSAndroid Build Coastguard Worker      for info in infos:
1067*2f2c4c7aSAndroid Build Coastguard Worker        if self.SockInfoMatchesSocket(s, info):
1068*2f2c4c7aSAndroid Build Coastguard Worker          if match:
1069*2f2c4c7aSAndroid Build Coastguard Worker            self.fail("Socket %s matched both %s and %s" %
1070*2f2c4c7aSAndroid Build Coastguard Worker                      (self.SocketDescription(s), match, info))
1071*2f2c4c7aSAndroid Build Coastguard Worker          matches[s] = info
1072*2f2c4c7aSAndroid Build Coastguard Worker      self.assertTrue(s in matches, "Did not find socket %s in dump" %
1073*2f2c4c7aSAndroid Build Coastguard Worker                      self.SocketDescription(s))
1074*2f2c4c7aSAndroid Build Coastguard Worker
1075*2f2c4c7aSAndroid Build Coastguard Worker    for i in infos:
1076*2f2c4c7aSAndroid Build Coastguard Worker       if i not in list(matches.values()):
1077*2f2c4c7aSAndroid Build Coastguard Worker         self.fail("Too many sockets in dump, first unexpected: %s" % str(i))
1078*2f2c4c7aSAndroid Build Coastguard Worker
1079*2f2c4c7aSAndroid Build Coastguard Worker  def testMarkBytecode(self):
1080*2f2c4c7aSAndroid Build Coastguard Worker    family, addr = random.choice([
1081*2f2c4c7aSAndroid Build Coastguard Worker        (AF_INET, "127.0.0.1"),
1082*2f2c4c7aSAndroid Build Coastguard Worker        (AF_INET6, "::1"),
1083*2f2c4c7aSAndroid Build Coastguard Worker        (AF_INET6, "::ffff:127.0.0.1")])
1084*2f2c4c7aSAndroid Build Coastguard Worker    s1, s2 = net_test.CreateSocketPair(family, SOCK_STREAM, addr)
1085*2f2c4c7aSAndroid Build Coastguard Worker    s1.setsockopt(SOL_SOCKET, net_test.SO_MARK, 0xfff1234)
1086*2f2c4c7aSAndroid Build Coastguard Worker    s2.setsockopt(SOL_SOCKET, net_test.SO_MARK, 0xf0f1235)
1087*2f2c4c7aSAndroid Build Coastguard Worker
1088*2f2c4c7aSAndroid Build Coastguard Worker    infos = self.FilterEstablishedSockets(0x1234, 0xffff)
1089*2f2c4c7aSAndroid Build Coastguard Worker    self.assertFoundSockets(infos, [s1])
1090*2f2c4c7aSAndroid Build Coastguard Worker
1091*2f2c4c7aSAndroid Build Coastguard Worker    infos = self.FilterEstablishedSockets(0x1234, 0xfffe)
1092*2f2c4c7aSAndroid Build Coastguard Worker    self.assertFoundSockets(infos, [s1, s2])
1093*2f2c4c7aSAndroid Build Coastguard Worker
1094*2f2c4c7aSAndroid Build Coastguard Worker    infos = self.FilterEstablishedSockets(0x1235, 0xffff)
1095*2f2c4c7aSAndroid Build Coastguard Worker    self.assertFoundSockets(infos, [s2])
1096*2f2c4c7aSAndroid Build Coastguard Worker
1097*2f2c4c7aSAndroid Build Coastguard Worker    infos = self.FilterEstablishedSockets(0x0, 0x0)
1098*2f2c4c7aSAndroid Build Coastguard Worker    self.assertFoundSockets(infos, [s1, s2])
1099*2f2c4c7aSAndroid Build Coastguard Worker
1100*2f2c4c7aSAndroid Build Coastguard Worker    infos = self.FilterEstablishedSockets(0xfff0000, 0xf0fed00)
1101*2f2c4c7aSAndroid Build Coastguard Worker    self.assertEqual(0, len(infos))
1102*2f2c4c7aSAndroid Build Coastguard Worker
1103*2f2c4c7aSAndroid Build Coastguard Worker    with net_test.RunAsUid(12345):
1104*2f2c4c7aSAndroid Build Coastguard Worker        self.assertRaisesErrno(EPERM, self.FilterEstablishedSockets,
1105*2f2c4c7aSAndroid Build Coastguard Worker                               0xfff0000, 0xf0fed00)
1106*2f2c4c7aSAndroid Build Coastguard Worker
1107*2f2c4c7aSAndroid Build Coastguard Worker    s1.close()
1108*2f2c4c7aSAndroid Build Coastguard Worker    s2.close()
1109*2f2c4c7aSAndroid Build Coastguard Worker
1110*2f2c4c7aSAndroid Build Coastguard Worker  @staticmethod
1111*2f2c4c7aSAndroid Build Coastguard Worker  def SetRandomMark(s):
1112*2f2c4c7aSAndroid Build Coastguard Worker    # Python doesn't like marks that don't fit into a signed int.
1113*2f2c4c7aSAndroid Build Coastguard Worker    mark = random.randrange(0, 2**31 - 1)
1114*2f2c4c7aSAndroid Build Coastguard Worker    s.setsockopt(SOL_SOCKET, net_test.SO_MARK, mark)
1115*2f2c4c7aSAndroid Build Coastguard Worker    return mark
1116*2f2c4c7aSAndroid Build Coastguard Worker
1117*2f2c4c7aSAndroid Build Coastguard Worker  def assertSocketMarkIs(self, s, mark):
1118*2f2c4c7aSAndroid Build Coastguard Worker    diag_msg, attrs = self.sock_diag.FindSockInfoFromFd(s)
1119*2f2c4c7aSAndroid Build Coastguard Worker    self.assertMarkIs(mark, attrs)
1120*2f2c4c7aSAndroid Build Coastguard Worker    with net_test.RunAsUid(12345):
1121*2f2c4c7aSAndroid Build Coastguard Worker      diag_msg, attrs = self.sock_diag.FindSockInfoFromFd(s)
1122*2f2c4c7aSAndroid Build Coastguard Worker      self.assertMarkIs(None, attrs)
1123*2f2c4c7aSAndroid Build Coastguard Worker
1124*2f2c4c7aSAndroid Build Coastguard Worker  def testMarkInAttributes(self):
1125*2f2c4c7aSAndroid Build Coastguard Worker    testcases = [(AF_INET, "127.0.0.1"),
1126*2f2c4c7aSAndroid Build Coastguard Worker                 (AF_INET6, "::1"),
1127*2f2c4c7aSAndroid Build Coastguard Worker                 (AF_INET6, "::ffff:127.0.0.1")]
1128*2f2c4c7aSAndroid Build Coastguard Worker    for family, addr in testcases:
1129*2f2c4c7aSAndroid Build Coastguard Worker      # TCP listen sockets.
1130*2f2c4c7aSAndroid Build Coastguard Worker      server = socket(family, SOCK_STREAM, 0)
1131*2f2c4c7aSAndroid Build Coastguard Worker      server.bind((addr, 0))
1132*2f2c4c7aSAndroid Build Coastguard Worker      port = server.getsockname()[1]
1133*2f2c4c7aSAndroid Build Coastguard Worker      server.listen(1)  # Or the socket won't be in the hashtables.
1134*2f2c4c7aSAndroid Build Coastguard Worker      server_mark = self.SetRandomMark(server)
1135*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketMarkIs(server, server_mark)
1136*2f2c4c7aSAndroid Build Coastguard Worker
1137*2f2c4c7aSAndroid Build Coastguard Worker      # TCP client sockets.
1138*2f2c4c7aSAndroid Build Coastguard Worker      client = socket(family, SOCK_STREAM, 0)
1139*2f2c4c7aSAndroid Build Coastguard Worker      client_mark = self.SetRandomMark(client)
1140*2f2c4c7aSAndroid Build Coastguard Worker      client.connect((addr, port))
1141*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketMarkIs(client, client_mark)
1142*2f2c4c7aSAndroid Build Coastguard Worker
1143*2f2c4c7aSAndroid Build Coastguard Worker      # TCP server sockets.
1144*2f2c4c7aSAndroid Build Coastguard Worker      accepted, _ = server.accept()
1145*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketMarkIs(accepted, server_mark)
1146*2f2c4c7aSAndroid Build Coastguard Worker
1147*2f2c4c7aSAndroid Build Coastguard Worker      accepted_mark = self.SetRandomMark(accepted)
1148*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketMarkIs(accepted, accepted_mark)
1149*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketMarkIs(server, server_mark)
1150*2f2c4c7aSAndroid Build Coastguard Worker
1151*2f2c4c7aSAndroid Build Coastguard Worker      accepted.close()
1152*2f2c4c7aSAndroid Build Coastguard Worker      server.close()
1153*2f2c4c7aSAndroid Build Coastguard Worker      client.close()
1154*2f2c4c7aSAndroid Build Coastguard Worker
1155*2f2c4c7aSAndroid Build Coastguard Worker      # Other TCP states are tested in SockDestroyTcpTest.
1156*2f2c4c7aSAndroid Build Coastguard Worker
1157*2f2c4c7aSAndroid Build Coastguard Worker      # UDP sockets.
1158*2f2c4c7aSAndroid Build Coastguard Worker      s = socket(family, SOCK_DGRAM, 0)
1159*2f2c4c7aSAndroid Build Coastguard Worker      mark = self.SetRandomMark(s)
1160*2f2c4c7aSAndroid Build Coastguard Worker      s.connect(("", 53))
1161*2f2c4c7aSAndroid Build Coastguard Worker      self.assertSocketMarkIs(s, mark)
1162*2f2c4c7aSAndroid Build Coastguard Worker      s.close()
1163*2f2c4c7aSAndroid Build Coastguard Worker
1164*2f2c4c7aSAndroid Build Coastguard Worker      # Basic test for SCTP. sctp_diag was only added in 4.7.
1165*2f2c4c7aSAndroid Build Coastguard Worker      if HAVE_SCTP:
1166*2f2c4c7aSAndroid Build Coastguard Worker        s = socket(family, SOCK_STREAM, IPPROTO_SCTP)
1167*2f2c4c7aSAndroid Build Coastguard Worker        s.bind((addr, 0))
1168*2f2c4c7aSAndroid Build Coastguard Worker        s.listen(1)
1169*2f2c4c7aSAndroid Build Coastguard Worker        mark = self.SetRandomMark(s)
1170*2f2c4c7aSAndroid Build Coastguard Worker        self.assertSocketMarkIs(s, mark)
1171*2f2c4c7aSAndroid Build Coastguard Worker        sockets = self.sock_diag.DumpAllInetSockets(IPPROTO_SCTP, NO_BYTECODE)
1172*2f2c4c7aSAndroid Build Coastguard Worker        self.assertEqual(1, len(sockets))
1173*2f2c4c7aSAndroid Build Coastguard Worker        self.assertEqual(mark, sockets[0][1].get("INET_DIAG_MARK", None))
1174*2f2c4c7aSAndroid Build Coastguard Worker        s.close()
1175*2f2c4c7aSAndroid Build Coastguard Worker
1176*2f2c4c7aSAndroid Build Coastguard Worker
1177*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__":
1178*2f2c4c7aSAndroid Build Coastguard Worker  unittest.main()
1179