18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The Regents of the University of California. All rights reserved. 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Redistribution and use in source and binary forms, with or without 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modification, are permitted provided that the following conditions 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * are met: 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * documentation and/or other materials provided with the distribution. 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 3. Neither the name of the University nor the names of its contributors 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * may be used to endorse or promote products derived from this software 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * without specific prior written permission. 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SUCH DAMAGE. 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * @(#)tcp_input.c 8.5 (Berkeley) 4/10/94 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tcp_input.c,v 1.10 1994/10/13 18:36:32 wollman Exp 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Changes and additions relating to SLiRP 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1995 Danny Gasparovski. 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Please read the file COPYRIGHT for the 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * terms and conditions of the copyright. 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h> 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "ip_icmp.h" 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket tcb; 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TCPREXMTTHRESH 3 478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket *tcp_last_so = &tcb; 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttcp_seq tcp_iss; /* tcp initial send seq # */ 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * PR_SLOWHZ) 528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* for modulo comparisons of timestamps */ 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TSTMP_LT(a,b) ((int)((a)-(b)) < 0) 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TSTMP_GEQ(a,b) ((int)((a)-(b)) >= 0) 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Insert segment ti into reassembly queue of tcp with 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * control block tp. Return TH_FIN if reassembly now includes 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * a segment with FIN. The macro form does the common case inline 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (segment is the next to be received on an established connection, 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and the queue is empty), avoiding linkage into and removal 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * from the queue and repetition of various conversions. 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Set DELACK for segments received in order, but ack immediately 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * when segments are out of order (so fast retransmit can work). 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TCP_ACK_HACK 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TCP_REASS(tp, ti, m, so, flags) {\ 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((ti)->ti_seq == (tp)->rcv_nxt && \ 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcpfrag_list_empty(tp) && \ 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (tp)->t_state == TCPS_ESTABLISHED) {\ 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ti->ti_flags & TH_PUSH) \ 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_ACKNOW; \ 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else \ 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_DELACK; \ 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (tp)->rcv_nxt += (ti)->ti_len; \ 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project flags = (ti)->ti_flags & TH_FIN; \ 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvpack++); \ 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len); \ 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_emu) { \ 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tcp_emu((so),(m))) sbappend((so), (m)); \ 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else \ 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbappend((so), (m)); \ 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* sorwakeup(so); */ \ 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else {\ 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (flags) = tcp_reass((tp), (ti), (m)); \ 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_ACKNOW; \ 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } \ 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TCP_REASS(tp, ti, m, so, flags) { \ 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((ti)->ti_seq == (tp)->rcv_nxt && \ 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcpfrag_list_empty(tp) && \ 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (tp)->t_state == TCPS_ESTABLISHED) { \ 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_DELACK; \ 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (tp)->rcv_nxt += (ti)->ti_len; \ 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project flags = (ti)->ti_flags & TH_FIN; \ 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvpack++); \ 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len); \ 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_emu) { \ 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tcp_emu((so),(m))) sbappend(so, (m)); \ 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else \ 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbappend((so), (m)); \ 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* sorwakeup(so); */ \ 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { \ 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (flags) = tcp_reass((tp), (ti), (m)); \ 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_ACKNOW; \ 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } \ 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct tcpiphdr *ti); 1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_xmit_timer(register struct tcpcb *tp, int rtt); 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, 1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct mbuf *m) 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct tcpiphdr *q; 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so = tp->t_socket; 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int flags; 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Call with ti==NULL after become established to 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * force pre-ESTABLISHED data up to user socket. 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ti == NULL) 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto present; 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Find a segment which begins after this one does. 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (q = tcpfrag_list_first(tp); !tcpfrag_list_end(q, tp); 1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner q = tcpiphdr_next(q)) 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_GT(q->ti_seq, ti->ti_seq)) 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If there is a preceding segment, it may provide some of 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * our data already. If so, drop the data from the incoming 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * segment. If it provides all of our data, drop us. 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!tcpfrag_list_end(tcpiphdr_prev(q), tp)) { 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register int i; 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q = tcpiphdr_prev(q); 1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* conversion to int (in i) handles seq wraparound */ 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = q->ti_seq + q->ti_len - ti->ti_seq; 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i > 0) { 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i >= ti->ti_len) { 1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvduppack++); 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvdupbyte += ti->ti_len); 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_freem(m); 1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Try to present any queued data 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * at the left window edge to the user. 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This is needed after the 3-WHS 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * completes. 1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto present; /* ??? */ 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_adj(m, i); 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_len -= i; 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_seq += i; 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q = tcpiphdr_next(q); 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvoopack++); 1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvoobyte += ti->ti_len); 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_mbuf = m; 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * While we overlap succeeding segments trim them or, 1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if they are completely covered, dequeue them. 1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (!tcpfrag_list_end(q, tp)) { 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i <= 0) 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i < q->ti_len) { 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q->ti_seq += i; 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q->ti_len -= i; 1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_adj(q->ti_mbuf, i); 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q = tcpiphdr_next(q); 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m = tcpiphdr_prev(q)->ti_mbuf; 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project remque(tcpiphdr2qlink(tcpiphdr_prev(q))); 1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_freem(m); 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Stick new segment in its place. 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project insque(tcpiphdr2qlink(ti), tcpiphdr2qlink(tcpiphdr_prev(q))); 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpresent: 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Present data to user, advancing rcv_nxt through 1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * completed sequence space. 2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!TCPS_HAVEESTABLISHED(tp->t_state)) 2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (0); 2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ti = tcpfrag_list_first(tp); 2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tcpfrag_list_end(ti, tp) || ti->ti_seq != tp->rcv_nxt) 2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (0); 2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len) 2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (0); 2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project do { 2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->rcv_nxt += ti->ti_len; 2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project flags = ti->ti_flags & TH_FIN; 2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project remque(tcpiphdr2qlink(ti)); 2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m = ti->ti_mbuf; 2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti = tcpiphdr_next(ti); 2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (so->so_state & SS_FCANTRCVMORE) */ 2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_state & SS_FCANTSENDMORE) 2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_freem(m); 2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else { 2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_emu) { 2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tcp_emu(so,m)) sbappend(so, m); 2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbappend(so, m); 2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); 2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* sorwakeup(so); */ 2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (flags); 2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * TCP input routine, follows pages 65-76 of the 2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * protocol specification dated September, 1981 very closely. 2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_input(struct mbuf *m, int iphlen, struct socket *inso) 2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct ip save_ip, *ip; 2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct tcpiphdr *ti; 2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project caddr_t optp = NULL; 2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int optlen = 0; 2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int len, tlen, off; 2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner register struct tcpcb *tp = NULL; 2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register int tiflags; 2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *so = NULL; 2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int todrop, acked, ourfinisacked, needoutput = 0; 2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* int dropsocket = 0; */ 2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int iss = 0; 2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_long tiwin; 2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* int ts_present = 0; */ 2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ex_list *ex_ptr; 2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("tcp_input"); 2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n", 2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (long )m, iphlen, (long )inso )); 2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If called with m == 0, then we're continuing the connect 2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (m == NULL) { 2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so = inso; 2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Re-set a few variables */ 2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp = sototcpcb(so); 2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m = so->so_m; 2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_m = NULL; 2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti = so->so_ti; 2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiwin = ti->ti_win; 2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiflags = ti->ti_flags; 2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto cont_conn; 2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvtotal++); 2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Get IP and TCP header together in first mbuf. 2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Note: IP leaves IP header in first mbuf. 2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ti = mtod(m, struct tcpiphdr *); 2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iphlen > sizeof(struct ip )) { 2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip_stripoptions(m, (struct mbuf *)0); 2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iphlen=sizeof(struct ip ); 2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* XXX Check if too short */ 2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Save a copy of the IP header in case we want restore it 2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * for sending an ICMP error message in response. 2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip=mtod(m, struct ip *); 2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project save_ip = *ip; 2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project save_ip.ip_len+= iphlen; 2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Checksum extended TCP header and data. 2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tlen = ((struct ip *)ti)->ip_len; 2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL; 2995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr)); 3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_x1 = 0; 3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_len = htons((u_int16_t)tlen); 3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = sizeof(struct ip ) + tlen; 3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* keep checksum for ICMP reply 3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ti->ti_sum = cksum(m, len); 3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if (ti->ti_sum) { */ 3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(cksum(m, len)) { 3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvbadsum++); 3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Check that TCP offset makes sense, 3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * pull out TCP options and adjust length. XXX 3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project off = ti->ti_off << 2; 3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (off < sizeof (struct tcphdr) || off > tlen) { 3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvbadoff++); 3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tlen -= off; 3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_len = tlen; 3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (off > sizeof (struct tcphdr)) { 3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project optlen = off - sizeof (struct tcphdr); 3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr); 3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Do quick retrieval of timestamp options ("options 3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * prediction?"). If timestamp is the only option and it's 3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * formatted as recommended in RFC 1323 appendix A, we 3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * quickly get the values now and not bother calling 3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tcp_dooptions(), etc. 3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if ((optlen == TCPOLEN_TSTAMP_APPA || 3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (optlen > TCPOLEN_TSTAMP_APPA && 3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) && 3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) && 3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (ti->ti_flags & TH_SYN) == 0) { 3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ts_present = 1; 3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ts_val = ntohl(*(u_int32_t *)(optp + 4)); 3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ts_ecr = ntohl(*(u_int32_t *)(optp + 8)); 3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * optp = NULL; / * we've parsed the options * / 3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiflags = ti->ti_flags; 3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Convert TCP protocol specific fields to host format. 3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NTOHL(ti->ti_seq); 3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NTOHL(ti->ti_ack); 3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NTOHS(ti->ti_win); 3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NTOHS(ti->ti_urp); 3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Drop TCP, IP headers and TCP options. 3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); 3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); 3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_restrict) { 3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) 3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ex_ptr->ex_fport == ti->ti_dport && 3645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (ntohl(ti->ti_dst.s_addr) & 0xff) == ex_ptr->ex_addr) 3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ex_ptr) 3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto drop; 3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Locate pcb for segment. 3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfindso: 3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so = tcp_last_so; 3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_fport != ti->ti_dport || 3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_lport != ti->ti_sport || 3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_laddr.s_addr != ti->ti_src.s_addr || 3785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr.s_addr != ti->ti_dst.s_addr) { 3795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so = solookup(&tcb, ti->ti_src, ti->ti_sport, 3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ti->ti_dst, ti->ti_dport); 3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so) 3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_last_so = so; 3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_socachemiss++); 3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If the state is CLOSED (i.e., TCB does not exist) then 3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all data in the incoming segment is discarded. 3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If the TCB exists but is in CLOSED state, it is embryonic, 3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but should either do a listen or a connect soon. 3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * state == CLOSED means we've done socreate() but haven't 3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * attached it to a protocol yet... 3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX If a TCB does not exist, and the TH_SYN flag is 3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the only flag set, then create a session, mark it 3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * as if it was LISTENING, and continue... 3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so == NULL) { 4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN) 4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropwithreset; 4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so = socreate()) == NULL) 4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropwithreset; 4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tcp_attach(so) < 0) { 4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project free(so); /* Not sofree (if it failed, it's not insqued) */ 4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropwithreset; 4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbreserve(&so->so_snd, TCP_SNDSPACE); 4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbreserve(&so->so_rcv, TCP_RCVSPACE); 4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* tcp_last_so = so; */ /* XXX ? */ 4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* tp = sototcpcb(so); */ 4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_laddr = ti->ti_src; 4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_lport = ti->ti_sport; 4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr = ti->ti_dst; 4195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_fport = ti->ti_dport; 4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_iptos = tcp_tos(so)) == 0) 4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_iptos = ((struct ip *)ti)->ip_tos; 4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp = sototcpcb(so); 4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_LISTEN; 4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If this is a still-connecting socket, this probably 4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * a retransmit of the SYN. Whether it's a retransmit SYN 4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * or something else, we nuke it. 4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_state & SS_ISFCONNECTING) 4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp = sototcpcb(so); 4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* XXX Should never fail */ 4395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tp == NULL) 4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropwithreset; 4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_state == TCPS_CLOSED) 4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Unscale the window into a 32-bit value. */ 4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if ((tiflags & TH_SYN) == 0) 4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tiwin = ti->ti_win << tp->snd_scale; 4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * else 4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiwin = ti->ti_win; 4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Segment received on connection. 4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Reset idle time and keep-alive timer. 4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_idle = 0; 4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (SO_OPTIONS) 4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; 4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 4595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; 4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Process options if not in LISTEN state, 4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * else do it below (after getting remote address). 4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (optp && tp->t_state != TCPS_LISTEN) 4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_dooptions(tp, (u_char *)optp, optlen, ti); 4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* , */ 4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* &ts_present, &ts_val, &ts_ecr); */ 4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Header prediction: check for the two common cases 4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of a uni-directional data xfer. If the packet has 4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * no control flags, is in-sequence, the window didn't 4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * change and we're not retransmitting, it's a 4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * candidate. If the length is zero and the ack moved 4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * forward, we're the sender side of the xfer. Just 4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * free the data acked & wake any higher level process 4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * that was blocked waiting for space. If the length 4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * is non-zero and the ack didn't move, we're the 4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * receiver side. If we're getting packets in-order 4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (the reassembly queue is empty), add the data to 4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the socket buffer and note that we need a delayed ack. 4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Some of these tests are not needed 4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * eg: the tiwin == tp->snd_wnd prevents many more 4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * predictions.. with no *real* advantage.. 4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_state == TCPS_ESTABLISHED && 4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK && 4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) && */ 4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_seq == tp->rcv_nxt && 4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiwin && tiwin == tp->snd_wnd && 4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt == tp->snd_max) { 4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If last ACK falls within this segment's sequence numbers, 4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * record the timestamp. 4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && 4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) { 5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->ts_recent_age = tcp_now; 5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->ts_recent = ts_val; 5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ti->ti_len == 0) { 5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_GT(ti->ti_ack, tp->snd_una) && 5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SEQ_LEQ(ti->ti_ack, tp->snd_max) && 5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_cwnd >= tp->snd_wnd) { 5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * this is a pure ack for outstanding data. 5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_predack++); 5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (ts_present) 5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); 5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * else 5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ if (tp->t_rtt && 5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SEQ_GT(ti->ti_ack, tp->t_rtseq)) 5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_xmit_timer(tp, tp->t_rtt); 5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project acked = ti->ti_ack - tp->snd_una; 5195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvackpack++); 5205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvackbyte += acked); 5215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbdrop(&so->so_snd, acked); 5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_una = ti->ti_ack; 5235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_freem(m); 5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If all outstanding data are acked, stop 5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * retransmit timer, otherwise restart timer 5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * using current (possibly backed-off) value. 5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If process is waiting for space, 5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * wakeup/selwakeup/signal. If data 5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * are ready to send, let tcp_output 5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * decide between more output or persist. 5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->snd_una == tp->snd_max) 5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_REXMT] = 0; 5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if (tp->t_timer[TCPT_PERSIST] == 0) 5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; 5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * There's room in so_snd, sowwakup will read() 5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * from the socket if we can 5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (so->so_snd.sb_flags & SB_NOTIFY) 5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sowwakeup(so); 5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This is called because sowwakeup might have 5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * put data into so_snd. Since we don't so sowwakeup, 5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * we don't need this.. XXX??? 5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_snd.sb_cc) 5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (void) tcp_output(tp); 5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (ti->ti_ack == tp->snd_una && 5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcpfrag_list_empty(tp) && 5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ti->ti_len <= sbspace(&so->so_rcv)) { 5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * this is a pure, in-sequence data packet 5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * with nothing on the reassembly queue and 5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * we have enough buffer space to take it. 5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_preddat++); 5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->rcv_nxt += ti->ti_len; 5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvpack++); 5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvbyte += ti->ti_len); 5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Add data to socket buffer. 5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_emu) { 5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tcp_emu(so,m)) sbappend(so, m); 5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbappend(so, m); 5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX This is called when data arrives. Later, check 5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if we can actually write() to the socket 5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Need to check? It's be NON_BLOCKING 5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* sorwakeup(so); */ 5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If this is a short packet, then ACK now - with Nagel 5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * congestion avoidance sender won't send more until 5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * he gets an ACK. 5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * It is better to not delay acks at all to maximize 5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * TCP throughput. See RFC 2581. 5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_ACKNOW; 5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_output(tp); 5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* header prediction */ 5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Calculate amount of space in receive window, 5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and then do TCP input processing. 5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Receive window is amount of space in rcv queue, 6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but not less than advertised window. 6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { int win; 6035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner win = sbspace(&so->so_rcv); 6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (win < 0) 6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project win = 0; 6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt)); 6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (tp->t_state) { 6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If the state is LISTEN then ignore segment if it contains an RST. 6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If the segment contains an ACK then it is bad and send a RST. 6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If it does not contain a SYN then it is not interesting; drop it. 6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Don't bother responding if the destination was a broadcast. 6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial 6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->iss, and send a segment: 6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK> 6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss. 6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Fill in remote peer address fields if not previously specified. 6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Enter SYN_RECEIVED state, and process any other fields of this 6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * segment in this state. 6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_LISTEN: { 6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_RST) 6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_ACK) 6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropwithreset; 6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((tiflags & TH_SYN) == 0) 6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This has way too many gotos... 6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * But a bit of spaghetti code never hurt anybody :) 6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If this is destined for the control address, then flag to 6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tcp_ctl once connected, otherwise connect 6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) { 6435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff; 6445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (lastbyte!=CTL_ALIAS && lastbyte!=CTL_DNS) { 6455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0 6465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if(lastbyte==CTL_CMD || lastbyte==CTL_EXEC) { 6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Command or exec adress */ 6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_state |= SS_CTL; 6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner { 6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* May be an add exec */ 6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { 6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if(ex_ptr->ex_fport == so->so_fport && 6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner lastbyte == ex_ptr->ex_addr) { 6565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_state |= SS_CTL; 6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 6585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if(so->so_state & SS_CTL) goto cont_input; 6625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */ 6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_emu & EMU_NOCONNECT) { 6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_emu &= ~EMU_NOCONNECT; 6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto cont_input; 6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { 6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_char code=ICMP_UNREACH_NET; 6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n", 6745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno,strerror(errno))); 6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(errno == ECONNREFUSED) { 6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ACK the SYN, send RST to refuse the connection */ 6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0, 6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TH_RST|TH_ACK); 6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; 6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project HTONL(ti->ti_seq); /* restore tcp header */ 6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project HTONL(ti->ti_ack); 6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project HTONS(ti->ti_win); 6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project HTONS(ti->ti_urp); 6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); 6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); 6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *ip=save_ip; 6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno)); 6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp = tcp_close(tp); 6915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_free(m); 6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Haven't connected yet, save the current mbuf 6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and ti, and return 6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Some OS's don't tell us whether the connect() 6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * succeeded or not. So we must time it out. 6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_m = m; 7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_ti = ti; 7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; 7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_SYN_RECEIVED; 7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cont_conn: 7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* m==NULL 7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Check if the connect succeeded 7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_state & SS_NOFDREF) { 7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp = tcp_close(tp); 7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropwithreset; 7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cont_input: 7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_template(tp); 7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (optp) 7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_dooptions(tp, (u_char *)optp, optlen, ti); 7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* , */ 7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* &ts_present, &ts_val, &ts_ecr); */ 7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iss) 7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->iss = iss; 7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->iss = tcp_iss; 7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_iss += TCP_ISSINCR/2; 7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->irs = ti->ti_seq; 7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_sendseqinit(tp); 7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_rcvseqinit(tp); 7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_ACKNOW; 7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_SYN_RECEIVED; 7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; 7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_accepts++); 7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto trimthenstep6; 7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* case TCPS_LISTEN */ 7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If the state is SYN_SENT: 7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if seg contains an ACK, but not for our SYN, drop the input. 7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if seg contains a RST, then drop the connection. 7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if seg does not contain SYN, then drop it. 7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Otherwise this is an acceptable SYN segment 7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * initialize tp->rcv_nxt and tp->irs 7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if seg contains ack then advance tp->snd_una 7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if SYN has been acked change to ESTABLISHED else SYN_RCVD state 7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * arrange for segment to be acked (eventually) 7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * continue processing rest of data/controls, beginning with URG 7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_SYN_SENT: 7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((tiflags & TH_ACK) && 7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (SEQ_LEQ(ti->ti_ack, tp->iss) || 7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SEQ_GT(ti->ti_ack, tp->snd_max))) 7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropwithreset; 7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_RST) { 7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_ACK) 7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp = tcp_drop(tp,0); /* XXX Check t_softerror! */ 7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((tiflags & TH_SYN) == 0) 7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_ACK) { 7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_una = ti->ti_ack; 7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_LT(tp->snd_nxt, tp->snd_una)) 7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt = tp->snd_una; 7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_REXMT] = 0; 7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->irs = ti->ti_seq; 7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_rcvseqinit(tp); 7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_ACKNOW; 7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) { 7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_connects++); 7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project soisfconnected(so); 7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_ESTABLISHED; 7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Do window scaling on this connection? */ 7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == 7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (TF_RCVD_SCALE|TF_REQ_SCALE)) { 7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->snd_scale = tp->requested_s_scale; 7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->rcv_scale = tp->request_r_scale; 7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (void) tcp_reass(tp, (struct tcpiphdr *)0, 7865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (struct mbuf *)0); 7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if we didn't have to retransmit the SYN, 7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * use its rtt as our initial srtt & rtt var. 7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_rtt) 7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_xmit_timer(tp, tp->t_rtt); 7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_SYN_RECEIVED; 7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttrimthenstep6: 7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Advance ti->ti_seq to correspond to first data byte. 7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If data, trim to stay within window, 8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * dropping FIN if necessary. 8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_seq++; 8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ti->ti_len > tp->rcv_wnd) { 8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project todrop = ti->ti_len - tp->rcv_wnd; 8055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_adj(m, -todrop); 8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_len = tp->rcv_wnd; 8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiflags &= ~TH_FIN; 8085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvpackafterwin++); 8095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvbyteafterwin += todrop); 8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_wl1 = ti->ti_seq - 1; 8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->rcv_up = ti->ti_seq; 8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto step6; 8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* switch tp->t_state */ 8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * States other than LISTEN or SYN_SENT. 8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * First check timestamp, if present. 8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Then check that at least some bytes of segment are within 8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * receive window. If segment begins before rcv_nxt, 8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * drop leading data (and SYN); if nothing left, just ack. 8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * RFC 1323 PAWS: If we have a timestamp reply on this segment 8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and it's less than ts_recent, drop it. 8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent && 8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * TSTMP_LT(ts_val, tp->ts_recent)) { 8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ /* Check to see if ts_recent is over 24 days old. */ 8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) { 8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ /* 8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * * Invalidate ts_recent. If this segment updates 8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * * ts_recent, the age will be reset later and ts_recent 8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * * will get a valid value. If it does not, setting 8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * * ts_recent to zero will at least satisfy the 8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * * requirement that zero be placed in the timestamp 8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * * echo reply when ts_recent isn't valid. The 8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * * age isn't reset until we get a valid ts_recent 8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * * because we don't want out-of-order segments to be 8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * * dropped when ts_recent is old. 8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * */ 8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* tp->ts_recent = 0; 8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } else { 8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tcpstat.tcps_rcvduppack++; 8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tcpstat.tcps_rcvdupbyte += ti->ti_len; 8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tcpstat.tcps_pawsdrop++; 8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * goto dropafterack; 8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project todrop = tp->rcv_nxt - ti->ti_seq; 8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (todrop > 0) { 8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_SYN) { 8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiflags &= ~TH_SYN; 8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_seq++; 8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ti->ti_urp > 1) 8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_urp--; 8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiflags &= ~TH_URG; 8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project todrop--; 8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Following if statement from Stevens, vol. 2, p. 960. 8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (todrop > ti->ti_len 8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) { 8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Any valid FIN must be to the left of the window. 8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * At this point the FIN must be a duplicate or out 8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of sequence; drop it. 8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiflags &= ~TH_FIN; 8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Send an ACK to resynchronize and drop any data. 8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * But keep on processing for RST or ACK. 8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_ACKNOW; 8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project todrop = ti->ti_len; 8805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvduppack++); 8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvdupbyte += todrop); 8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvpartduppack++); 8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvpartdupbyte += todrop); 8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_adj(m, todrop); 8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_seq += todrop; 8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_len -= todrop; 8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ti->ti_urp > todrop) 8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_urp -= todrop; 8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else { 8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiflags &= ~TH_URG; 8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_urp = 0; 8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If new data are received on a connection after the 8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * user processes are gone, then RST the other end. 8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_state & SS_NOFDREF) && 9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) { 9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp = tcp_close(tp); 9035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvafterclose++); 9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropwithreset; 9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If segment ends after window, drop trailing data 9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (and PUSH and FIN); if nothing left, just ACK. 9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd); 9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (todrop > 0) { 9135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvpackafterwin++); 9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (todrop >= ti->ti_len) { 9155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvbyteafterwin += ti->ti_len); 9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If a new connection request is received 9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * while in TIME_WAIT, drop the old connection 9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and start over if the sequence numbers 9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * are above the previous ones. 9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_SYN && 9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state == TCPS_TIME_WAIT && 9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { 9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iss = tp->rcv_nxt + TCP_ISSINCR; 9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp = tcp_close(tp); 9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto findso; 9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If window is closed can only take segments at 9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * window edge, and have to drop data and PUSH from 9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * incoming segments. Continue processing, but 9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * remember to ack. Otherwise, drop segment 9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and ack. 9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) { 9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_ACKNOW; 9385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvwinprobe++); 9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropafterack; 9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 9425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvbyteafterwin += todrop); 9435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_adj(m, -todrop); 9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_len -= todrop; 9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiflags &= ~(TH_PUSH|TH_FIN); 9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If last ACK falls within this segment's sequence numbers, 9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * record its timestamp. 9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && 9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len + 9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ((tiflags & (TH_SYN|TH_FIN)) != 0))) { 9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->ts_recent_age = tcp_now; 9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->ts_recent = ts_val; 9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If the RST bit is set examine the state: 9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SYN_RECEIVED STATE: 9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If passive open, return to LISTEN state. 9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If active open, inform user that connection was refused. 9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: 9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Inform user that connection was reset, and close tcb. 9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * CLOSING, LAST_ACK, TIME_WAIT STATES 9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Close the tcb. 9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags&TH_RST) switch (tp->t_state) { 9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_SYN_RECEIVED: 9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* so->so_error = ECONNREFUSED; */ 9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto close; 9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_ESTABLISHED: 9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_FIN_WAIT_1: 9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_FIN_WAIT_2: 9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_CLOSE_WAIT: 9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* so->so_error = ECONNRESET; */ 9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project close: 9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_CLOSED; 9835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_drops++); 9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp = tcp_close(tp); 9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_CLOSING: 9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_LAST_ACK: 9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_TIME_WAIT: 9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp = tcp_close(tp); 9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If a SYN is in the window, then this is an 9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * error and we send an RST and drop the connection. 9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_SYN) { 9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp = tcp_drop(tp,0); 10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropwithreset; 10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If the ACK bit is off we drop the segment and return. 10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((tiflags & TH_ACK) == 0) goto drop; 10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Ack processing. 10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (tp->t_state) { 10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In SYN_RECEIVED state if the ack ACKs our SYN then enter 10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ESTABLISHED state and continue processing, otherwise 10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * send an RST. una<=ack<=max 10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_SYN_RECEIVED: 10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_GT(tp->snd_una, ti->ti_ack) || 10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SEQ_GT(ti->ti_ack, tp->snd_max)) 10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropwithreset; 10225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_connects++); 10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_ESTABLISHED; 10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The sent SYN is ack'ed with our sequence number +1 10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The first data byte already in the buffer will get 10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * lost if no correction is made. This is only needed for 10288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SS_CTL since the buffer is empty otherwise. 10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->snd_una++; or: 10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_una=ti->ti_ack; 10328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_state & SS_CTL) { 10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* So tcp_ctl reports the right state */ 10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = tcp_ctl(so); 10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret == 1) { 10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project soisfconnected(so); 10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state &= ~SS_CTL; /* success XXX */ 10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (ret == 2) { 10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state = SS_NOFDREF; /* CTL_CMD */ 10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project needoutput = 1; 10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_FIN_WAIT_1; 10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project soisfconnected(so); 10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Do window scaling? */ 10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == 10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (TF_RCVD_SCALE|TF_REQ_SCALE)) { 10518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->snd_scale = tp->requested_s_scale; 10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->rcv_scale = tp->request_r_scale; 10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 10555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0); 10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_wl1 = ti->ti_seq - 1; 10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Avoid ack processing; snd_una==ti_ack => dup ack */ 10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto synrx_to_est; 10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* fall into ... */ 10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In ESTABLISHED state: drop duplicate ACKs; ACK out of range 10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ACKs. If the ack is in the range 10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->snd_una < ti->ti_ack <= tp->snd_max 10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * then advance tp->snd_una to ti->ti_ack and drop 10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * data from the retransmission queue. If this ACK reflects 10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * more up to date window information we update our window information. 10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_ESTABLISHED: 10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_FIN_WAIT_1: 10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_FIN_WAIT_2: 10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_CLOSE_WAIT: 10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_CLOSING: 10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_LAST_ACK: 10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_TIME_WAIT: 10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) { 10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ti->ti_len == 0 && tiwin == tp->snd_wnd) { 10795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvdupack++); 10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd," dup ack m = %lx so = %lx \n", 10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (long )m, (long )so)); 10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If we have outstanding data (other than 10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * a window probe), this is a completely 10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * duplicate ack (ie, window info didn't 10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * change), the ack is the biggest we've 10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * seen and we've seen exactly our rexmt 10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * threshold of them, assume a packet 10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * has been dropped and retransmit it. 10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Kludge snd_nxt & the congestion 10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * window so we send only this one 10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * packet. 10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We know we're losing at the current 10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * window size so do congestion avoidance 10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (set ssthresh to half the current window 10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and pull our congestion window back to 10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the new ssthresh). 10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Dup acks mean that packets have left the 11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * network (they're now cached at the receiver) 11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * so bump cwnd by the amount in the receiver 11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to keep a constant cwnd packets in the 11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * network. 11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_timer[TCPT_REXMT] == 0 || 11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_ack != tp->snd_una) 11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_dupacks = 0; 11095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (++tp->t_dupacks == TCPREXMTTHRESH) { 11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_seq onxt = tp->snd_nxt; 11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_int win = 11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project min(tp->snd_wnd, tp->snd_cwnd) / 2 / 11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_maxseg; 11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (win < 2) 11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project win = 2; 11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_ssthresh = win * tp->t_maxseg; 11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_REXMT] = 0; 11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_rtt = 0; 11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt = ti->ti_ack; 11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_cwnd = tp->t_maxseg; 11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (void) tcp_output(tp); 11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_cwnd = tp->snd_ssthresh + 11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_maxseg * tp->t_dupacks; 11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_GT(onxt, tp->snd_nxt)) 11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt = onxt; 11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 11285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (tp->t_dupacks > TCPREXMTTHRESH) { 11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_cwnd += tp->t_maxseg; 11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (void) tcp_output(tp); 11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_dupacks = 0; 11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project synrx_to_est: 11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If the congestion window was inflated to account 11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * for the other side's cached packets, retract it. 11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 11425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tp->t_dupacks > TCPREXMTTHRESH && 11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_cwnd > tp->snd_ssthresh) 11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_cwnd = tp->snd_ssthresh; 11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_dupacks = 0; 11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_GT(ti->ti_ack, tp->snd_max)) { 11475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvacktoomuch++); 11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropafterack; 11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project acked = ti->ti_ack - tp->snd_una; 11515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvackpack++); 11525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvackbyte += acked); 11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If we have a timestamp reply, update smoothed 11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * round trip time. If no timestamp is present but 11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * transmit timer is running and timed sequence 11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * number was acked, update smoothed round trip time. 11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Since we now have an rtt measurement, cancel the 11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * timer backoff (cf., Phil Karn's retransmit alg.). 11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Recompute the initial retransmit timer. 11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (ts_present) 11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); 11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * else 11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) 11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_xmit_timer(tp,tp->t_rtt); 11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If all outstanding data is acked, stop retransmit 11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * timer and remember to restart (more output or persist). 11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If there is more data to be acked, restart retransmit 11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * timer, using current (possibly backed-off) value. 11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ti->ti_ack == tp->snd_max) { 11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_REXMT] = 0; 11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project needoutput = 1; 11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (tp->t_timer[TCPT_PERSIST] == 0) 11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; 11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * When new data is acked, open the congestion window. 11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If the window gives us less than ssthresh packets 11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in flight, open exponentially (maxseg per packet). 11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Otherwise open linearly: maxseg per window 11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (maxseg^2 / cwnd per packet). 11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register u_int cw = tp->snd_cwnd; 11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register u_int incr = tp->t_maxseg; 11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (cw > tp->snd_ssthresh) 11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project incr = incr * incr / cw; 11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale); 11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (acked > so->so_snd.sb_cc) { 11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_wnd -= so->so_snd.sb_cc; 11985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbdrop(&so->so_snd, (int )so->so_snd.sb_cc); 11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ourfinisacked = 1; 12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 12015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbdrop(&so->so_snd, acked); 12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_wnd -= acked; 12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ourfinisacked = 0; 12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX sowwakup is called when data is acked and there's room for 12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * for more data... it should read() the socket 12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (so->so_snd.sb_flags & SB_NOTIFY) 12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sowwakeup(so); 12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_una = ti->ti_ack; 12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_LT(tp->snd_nxt, tp->snd_una)) 12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt = tp->snd_una; 12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (tp->t_state) { 12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In FIN_WAIT_1 STATE in addition to the processing 12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * for the ESTABLISHED state if our FIN is now acknowledged 12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * then enter FIN_WAIT_2. 12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_FIN_WAIT_1: 12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ourfinisacked) { 12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If we can't receive any more 12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * data, then closing user can proceed. 12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Starting the timer is contrary to the 12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * specification, but if we don't get a FIN 12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * we'll hang forever. 12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_state & SS_FCANTRCVMORE) { 12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project soisfdisconnected(so); 12345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE; 12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_FIN_WAIT_2; 12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In CLOSING STATE in addition to the processing for 12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the ESTABLISHED state if the ACK acknowledges our FIN 12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * then enter the TIME-WAIT state, otherwise ignore 12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the segment. 12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_CLOSING: 12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ourfinisacked) { 12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_TIME_WAIT; 12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_canceltimers(tp); 12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project soisfdisconnected(so); 12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 12568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In LAST_ACK, we may still be waiting for data to drain 12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and/or to be acked, as well as for the ack of our FIN. 12588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If our FIN is now acknowledged, delete the TCB, 12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * enter the closed state and return. 12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_LAST_ACK: 12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ourfinisacked) { 12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp = tcp_close(tp); 12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In TIME_WAIT state the only thing that should arrive 12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * is a retransmission of the remote FIN. Acknowledge 12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * it and restart the finack timer. 12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_TIME_WAIT: 12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dropafterack; 12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* switch(tp->t_state) */ 12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstep6: 12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Update window information. 12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Don't look at window if no ACK: TAC's send garbage on first SYN. 12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((tiflags & TH_ACK) && 12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (SEQ_LT(tp->snd_wl1, ti->ti_seq) || 12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) || 12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) { 12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* keep track of pure window updates */ 12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ti->ti_len == 0 && 12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd) 12915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rcvwinupd++); 12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_wnd = tiwin; 12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_wl1 = ti->ti_seq; 12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_wl2 = ti->ti_ack; 12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->snd_wnd > tp->max_sndwnd) 12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->max_sndwnd = tp->snd_wnd; 12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project needoutput = 1; 12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Process segments with URG. 13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((tiflags & TH_URG) && ti->ti_urp && 13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCPS_HAVERCVDFIN(tp->t_state) == 0) { 13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This is a kludge, but if we receive and accept 13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * random urgent pointers, we'll crash in 13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * soreceive. It's hard to imagine someone 13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * actually wanting to send this much urgent data. 13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ti->ti_urp + so->so_rcv.sb_cc > so->so_rcv.sb_datalen) { 13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_urp = 0; 13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiflags &= ~TH_URG; 13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto dodata; 13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If this segment advances the known urgent pointer, 13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * then mark the data stream. This should not happen 13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since 13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * a FIN has been received from the remote side. 13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In these states we ignore the URG. 13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * According to RFC961 (Assigned Protocols), 13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the urgent pointer points to the last octet 13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of urgent data. We continue, however, 13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to consider it to indicate the first octet 13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of data past the urgent section as the original 13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * spec states (in one of two places). 13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) { 13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->rcv_up = ti->ti_seq + ti->ti_urp; 13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_urgc = so->so_rcv.sb_cc + 13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (tp->rcv_up - tp->rcv_nxt); /* -1; */ 13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->rcv_up = ti->ti_seq + ti->ti_urp; 13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If no out of band data is expected, 13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * pull receive urgent pointer along 13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * with the receive window. 13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) 13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->rcv_up = tp->rcv_nxt; 13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdodata: 13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Process the segment text, merging it into the TCP sequencing queue, 13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and arranging for acknowledgment of receipt if necessary. 13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This process logically involves adjusting tp->rcv_wnd as data 13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * is presented to the user (this happens in tcp_usrreq.c, 13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * case PRU_RCVD). If a FIN has already been received on this 13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * connection then we just ignore the text. 13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((ti->ti_len || (tiflags&TH_FIN)) && 13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCPS_HAVERCVDFIN(tp->t_state) == 0) { 13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCP_REASS(tp, ti, m, so, tiflags); 13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Note the amount of data that peer has sent into 13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * our window, in order to estimate the sender's 13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * buffer size. 13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt); 13648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 13655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_free(m); 13668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tiflags &= ~TH_FIN; 13678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 13708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If FIN is received ACK the FIN and let the user know 13718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * that the connection is closing. 13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_FIN) { 13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { 13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If we receive a FIN we can't send more data, 13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * set it SS_FDRAIN 13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Shutdown the socket if there is no rx data in the 13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * buffer. 13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * soread() is called on completion of shutdown() and 13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * will got to TCPS_LAST_ACK, and use tcp_output() 13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to send the FIN. 13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* sofcantrcvmore(so); */ 13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofwdrain(so); 13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_ACKNOW; 13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->rcv_nxt++; 13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (tp->t_state) { 13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In SYN_RECEIVED and ESTABLISHED STATES 13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * enter the CLOSE_WAIT state. 13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_SYN_RECEIVED: 13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_ESTABLISHED: 13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(so->so_emu == EMU_CTL) /* no shutdown on socket */ 13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_LAST_ACK; 14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_CLOSE_WAIT; 14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If still in FIN_WAIT_1 STATE FIN has not been acked so 14068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * enter the CLOSING state. 14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 14088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_FIN_WAIT_1: 14098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_CLOSING; 14108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 14118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 14138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In FIN_WAIT_2 state enter the TIME_WAIT state, 14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * starting the time-wait timer, turning off the other 14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * standard timers. 14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_FIN_WAIT_2: 14188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_state = TCPS_TIME_WAIT; 14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_canceltimers(tp); 14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project soisfdisconnected(so); 14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 14258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In TIME_WAIT state restart the 2 MSL time_wait timer. 14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 14278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPS_TIME_WAIT: 14288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If this is a small packet, then ACK now - with Nagel 14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * congestion avoidance sender won't send more until 14368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * he gets an ACK. 14378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 14388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * See above. 14398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 14408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg) { 14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if ((ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg && 14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (so->so_iptos & IPTOS_LOWDELAY) == 0) || 14448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ((so->so_iptos & IPTOS_LOWDELAY) && 14458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ((struct tcpiphdr_2 *)ti)->first_char == (char)27)) { 14468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ti->ti_len && (unsigned)ti->ti_len <= 5 && 14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((struct tcpiphdr_2 *)ti)->first_char == (char)27) { 14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_ACKNOW; 14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Return any desired output. 14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (needoutput || (tp->t_flags & TF_ACKNOW)) { 14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (void) tcp_output(tp); 14578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdropafterack: 14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Generate an ACK dropping incoming segment if it occupies 14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sequence space, where the ACK reflects our state. 14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_RST) 14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto drop; 14675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_freem(m); 14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_ACKNOW; 14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (void) tcp_output(tp); 14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdropwithreset: 14735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* reuses m if m!=NULL, m_free() unnecessary */ 14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_ACK) 14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST); 14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else { 14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tiflags & TH_SYN) ti->ti_len++; 14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0, 14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TH_RST|TH_ACK); 14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdrop: 14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Drop space held by incoming segment and return. 14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 14885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_free(m); 14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* , ts_present, ts_val, ts_ecr) */ 14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* int *ts_present; 14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * u_int32_t *ts_val, *ts_ecr; 14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 14975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 14985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti) 14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_int16_t mss; 15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int opt, optlen; 15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("tcp_dooptions"); 15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARGS((dfd," tp = %lx cnt=%i \n", (long )tp, cnt)); 15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (; cnt > 0; cnt -= optlen, cp += optlen) { 15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project opt = cp[0]; 15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (opt == TCPOPT_EOL) 15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (opt == TCPOPT_NOP) 15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project optlen = 1; 15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else { 15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project optlen = cp[1]; 15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (optlen <= 0) 15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (opt) { 15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project continue; 15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TCPOPT_MAXSEG: 15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (optlen != TCPOLEN_MAXSEG) 15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project continue; 15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(ti->ti_flags & TH_SYN)) 15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project continue; 15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy((char *) &mss, (char *) cp + 2, sizeof(mss)); 15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project NTOHS(mss); 15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (void) tcp_mss(tp, mss); /* sets t_maxseg */ 15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* case TCPOPT_WINDOW: 15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if (optlen != TCPOLEN_WINDOW) 15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * continue; 15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if (!(ti->ti_flags & TH_SYN)) 15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * continue; 15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->t_flags |= TF_RCVD_SCALE; 15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT); 15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * break; 15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* case TCPOPT_TIMESTAMP: 15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if (optlen != TCPOLEN_TIMESTAMP) 15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * continue; 15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * *ts_present = 1; 15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * memcpy((char *) ts_val, (char *)cp + 2, sizeof(*ts_val)); 15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * NTOHL(*ts_val); 15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr)); 15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * NTOHL(*ts_ecr); 15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ /* 15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * * A timestamp received in a SYN makes 15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * * it ok to send timestamp requests and replies. 15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * */ 15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (ti->ti_flags & TH_SYN) { 15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->t_flags |= TF_RCVD_TSTMP; 15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->ts_recent = *ts_val; 15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->ts_recent_age = tcp_now; 15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ break; 15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Pull out of band byte out of a segment so 15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * it doesn't appear in the user's data queue. 15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * It is still reflected in the segment length for 15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sequencing purposes. 15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef notdef 15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 15758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttcp_pulloutofband(so, ti, m) 15768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 15778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct tcpiphdr *ti; 15785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner register struct mbuf *m; 15798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int cnt = ti->ti_urp - 1; 15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (cnt >= 0) { 15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (m->m_len > cnt) { 15845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *cp = mtod(m, caddr_t) + cnt; 15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct tcpcb *tp = sototcpcb(so); 15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_iobc = *cp; 15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_oobflags |= TCPOOB_HAVEDATA; 15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(sp, cp+1, (unsigned)(m->m_len - cnt - 1)); 15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len--; 15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cnt -= m->m_len; 15948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m = m->m_next; /* XXX WRONG! Fix it! */ 15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (m == 0) 15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project panic("tcp_pulloutofband"); 15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* notdef */ 16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Collect new round-trip time estimate 16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and update averages and current timeout. 16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 16095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_xmit_timer(register struct tcpcb *tp, int rtt) 16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register short delta; 16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("tcp_xmit_timer"); 16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("tp = %lx", (long)tp); 16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("rtt = %d", rtt); 16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_rttupdated++); 16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_srtt != 0) { 16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * srtt is stored as fixed point with 3 bits after the 16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * binary point (i.e., scaled by 8). The following magic 16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * is equivalent to the smoothing algorithm in rfc793 with 16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed 16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * point). Adjust rtt to origin 0. 16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project delta = rtt - 1 - (tp->t_srtt >> TCP_RTT_SHIFT); 16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((tp->t_srtt += delta) <= 0) 16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_srtt = 1; 16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We accumulate a smoothed rtt variance (actually, a 16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * smoothed mean difference), then set the retransmit 16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * timer to smoothed rtt + 4 times the smoothed variance. 16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * rttvar is stored as fixed point with 2 bits after the 16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * binary point (scaled by 4). The following is 16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * equivalent to rfc793 smoothing with an alpha of .75 16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (rttvar = rttvar*3/4 + |delta| / 4). This replaces 16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * rfc793's wired-in beta. 16388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (delta < 0) 16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project delta = -delta; 16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT); 16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((tp->t_rttvar += delta) <= 0) 16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_rttvar = 1; 16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 16458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * No rtt measurement yet - use the unsmoothed rtt. 16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Set the variance to half the rtt (so our first 16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * retransmit happens at 3*rtt). 16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_srtt = rtt << TCP_RTT_SHIFT; 16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1); 16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_rtt = 0; 16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_rxtshift = 0; 16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 16578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the retransmit should happen at rtt + 4 * rttvar. 16588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Because of the way we do the smoothing, srtt and rttvar 16598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * will each average +1/2 tick of bias. When we compute 16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the retransmit timer, we want 1/2 tick of rounding and 16618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 1 extra tick because of +-1/2 tick uncertainty in the 16628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * firing of the timer. The bias will give us exactly the 16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 1.5 tick we need. But, because the bias is 16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * statistical, we have to test that we don't drop below 16658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the minimum feasible timer (which is 2 ticks). 16668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 16678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), 16688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ 16698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 16718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We received an ack for a packet that wasn't retransmitted; 16728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * it is probably safe to discard any error indications we've 16738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * received recently. This isn't quite right, but close enough 16748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * for now (a route might have failed after we sent a segment, 16758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and the return path might not be symmetrical). 16768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 16778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_softerror = 0; 16788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 16798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Determine a reasonable value for maxseg size. 16828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If the route is known, check route for mtu. 16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If none, use an mss that can be handled on the outgoing 16848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * interface without forcing IP to fragment; if bigger than 16858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * an mbuf cluster (MCLBYTES), round down to nearest multiple of MCLBYTES 16868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to utilize large mbufs. If no route is found, route has no mtu, 16878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * or the destination isn't local, use a default, hopefully conservative 16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * size (usually 512 or the default IP max size, but no more than the mtu 16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of the interface), as we can't discover anything about intervening 16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * gateways or networks. We also initialize the congestion/slow start 16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * window to be a single segment if the destination isn't local. 16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * While looking at the routing entry, we also initialize other path-dependent 16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * parameters from pre-set or cached values in the routing entry. 16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint 16975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_mss(struct tcpcb *tp, u_int offer) 16988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so = tp->t_socket; 17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int mss; 17018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("tcp_mss"); 17038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("tp = %lx", (long)tp); 17048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("offer = %d", offer); 17058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner mss = min(IF_MTU, IF_MRU) - sizeof(struct tcpiphdr); 17078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offer) 17088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mss = min(mss, offer); 17098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mss = max(mss, 32); 17108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (mss < tp->t_maxseg || offer != 0) 17118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_maxseg = mss; 17128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_cwnd = mss; 17148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbreserve(&so->so_snd, TCP_SNDSPACE + ((TCP_SNDSPACE % mss) ? 17165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (mss - (TCP_SNDSPACE % mss)) : 17175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 0)); 17185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbreserve(&so->so_rcv, TCP_RCVSPACE + ((TCP_RCVSPACE % mss) ? 17195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (mss - (TCP_RCVSPACE % mss)) : 17205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 0)); 17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " returning mss = %d\n", mss)); 17238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return mss; 17258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1726