18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1982, 1986, 1988, 1990, 1993 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_output.c 8.3 (Berkeley) 12/30/93 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tcp_output.c,v 1.3 1994/09/15 10:36:55 davidg 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. 365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 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 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Since this is only used in "stats socket", we give meaning 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * names instead of the REAL names 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerconst char * const tcpstates[] = { 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */ 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project "REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD", 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", 528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const u_char tcp_outflags[TCP_NSTATES] = { 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TH_FIN|TH_ACK, TH_ACK, TH_ACK, 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MAX_TCPOPTLEN 32 /* max # bytes that go in options */ 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Tcp output routine: figure out what should be sent and send it. 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint 675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_output(struct tcpcb *tp) 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct socket *so = tp->t_socket; 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register long len, win; 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int off, flags, error; 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner register struct mbuf *m; 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct tcpiphdr *ti; 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_char opt[MAX_TCPOPTLEN]; 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned optlen, hdrlen; 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int idle, sendalot; 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("tcp_output"); 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("tp = %lx", (long )tp); 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Determine length of data that should be transmitted, 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and flags that will be used. 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If there is some data or critical controls (SYN, RST) 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to send, then transmit; otherwise, investigate further. 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project idle = (tp->snd_max == tp->snd_una); 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (idle && tp->t_idle >= tp->t_rxtcur) 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We have been idle for "a while" and no acks are 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * expected to clock out any data we send -- 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * slow start to get ack "clock" running again. 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_cwnd = tp->t_maxseg; 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectagain: 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sendalot = 0; 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project off = tp->snd_nxt - tp->snd_una; 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project win = min(tp->snd_wnd, tp->snd_cwnd); 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project flags = tcp_outflags[tp->t_state]; 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags)); 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If in persist timeout with window of 0, send 1 byte. 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Otherwise, if window is small but nonzero 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and timer expired, we will send what we can 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and go to transmit state. 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_force) { 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (win == 0) { 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If we still have some data to send, then 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * clear the FIN bit. Usually this would 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * happen below when it realizes that we 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * aren't sending all the data. However, 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if we have exactly 1 byte of unset data, 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * then it won't clear the FIN bit below, 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and if we are in persist state, we wind 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * up sending the packet without recording 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * that we sent the FIN bit. 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We can't just blindly clear the FIN bit, 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * because if we don't have any more data 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to send then the probe will be the FIN 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * itself. 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (off < so->so_snd.sb_cc) 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project flags &= ~TH_FIN; 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project win = 1; 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_PERSIST] = 0; 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_rxtshift = 0; 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = min(so->so_snd.sb_cc, win) - off; 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len < 0) { 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If FIN has been sent but not acked, 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but we haven't been called to retransmit, 1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * len will be -1. Otherwise, window shrank 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * after we sent into it. If window shrank to 0, 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * cancel pending retransmit and pull snd_nxt 1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * back to (closed) window. We will enter persist 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * state below. If the window didn't close completely, 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * just wait for an ACK. 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = 0; 1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (win == 0) { 1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_REXMT] = 0; 1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt = tp->snd_una; 1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len > tp->t_maxseg) { 1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = tp->t_maxseg; 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sendalot = 1; 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project flags &= ~TH_FIN; 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner win = sbspace(&so->so_rcv); 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Sender silly window avoidance. If connection is idle 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and can send all data, a maximum segment, 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * at least a maximum default-size segment do it, 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * or are forced, do it; otherwise don't bother. 1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If peer's buffer is tiny, then send 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * when window is at least half open. 1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If retransmitting (possibly after persist timer forced us 1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to send into a small window), then must resend. 1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len) { 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len == tp->t_maxseg) 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto send; 1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((1 || idle || tp->t_flags & TF_NODELAY) && 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len + off >= so->so_snd.sb_cc) 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto send; 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_force) 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto send; 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0) 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto send; 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_LT(tp->snd_nxt, tp->snd_max)) 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto send; 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Compare available window to amount of window 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * known to peer (as advertised window less 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * next expected input). If the difference is at least two 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * max size segments, or at least 50% of the maximum possible 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * window, then want to send a window update to peer. 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (win > 0) { 1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * "adv" is the amount we can increase the window, 2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * taking into account that we are limited by 2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * TCP_MAXWIN << tp->rcv_scale. 2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) - 2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (tp->rcv_adv - tp->rcv_nxt); 2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (adv >= (long) (2 * tp->t_maxseg)) 2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto send; 2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (2 * adv >= (long) so->so_rcv.sb_datalen) 2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto send; 2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Send if we owe peer an ACK. 2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_flags & TF_ACKNOW) 2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto send; 2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & (TH_SYN|TH_RST)) 2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto send; 2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_GT(tp->snd_up, tp->snd_una)) 2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto send; 2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If our state indicates that FIN should be sent 2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and we have not yet done so, or we're retransmitting the FIN, 2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * then we need to send. 2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & TH_FIN && 2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una)) 2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto send; 2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * TCP window updates are not reliable, rather a polling protocol 2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * using ``persist'' packets is used to insure receipt of window 2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * updates. The three ``states'' for the output side are: 2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * idle not doing retransmits or persists 2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * persisting to move a small or zero window 2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (re)transmitting and thereby not persisting 2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->t_timer[TCPT_PERSIST] 2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * is set when we are in persist state. 2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->t_force 2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * is set when we are called to send a persist packet. 2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->t_timer[TCPT_REXMT] 2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * is set when we are retransmitting 2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The output side is idle when both timers are zero. 2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If send window is too small, there is data to transmit, and no 2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * retransmit or persist is pending, then go to persist state. 2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If nothing happens soon, send when timer expires: 2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if window is nonzero, transmit what we can, 2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * otherwise force out a byte. 2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 && 2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_PERSIST] == 0) { 2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_rxtshift = 0; 2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_setpersist(tp); 2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * No reason to send a segment, just return. 2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_didnuttin++); 2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (0); 2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsend: 2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Before ESTABLISHED, force sending of initial options 2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * unless TCP set not to do any options. 2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * NOTE: we assume that the IP/TCP header plus TCP options 2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * always fit in a single mbuf, leaving room for a maximum 2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * link header, i.e. 2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN 2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project optlen = 0; 2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project hdrlen = sizeof (struct tcpiphdr); 2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & TH_SYN) { 2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt = tp->iss; 2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((tp->t_flags & TF_NOOPT) == 0) { 2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_int16_t mss; 2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project opt[0] = TCPOPT_MAXSEG; 2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project opt[1] = 4; 2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mss = htons((u_int16_t) tcp_mss(tp, 0)); 2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss)); 2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project optlen = 4; 2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if ((tp->t_flags & TF_REQ_SCALE) && 2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ((flags & TH_ACK) == 0 || 2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (tp->t_flags & TF_RCVD_SCALE))) { 2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * *((u_int32_t *) (opt + optlen)) = htonl( 2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * TCPOPT_NOP << 24 | 2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * TCPOPT_WINDOW << 16 | 2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * TCPOLEN_WINDOW << 8 | 2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->request_r_scale); 2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * optlen += 4; 2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Send a timestamp and echo-reply if this is a SYN and our side 3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * wants to use timestamps (TF_REQ_TSTMP is set) or both our side 3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and our peer have sent timestamps in our SYN's. 3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && 3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (flags & TH_RST) == 0 && 3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ((flags & (TH_SYN|TH_ACK)) == TH_SYN || 3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (tp->t_flags & TF_RCVD_TSTMP))) { 3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * u_int32_t *lp = (u_int32_t *)(opt + optlen); 3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * / * Form timestamp option as shown in appendix A of RFC 1323. * / 3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * *lp++ = htonl(TCPOPT_TSTAMP_HDR); 3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * *lp++ = htonl(tcp_now); 3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * *lp = htonl(tp->ts_recent); 3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * optlen += TCPOLEN_TSTAMP_APPA; 3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project hdrlen += optlen; 3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Adjust data length if insertion of options will 3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * bump the packet length beyond the t_maxseg length. 3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len > tp->t_maxseg - optlen) { 3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = tp->t_maxseg - optlen; 3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sendalot = 1; 3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Grab a header mbuf, attaching a copy of data to 3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * be transmitted, and initialize the header from 3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the template for sends on this connection. 3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len) { 3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_force && len == 1) 3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_sndprobe++); 3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { 3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_sndrexmitpack++); 3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_sndrexmitbyte += len); 3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_sndpack++); 3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_sndbyte += len); 3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m = m_get(); 3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (m == NULL) { 3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* error = ENOBUFS; */ 3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project error = 1; 3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto out; 3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_data += IF_MAXLINKHDR; 3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len = hdrlen; 3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This will always succeed, since we make sure our mbufs 3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * are big enough to hold one MSS packet + header + ... etc. 3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (len <= MHLEN - hdrlen - max_linkhdr) { */ 3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen); 3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len += len; 3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* } else { 3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len); 3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if (m->m_next == 0) 3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * len = 0; 3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If we're sending everything we've got, set PUSH. 3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (This will keep happy those implementations which only 3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * give data to the user when a buffer fills or 3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * a PUSH comes in.) 3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (off + len == so->so_snd.sb_cc) 3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project flags |= TH_PUSH; 3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_flags & TF_ACKNOW) 3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_sndacks++); 3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if (flags & (TH_SYN|TH_FIN|TH_RST)) 3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_sndctrl++); 3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if (SEQ_GT(tp->snd_up, tp->snd_una)) 3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_sndurg++); 3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_sndwinup++); 3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m = m_get(); 3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (m == NULL) { 3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* error = ENOBUFS; */ 3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project error = 1; 3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto out; 3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_data += IF_MAXLINKHDR; 3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len = hdrlen; 3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ti = mtod(m, struct tcpiphdr *); 3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr)); 4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Fill in fields, remembering maximum advertised 4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * window for use in delaying messages about window sizes. 4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If resending a FIN, be sure not to use a new sequence number. 4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && 4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt == tp->snd_max) 4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt--; 4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If we are doing retransmissions, then snd_nxt will 4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * not reflect the first unsent octet. For ACK only 4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * packets, we do not want the sequence number of the 4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * retransmitted packet, we want the sequence number 4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of the next unsent octet. So, if there is no data 4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (and no SYN or FIN), use snd_max instead of snd_nxt 4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * when filling in ti_seq. But if we are in persist 4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * state, snd_max might reflect one byte beyond the 4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * right edge of the window, so use snd_nxt in that 4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * case, since we know we aren't doing a retransmission. 4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (retransmit and persist are mutually exclusive...) 4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST]) 4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_seq = htonl(tp->snd_nxt); 4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_seq = htonl(tp->snd_max); 4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_ack = htonl(tp->rcv_nxt); 4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (optlen) { 4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy((caddr_t)(ti + 1), (caddr_t)opt, optlen); 4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2; 4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_flags = flags; 4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Calculate receive window. Don't shrink window, 4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but avoid silly window syndrome. 4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg) 4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project win = 0; 4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (win > (long)TCP_MAXWIN << tp->rcv_scale) 4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project win = (long)TCP_MAXWIN << tp->rcv_scale; 4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) 4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project win = (long)(tp->rcv_adv - tp->rcv_nxt); 4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale)); 4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_GT(tp->snd_up, tp->snd_una)) { 4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq))); 4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef notdef 4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { 4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt)); 4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_flags |= TH_URG; 4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If no urgent pointer to send, then we pull 4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the urgent pointer to the left edge of the send window 4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * so that it doesn't drift into the send window on sequence 4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * number wraparound. 4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_up = tp->snd_una; /* drag it along */ 4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Put TCP length in extended header, and then 4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * checksum extended header and data. 4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len + optlen) 4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_len = htons((u_int16_t)(sizeof (struct tcphdr) + 4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project optlen + len)); 4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ti->ti_sum = cksum(m, (int)(hdrlen + len)); 4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In transmit state, time the transmission and arrange for 4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the retransmit. In persist state, just set snd_max. 4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) { 4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_seq startseq = tp->snd_nxt; 4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Advance snd_nxt over sequence space of this segment. 4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & (TH_SYN|TH_FIN)) { 4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & TH_SYN) 4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt++; 4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & TH_FIN) { 4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt++; 4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags |= TF_SENTFIN; 4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt += len; 4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { 4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_max = tp->snd_nxt; 4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Time this transmission if not a retransmission and 4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * not currently timing anything. 4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_rtt == 0) { 4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_rtt = 1; 4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_rtseq = startseq; 4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_segstimed++); 4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Set retransmit timer if not currently set, 5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and not doing an ack or a keep-alive probe. 5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Initial value for retransmit timer is smoothed 5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * round-trip time + 2 * round-trip time variance. 5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Initialize shift counter which is used for backoff 5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of retransmit time. 5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_timer[TCPT_REXMT] == 0 && 5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_nxt != tp->snd_una) { 5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; 5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_timer[TCPT_PERSIST]) { 5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_timer[TCPT_PERSIST] = 0; 5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_rxtshift = 0; 5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (SEQ_GT(tp->snd_nxt + len, tp->snd_max)) 5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_max = tp->snd_nxt + len; 5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Fill in IP length and desired time to live and 5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * send to IP level. There should be a better way 5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to handle ttl and tos; we could keep them in 5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the template, but need a way to checksum without them. 5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */ 5295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 5315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((struct ip *)ti)->ip_len = m->m_len; 5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ((struct ip *)ti)->ip_ttl = IPDEFTTL; 5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((struct ip *)ti)->ip_tos = so->so_iptos; 5365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* #if BSD >= 43 */ 5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Don't do IP options... */ 5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, 5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * so->so_options & SO_DONTROUTE, 0); 5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project error = ip_output(so, m); 5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* #else 5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, 5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * so->so_options & SO_DONTROUTE); 5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * #endif 5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (error) { 5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectout: 5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (error == ENOBUFS) { 5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tcp_quench(tp->t_inpcb, 0); 5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * return (0); 5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if ((error == EHOSTUNREACH || error == ENETDOWN) 5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * && TCPS_HAVERCVDSYN(tp->t_state)) { 5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tp->t_softerror = error; 5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * return (0); 5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (error); 5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(tcpstat.tcps_sndtotal++); 5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Data sent (as far as we can tell). 5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If this advertises a larger window than any other segment, 5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * then remember the size of the advertised window. 5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Any pending ACK has now been sent. 5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) 5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->rcv_adv = tp->rcv_nxt + win; 5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->last_ack_sent = tp->rcv_nxt; 5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); 5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sendalot) 5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto again; 5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (0); 5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 5845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_setpersist(struct tcpcb *tp) 5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; 5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if (tp->t_timer[TCPT_REXMT]) 5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * panic("tcp_output REXMT"); 5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Start/restart persistence timer. 5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], 5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project t * tcp_backoff[tp->t_rxtshift], 5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCPTV_PERSMIN, TCPTV_PERSMAX); 5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tp->t_rxtshift < TCP_MAXRXTSHIFT) 5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_rxtshift++; 5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 600