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 Workerimport time 18*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import * # pylint: disable=wildcard-import 19*2f2c4c7aSAndroid Build Coastguard Worker 20*2f2c4c7aSAndroid Build Coastguard Workerimport net_test 21*2f2c4c7aSAndroid Build Coastguard Workerimport multinetwork_base 22*2f2c4c7aSAndroid Build Coastguard Workerimport packets 23*2f2c4c7aSAndroid Build Coastguard Worker 24*2f2c4c7aSAndroid Build Coastguard Worker# TCP states. See include/net/tcp_states.h. 25*2f2c4c7aSAndroid Build Coastguard WorkerTCP_ESTABLISHED = 1 26*2f2c4c7aSAndroid Build Coastguard WorkerTCP_SYN_SENT = 2 27*2f2c4c7aSAndroid Build Coastguard WorkerTCP_SYN_RECV = 3 28*2f2c4c7aSAndroid Build Coastguard WorkerTCP_FIN_WAIT1 = 4 29*2f2c4c7aSAndroid Build Coastguard WorkerTCP_FIN_WAIT2 = 5 30*2f2c4c7aSAndroid Build Coastguard WorkerTCP_TIME_WAIT = 6 31*2f2c4c7aSAndroid Build Coastguard WorkerTCP_CLOSE = 7 32*2f2c4c7aSAndroid Build Coastguard WorkerTCP_CLOSE_WAIT = 8 33*2f2c4c7aSAndroid Build Coastguard WorkerTCP_LAST_ACK = 9 34*2f2c4c7aSAndroid Build Coastguard WorkerTCP_LISTEN = 10 35*2f2c4c7aSAndroid Build Coastguard WorkerTCP_CLOSING = 11 36*2f2c4c7aSAndroid Build Coastguard WorkerTCP_NEW_SYN_RECV = 12 37*2f2c4c7aSAndroid Build Coastguard Worker 38*2f2c4c7aSAndroid Build Coastguard WorkerTCP_NOT_YET_ACCEPTED = -1 39*2f2c4c7aSAndroid Build Coastguard Worker 40*2f2c4c7aSAndroid Build Coastguard Worker 41*2f2c4c7aSAndroid Build Coastguard Workerclass TcpBaseTest(multinetwork_base.MultiNetworkBaseTest): 42*2f2c4c7aSAndroid Build Coastguard Worker 43*2f2c4c7aSAndroid Build Coastguard Worker def __init__(self, *args, **kwargs): 44*2f2c4c7aSAndroid Build Coastguard Worker super().__init__(*args, **kwargs) 45*2f2c4c7aSAndroid Build Coastguard Worker self.accepted = None 46*2f2c4c7aSAndroid Build Coastguard Worker self.s = None 47*2f2c4c7aSAndroid Build Coastguard Worker self.last_packet = None 48*2f2c4c7aSAndroid Build Coastguard Worker self.sent_fin = False 49*2f2c4c7aSAndroid Build Coastguard Worker 50*2f2c4c7aSAndroid Build Coastguard Worker def CloseSockets(self): 51*2f2c4c7aSAndroid Build Coastguard Worker if self.accepted: 52*2f2c4c7aSAndroid Build Coastguard Worker self.accepted.close() 53*2f2c4c7aSAndroid Build Coastguard Worker self.accepted = None 54*2f2c4c7aSAndroid Build Coastguard Worker if self.s: 55*2f2c4c7aSAndroid Build Coastguard Worker self.s.close() 56*2f2c4c7aSAndroid Build Coastguard Worker self.s = None 57*2f2c4c7aSAndroid Build Coastguard Worker 58*2f2c4c7aSAndroid Build Coastguard Worker def tearDown(self): 59*2f2c4c7aSAndroid Build Coastguard Worker self.CloseSockets() 60*2f2c4c7aSAndroid Build Coastguard Worker super(TcpBaseTest, self).tearDown() 61*2f2c4c7aSAndroid Build Coastguard Worker 62*2f2c4c7aSAndroid Build Coastguard Worker def OpenListenSocket(self, version, netid): 63*2f2c4c7aSAndroid Build Coastguard Worker family = {4: AF_INET, 5: AF_INET6, 6: AF_INET6}[version] 64*2f2c4c7aSAndroid Build Coastguard Worker address = {4: "0.0.0.0", 5: "::", 6: "::"}[version] 65*2f2c4c7aSAndroid Build Coastguard Worker s = net_test.Socket(family, SOCK_STREAM, IPPROTO_TCP) 66*2f2c4c7aSAndroid Build Coastguard Worker # We haven't configured inbound iptables marking, so bind explicitly. 67*2f2c4c7aSAndroid Build Coastguard Worker self.SelectInterface(s, netid, "mark") 68*2f2c4c7aSAndroid Build Coastguard Worker self.port = net_test.BindRandomPort(version, s) 69*2f2c4c7aSAndroid Build Coastguard Worker return s 70*2f2c4c7aSAndroid Build Coastguard Worker 71*2f2c4c7aSAndroid Build Coastguard Worker def _ReceiveAndExpectResponse(self, netid, packet, reply, msg): 72*2f2c4c7aSAndroid Build Coastguard Worker pkt = super(TcpBaseTest, self)._ReceiveAndExpectResponse(netid, packet, 73*2f2c4c7aSAndroid Build Coastguard Worker reply, msg) 74*2f2c4c7aSAndroid Build Coastguard Worker self.last_packet = pkt 75*2f2c4c7aSAndroid Build Coastguard Worker return pkt 76*2f2c4c7aSAndroid Build Coastguard Worker 77*2f2c4c7aSAndroid Build Coastguard Worker def ReceivePacketOn(self, netid, packet): 78*2f2c4c7aSAndroid Build Coastguard Worker super(TcpBaseTest, self).ReceivePacketOn(netid, packet) 79*2f2c4c7aSAndroid Build Coastguard Worker self.last_packet = packet 80*2f2c4c7aSAndroid Build Coastguard Worker 81*2f2c4c7aSAndroid Build Coastguard Worker def ReceiveRstPacketOn(self, netid): 82*2f2c4c7aSAndroid Build Coastguard Worker # self.last_packet is the last packet we received. Invert direction twice. 83*2f2c4c7aSAndroid Build Coastguard Worker _, ack = packets.ACK(self.version, self.myaddr, self.remoteaddr, 84*2f2c4c7aSAndroid Build Coastguard Worker self.last_packet) 85*2f2c4c7aSAndroid Build Coastguard Worker desc, rst = packets.RST(self.version, self.remoteaddr, self.myaddr, 86*2f2c4c7aSAndroid Build Coastguard Worker ack) 87*2f2c4c7aSAndroid Build Coastguard Worker super(TcpBaseTest, self).ReceivePacketOn(netid, rst) 88*2f2c4c7aSAndroid Build Coastguard Worker 89*2f2c4c7aSAndroid Build Coastguard Worker def RstPacket(self): 90*2f2c4c7aSAndroid Build Coastguard Worker return packets.RST(self.version, self.myaddr, self.remoteaddr, 91*2f2c4c7aSAndroid Build Coastguard Worker self.last_packet, self.sent_fin) 92*2f2c4c7aSAndroid Build Coastguard Worker 93*2f2c4c7aSAndroid Build Coastguard Worker def FinPacket(self): 94*2f2c4c7aSAndroid Build Coastguard Worker return packets.FIN(self.version, self.myaddr, self.remoteaddr, 95*2f2c4c7aSAndroid Build Coastguard Worker self.last_packet) 96*2f2c4c7aSAndroid Build Coastguard Worker 97*2f2c4c7aSAndroid Build Coastguard Worker def ExpectPacketOn(self, netid, msg, pkt): 98*2f2c4c7aSAndroid Build Coastguard Worker self.sent_fin |= (pkt.getlayer("TCP").flags & packets.TCP_FIN) != 0 99*2f2c4c7aSAndroid Build Coastguard Worker return super(TcpBaseTest, self).ExpectPacketOn(netid, msg, pkt) 100*2f2c4c7aSAndroid Build Coastguard Worker 101*2f2c4c7aSAndroid Build Coastguard Worker def IncomingConnection(self, version, end_state, netid): 102*2f2c4c7aSAndroid Build Coastguard Worker self.s = self.OpenListenSocket(version, netid) 103*2f2c4c7aSAndroid Build Coastguard Worker self.end_state = end_state 104*2f2c4c7aSAndroid Build Coastguard Worker 105*2f2c4c7aSAndroid Build Coastguard Worker remoteaddr = self.remoteaddr = self.GetRemoteAddress(version) 106*2f2c4c7aSAndroid Build Coastguard Worker remotesockaddr = self.remotesockaddr = self.GetRemoteSocketAddress(version) 107*2f2c4c7aSAndroid Build Coastguard Worker 108*2f2c4c7aSAndroid Build Coastguard Worker myaddr = self.myaddr = self.MyAddress(version, netid) 109*2f2c4c7aSAndroid Build Coastguard Worker mysockaddr = self.mysockaddr = self.MySocketAddress(version, netid) 110*2f2c4c7aSAndroid Build Coastguard Worker 111*2f2c4c7aSAndroid Build Coastguard Worker if version == 5: version = 4 112*2f2c4c7aSAndroid Build Coastguard Worker self.version = version 113*2f2c4c7aSAndroid Build Coastguard Worker 114*2f2c4c7aSAndroid Build Coastguard Worker if end_state == TCP_LISTEN: 115*2f2c4c7aSAndroid Build Coastguard Worker return 116*2f2c4c7aSAndroid Build Coastguard Worker 117*2f2c4c7aSAndroid Build Coastguard Worker desc, syn = packets.SYN(self.port, version, remoteaddr, myaddr) 118*2f2c4c7aSAndroid Build Coastguard Worker synack_desc, synack = packets.SYNACK(version, myaddr, remoteaddr, syn) 119*2f2c4c7aSAndroid Build Coastguard Worker msg = "Received %s, expected to see reply %s" % (desc, synack_desc) 120*2f2c4c7aSAndroid Build Coastguard Worker reply = self._ReceiveAndExpectResponse(netid, syn, synack, msg) 121*2f2c4c7aSAndroid Build Coastguard Worker if end_state == TCP_SYN_RECV: 122*2f2c4c7aSAndroid Build Coastguard Worker return 123*2f2c4c7aSAndroid Build Coastguard Worker 124*2f2c4c7aSAndroid Build Coastguard Worker establishing_ack = packets.ACK(version, remoteaddr, myaddr, reply)[1] 125*2f2c4c7aSAndroid Build Coastguard Worker self.ReceivePacketOn(netid, establishing_ack) 126*2f2c4c7aSAndroid Build Coastguard Worker 127*2f2c4c7aSAndroid Build Coastguard Worker if end_state == TCP_NOT_YET_ACCEPTED: 128*2f2c4c7aSAndroid Build Coastguard Worker return 129*2f2c4c7aSAndroid Build Coastguard Worker 130*2f2c4c7aSAndroid Build Coastguard Worker self.accepted, _ = self.s.accept() 131*2f2c4c7aSAndroid Build Coastguard Worker net_test.DisableFinWait(self.accepted) 132*2f2c4c7aSAndroid Build Coastguard Worker 133*2f2c4c7aSAndroid Build Coastguard Worker if end_state == TCP_ESTABLISHED: 134*2f2c4c7aSAndroid Build Coastguard Worker return 135*2f2c4c7aSAndroid Build Coastguard Worker 136*2f2c4c7aSAndroid Build Coastguard Worker desc, data = packets.ACK(version, myaddr, remoteaddr, establishing_ack, 137*2f2c4c7aSAndroid Build Coastguard Worker payload=net_test.UDP_PAYLOAD) 138*2f2c4c7aSAndroid Build Coastguard Worker self.accepted.send(net_test.UDP_PAYLOAD) 139*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg + ": expecting %s" % desc, data) 140*2f2c4c7aSAndroid Build Coastguard Worker 141*2f2c4c7aSAndroid Build Coastguard Worker desc, fin = packets.FIN(version, remoteaddr, myaddr, data) 142*2f2c4c7aSAndroid Build Coastguard Worker fin = packets._GetIpLayer(version)(bytes(fin)) 143*2f2c4c7aSAndroid Build Coastguard Worker ack_desc, ack = packets.ACK(version, myaddr, remoteaddr, fin) 144*2f2c4c7aSAndroid Build Coastguard Worker msg = "Received %s, expected to see reply %s" % (desc, ack_desc) 145*2f2c4c7aSAndroid Build Coastguard Worker 146*2f2c4c7aSAndroid Build Coastguard Worker # TODO: Why can't we use this? 147*2f2c4c7aSAndroid Build Coastguard Worker # self._ReceiveAndExpectResponse(netid, fin, ack, msg) 148*2f2c4c7aSAndroid Build Coastguard Worker self.ReceivePacketOn(netid, fin) 149*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(0.1) 150*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(netid, msg + ": expecting %s" % ack_desc, ack) 151*2f2c4c7aSAndroid Build Coastguard Worker if end_state == TCP_CLOSE_WAIT: 152*2f2c4c7aSAndroid Build Coastguard Worker return 153*2f2c4c7aSAndroid Build Coastguard Worker 154*2f2c4c7aSAndroid Build Coastguard Worker raise ValueError("Invalid TCP state %d specified" % end_state) 155