1 /* tcp_output.c 4.17 81/11/24 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/mbuf.h" 6 #include "../h/socket.h" 7 #include "../h/socketvar.h" 8 #include "../net/inet.h" 9 #include "../net/inet_pcb.h" 10 #include "../net/inet_systm.h" 11 #include "../net/imp.h" 12 #include "../net/ip.h" 13 #include "../net/ip_var.h" 14 #include "../net/tcp.h" 15 #include "../net/tcp_var.h" 16 #include "../net/tcp_fsm.h" 17 #include "/usr/include/errno.h" 18 19 /* 20 * Special routines to send control messages. 21 */ 22 tcp_sndctl(tp) 23 struct tcpcb *tp; 24 { 25 COUNT(TCP_SNDCTL); 26 27 if (tcp_send(tp)) 28 return (1); 29 tcp_sndnull(tp); 30 return (0); 31 } 32 33 tcp_sndwin(tp) 34 struct tcpcb *tp; 35 { 36 int ihave, hehas; 37 COUNT(TCP_SNDWIN); 38 39 if (tp->rcv_adv) { 40 register struct socket *so = tp->t_inpcb->inp_socket; 41 42 ihave = so->so_rcv.sb_hiwat - 43 (so->so_rcv.sb_cc + tp->seqcnt); 44 hehas = tp->rcv_adv - tp->rcv_nxt; 45 if ((100*(ihave-hehas)/so->so_rcv.sb_hiwat) < 35) 46 return; 47 } 48 if (tcp_send(tp)) 49 return; 50 tcp_sndnull(tp); 51 } 52 53 tcp_sndnull(tp) 54 register struct tcpcb *tp; 55 { 56 COUNT(TCP_SNDNULL); 57 58 (void) tcp_output(tp, 0, 0, (struct mbuf *)0); 59 tp->tc_flags &= ~TC_ACK_DUE; 60 } 61 62 /* 63 * Tcp segment output routine. 64 */ 65 tcp_send(tp) 66 register struct tcpcb *tp; 67 { 68 register unsigned long last, wind; 69 register struct socket *so = tp->t_inpcb->inp_socket; 70 struct mbuf *m; 71 int flags = 0, forced, sent, len; 72 73 COUNT(TCP_SEND); 74 tp->snd_lst = tp->snd_nxt; 75 forced = 0; 76 m = NULL; 77 if (tp->snd_nxt == tp->iss) { 78 flags |= TH_SYN; 79 tp->snd_lst++; 80 } 81 last = tp->snd_off; 82 for (m = so->so_snd.sb_mb; m != NULL; m = m->m_next) 83 last += m->m_len; 84 if (tp->snd_nxt > last) { 85 if ((tp->tc_flags&TC_SND_FIN) && 86 (tp->seq_fin == tp->iss || tp->snd_nxt <= tp->seq_fin)) { 87 88 flags |= TH_FIN; 89 tp->seq_fin = tp->snd_lst++; 90 } 91 } else { 92 if (tp->tc_flags&TC_SYN_ACKED) { 93 wind = tp->snd_una + tp->snd_wnd; 94 tp->snd_lst = MIN(last, wind); 95 if ((len = tp->snd_lst - tp->snd_nxt) > 1024) 96 tp->snd_lst -= len - 1024; 97 if (tp->snd_lst >= wind) 98 tp->t_persist = T_PERS; 99 } 100 if ((tp->tc_flags&TC_FORCE_ONE) && (tp->snd_lst == wind)) { 101 tp->snd_lst = tp->snd_nxt + 1; 102 forced = 1; 103 } else if (tp->snd_nxt >= tp->snd_lst && (tp->tc_flags&TC_SND_FIN) == 0) 104 return (0); 105 m = m_copy(so->so_snd.sb_mb, 106 (int)(MAX(tp->iss+1,tp->snd_nxt) - tp->snd_off), 107 (int)(tp->snd_lst - tp->snd_off)); 108 if (tp->snd_end > tp->iss && tp->snd_end <= tp->snd_lst) 109 flags |= TH_EOL; 110 if ((tp->tc_flags&TC_SND_FIN) && !forced && 111 tp->snd_lst == last && 112 (tp->seq_fin == tp->iss || tp->snd_nxt <= tp->seq_fin)) { 113 flags |= TH_FIN; 114 tp->seq_fin = tp->snd_lst++; 115 } 116 } 117 if (tp->snd_nxt >= tp->snd_lst) 118 return (0); 119 if (tp->tc_flags & TC_SND_URG) 120 flags |= TH_URG; 121 sent = tcp_output(tp, flags, (int)(tp->snd_lst - tp->snd_nxt), m); 122 if (!forced) { 123 tp->t_rexmt = tp->t_xmtime; 124 tp->t_rexmt_val = tp->snd_lst; 125 if ((tp->tc_flags&TC_REXMT) == 0) { 126 tp->t_rexmttl = T_REXMTTL; 127 tp->t_rtl_val = tp->snd_lst; 128 } 129 } 130 if (sent) 131 tp->snd_nxt = tp->snd_lst; 132 if ((tp->tc_flags&TC_SYN_ACKED) && 133 tp->snd_una > tp->t_xmt_val) { 134 tp->t_xmt = 0; 135 tp->t_xmt_val = tp->snd_lst; 136 } 137 tp->tc_flags &= ~(TC_ACK_DUE|TC_REXMT|TC_FORCE_ONE); 138 tp->snd_hi = MAX(tp->snd_nxt, tp->snd_hi); 139 return (1); 140 } 141 tcp_output(tp, flags, len, dat) 142 register struct tcpcb *tp; 143 register int flags; 144 int len; 145 struct mbuf *dat; 146 { 147 register struct tcpiphdr *t; /* known to be r9 */ 148 register struct mbuf *m; 149 struct socket *so = tp->t_inpcb->inp_socket; 150 register struct ip *ip; 151 COUNT(TCP_OUTPUT); 152 153 if ((t = tp->t_template) == 0) 154 return (0); 155 MGET(m, 0); 156 if (m == 0) 157 return (0); 158 m->m_off = MMAXOFF - sizeof(struct tcpiphdr); 159 m->m_len = sizeof (struct tcpiphdr); 160 m->m_next = dat; 161 if (flags & TH_SYN) 162 len--; 163 if (flags & TH_FIN) 164 len--; 165 if (len < 0) 166 panic("tcp_output"); 167 bcopy((caddr_t)t, mtod(m, caddr_t), sizeof (struct tcpiphdr)); 168 t = mtod(m, struct tcpiphdr *); 169 if (tp->tc_flags&TC_SND_RST) { 170 flags &= ~TH_SYN; 171 flags |= TH_RST; 172 } 173 if (tp->tc_flags&TC_SYN_RCVD) 174 flags |= TH_ACK; 175 t->ti_flags = flags; 176 if (flags & TH_URG) 177 t->ti_urp = htons((u_short)tp->snd_urp); /*XXX */ 178 t->ti_win = 179 so->so_rcv.sb_hiwat - 180 (so->so_rcv.sb_cc + tp->seqcnt); 181 if (tp->rcv_nxt + t->ti_win > tp->rcv_adv) 182 tp->rcv_adv = tp->rcv_nxt + t->ti_win; 183 if (len) 184 t->ti_len = htons((u_short)(len + sizeof (struct tcphdr))); 185 t->ti_win = htons(t->ti_win); 186 t->ti_seq = htonl(tp->snd_nxt); 187 t->ti_ackno = htonl(tp->rcv_nxt); 188 t->ti_sum = 0; /* gratuitous? */ 189 t->ti_sum = inet_cksum(m, sizeof (struct tcpiphdr) + len); 190 ip = (struct ip *)t; 191 ip->ip_v = IPVERSION; 192 ip->ip_hl = 5; 193 ip->ip_tos = 0; 194 ip->ip_len = len + sizeof(struct tcpiphdr); 195 ip->ip_id = ip_id++; 196 ip->ip_off = 0; 197 ip->ip_ttl = MAXTTL; 198 ip_send(ip); 199 return (1); 200 } 201