1 /* tcp_output.c 4.2 81/10/30 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/mbuf.h" 6 #include "../h/socket.h" 7 #include "../inet/inet.h" 8 #include "../inet/inet_host.h" 9 #include "../inet/inet_systm.h" 10 #include "../inet/imp.h" 11 #include "../inet/ip.h" 12 #include "../inet/tcp.h" 13 #include "../inet/tcp_fsm.h" 14 15 /* 16 * Special routines to send control messages. 17 */ 18 tcp_sndctl(tp) 19 struct tcb *tp; 20 { 21 COUNT(TCP_SNDCTL); 22 23 if (tcp_send(tp)) 24 return (1); 25 tcp_sndnull(tp); 26 return(0); 27 } 28 29 tcp_sndwin(tp) 30 struct tcb *tp; 31 { 32 int ihave, hehas; 33 COUNT(TCP_SNDWIN); 34 35 if (tp->rcv_adv) { 36 ihave = tp->t_ucb->uc_rhiwat - 37 (tp->t_ucb->uc_rcc + tp->seqcnt); 38 hehas = tp->rcv_adv - tp->rcv_nxt; 39 if (hehas > 32 && 40 (100*(ihave-hehas)/tp->t_ucb->uc_rhiwat) < 35) 41 return; 42 } 43 if (tcp_send(tp)) 44 return (1); 45 tcp_sndnull(tp); 46 return (0); 47 } 48 49 tcp_sndnull(tp) 50 register struct tcb *tp; 51 { 52 COUNT(TCP_SNDNULL); 53 54 tcp_output(tp, 0, 0, (struct mbuf *)0); 55 tp->tc_flags &= ~TC_ACK_DUE; 56 } 57 58 tcp_sndrst(tp, n) 59 register struct tcb *tp; 60 register struct th *n; 61 { 62 COUNT(TCP_SNDRST); 63 64 /* don't send a reset in response to a reset */ 65 if (n->th_flags&TH_RST) 66 return; 67 tp->tc_flags |= TC_SND_RST; 68 if (n->th_flags&TH_ACK) 69 tp->snd_nxt = n->t_ackno; 70 tp->tc_flags &= ~TC_SYN_RCVD; 71 tcp_sndnull(tp); 72 tp->tc_flags &= ~TC_SND_RST; 73 } 74 75 /* 76 * Tcp segment output routine. 77 */ 78 tcp_send(tp) 79 register struct tcb *tp; 80 { 81 register struct ucb *up; 82 register unsigned long last, wind; 83 struct mbuf *m; 84 int flags = 0, forced, sent; 85 struct mbuf *tcp_sndcopy(); 86 int len; 87 88 COUNT(TCP_SEND); 89 up = tp->t_ucb; 90 tp->snd_lst = tp->snd_nxt; 91 forced = 0; 92 m = NULL; 93 if (tp->snd_nxt == tp->iss) { 94 flags |= TH_SYN; 95 tp->snd_lst++; 96 } 97 last = tp->snd_off; 98 for (m = up->uc_sbuf; m != NULL; m = m->m_next) 99 last += m->m_len; 100 if (tp->snd_nxt > last) { 101 if ((tp->tc_flags&TC_SND_FIN) && 102 (tp->seq_fin == tp->iss || tp->snd_nxt <= tp->seq_fin)) { 103 104 flags |= TH_FIN; 105 tp->seq_fin = tp->snd_lst++; 106 } 107 } else { 108 if (tp->tc_flags&TC_SYN_ACKED) { 109 wind = tp->snd_una + tp->snd_wnd; 110 tp->snd_lst = min(last, wind); 111 if ((len = tp->snd_lst - tp->snd_nxt) > 1024) 112 tp->snd_lst -= len - 1024; 113 if (tp->snd_lst >= wind) 114 tp->t_persist = T_PERS; 115 } 116 if ((tp->tc_flags&TC_FORCE_ONE) && (tp->snd_lst == wind)) { 117 tp->snd_lst = tp->snd_nxt + 1; 118 forced = 1; 119 } 120 m = tcp_sndcopy(tp, max(tp->iss+1,tp->snd_nxt), tp->snd_lst); 121 if (tp->snd_end > tp->iss && tp->snd_end <= tp->snd_lst) 122 flags |= TH_EOL; 123 if ((tp->tc_flags&TC_SND_FIN) && !forced && 124 tp->snd_lst == last && 125 (tp->seq_fin == tp->iss || tp->snd_nxt <= tp->seq_fin)) { 126 flags |= TH_FIN; 127 tp->seq_fin = tp->snd_lst++; 128 } 129 } 130 if (tp->snd_nxt >= tp->snd_lst) 131 return (0); 132 if (tp->tc_flags & TC_SND_URG) 133 flags |= TH_URG; 134 sent = tcp_output(tp, flags, tp->snd_lst - tp->snd_nxt, m); 135 if (!forced) { 136 tp->t_rexmt = tp->t_xmtime; 137 tp->t_rexmt_val = tp->snd_lst; 138 if ((tp->tc_flags&TC_REXMT) == 0) { 139 tp->t_rexmttl = T_REXMTTL; 140 tp->t_rtl_val = tp->snd_lst; 141 } 142 } 143 if (sent) 144 tp->snd_nxt = tp->snd_lst; 145 if ((tp->tc_flags&TC_SYN_ACKED) && 146 tp->snd_una > tp->t_xmt_val) { 147 tp->t_xmt = 0; 148 tp->t_xmt_val = tp->snd_lst; 149 } 150 tp->tc_flags &= ~(TC_ACK_DUE|TC_REXMT|TC_FORCE_ONE); 151 tp->snd_hi = max(tp->snd_nxt, tp->snd_hi); 152 return (1); 153 } 154 155 /* 156 * Create template to be used to send tcp packets on a connection. 157 * Call after host entry created, allocates an mbuf and fills 158 * in a skeletal tcp/ip header, minimizing the amount of work 159 * necessary when the connection is used. 160 */ 161 struct th * 162 tcp_template(tp) 163 struct tcb *tp; 164 { 165 register struct host *h = tp->t_ucb->uc_host; 166 register struct mbuf *m; 167 register struct th *n; 168 register struct ip *ip; 169 170 if (h == 0) 171 return (0); 172 m = m_get(1); 173 if (m == 0) 174 return (0); 175 m->m_off = MMAXOFF - sizeof (struct th); 176 m->m_len = sizeof (struct th); 177 n = mtod(m, struct th *); 178 n->t_next = n->t_prev = 0; 179 n->t_x1 = 0; 180 n->t_pr = TCPROTO; 181 n->t_len = htons(sizeof (struct th) - sizeof (struct ip)); 182 n->t_s.s_addr = n_lhost.s_addr; 183 n->t_d.s_addr = h->h_addr.s_addr; 184 n->t_src = htons(tp->t_lport); 185 n->t_dst = htons(tp->t_fport); 186 n->t_seq = 0; 187 n->t_ackno = 0; 188 n->t_x2 = 0; 189 n->t_off = 5; 190 n->th_flags = 0; 191 n->t_win = 0; 192 n->t_sum = 0; 193 n->t_urp = 0; 194 return (n); 195 } 196 197 tcp_output(tp, flags, len, dat) 198 register struct tcb *tp; 199 register int flags; 200 int len; 201 struct mbuf *dat; 202 { 203 register struct mbuf *m; 204 register struct th *t; 205 register struct ip *ip; 206 int i; 207 #ifdef TCPDEBUG 208 struct tcp_debug tdb; 209 #endif 210 COUNT(SEND_TCP); 211 212 if ((t = tp->t_ucb->uc_template) == 0) 213 return (0); 214 MGET(m, 0); 215 if (m == 0) 216 return (0); 217 m->m_off = MMAXOFF - sizeof(struct th); 218 m->m_len = sizeof (struct th); 219 m->m_next = dat; 220 if (flags & TH_SYN) 221 len--; 222 if (flags & TH_FIN) 223 len--; 224 bcopy((caddr_t)t, mtod(m, caddr_t), sizeof (struct th)); 225 t = mtod(m, struct th *); 226 if (tp->tc_flags&TC_SND_RST) { 227 flags &= ~TH_SYN; 228 flags |= TH_RST; 229 } 230 if (tp->tc_flags&TC_SYN_RCVD) 231 flags |= TH_ACK; 232 t->th_flags = flags; 233 if (flags & TH_URG) 234 t->t_urp = htons(tp->snd_urp); 235 t->t_win = 236 tp->t_ucb->uc_rhiwat - (tp->t_ucb->uc_rcc + tp->seqcnt); 237 if (tp->rcv_nxt + t->t_win > tp->rcv_adv) 238 tp->rcv_adv = tp->rcv_nxt + t->t_win; 239 if (len) 240 t->t_len = htons(len + TCPSIZE); 241 t->t_win = htons(t->t_win); 242 #ifdef TCPDEBUG 243 if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 244 t->t_seq = tp->snd_nxt; 245 t->t_ackno = tp->rcv_nxt; 246 tdb_setup(tp, t, INSEND, &tdb); 247 tdb_stuff(&tdb, -2); 248 } 249 #endif 250 t->t_seq = htonl(tp->snd_nxt); 251 t->t_ackno = htonl(tp->rcv_nxt); 252 t->t_sum = cksum(m, len + sizeof(struct th)); 253 ip = (struct ip *)t; 254 ip->ip_v = IPVERSION; 255 ip->ip_hl = 5; 256 ip->ip_tos = 0; 257 ip->ip_len = len + sizeof(struct th); 258 ip->ip_id = ip_id++; 259 ip->ip_off = 0; 260 ip->ip_ttl = MAXTTL; 261 i = ip_send(ip); 262 return(i); 263 } 264 265 firstempty(tp) 266 register struct tcb *tp; 267 { 268 register struct th *p, *q; 269 COUNT(FIRSTEMPTY); 270 271 if ((p = tp->t_rcv_next) == (struct th *)tp || tp->rcv_nxt < p->t_seq) 272 return (tp->rcv_nxt); 273 while ((q = p->t_next) != (struct th *)tp && 274 (t_end(p) + 1) == q->t_seq) 275 p = q; 276 return (t_end(p) + 1); 277 } 278 279 struct mbuf * 280 tcp_sndcopy(tp, start, end) 281 struct tcb *tp; 282 u_long start, end; 283 { 284 register struct mbuf *m, *n, **np; 285 u_long off; 286 register int len; 287 int adj; 288 struct mbuf *top, *p; 289 COUNT(SND_COPY); 290 291 if (start >= end) 292 return(NULL); 293 off = tp->snd_off; 294 m = tp->t_ucb->uc_sbuf; 295 while (m != NULL && start >= (off + m->m_len)) { 296 off += m->m_len; 297 m = m->m_next; 298 } 299 np = ⊤ 300 top = 0; 301 adj = start - off; 302 len = end - start; 303 while (m && len > 0) { 304 MGET(n, 1); 305 *np = n; 306 if (n == 0) 307 goto nospace; 308 n->m_len = MIN(len, m->m_len - adj); 309 if (m->m_off > MMAXOFF) { 310 p = mtod(m, struct mbuf *); 311 n->m_off = ((int)p - (int)n) + adj; 312 mprefcnt[mtopf(p)]++; 313 } else { 314 n->m_off = MMINOFF; 315 bcopy(mtod(m, caddr_t)+adj, mtod(n, caddr_t), 316 n->m_len); 317 } 318 len -= n->m_len; 319 adj = 0; 320 m = m->m_next; 321 /* SHOULD TRY PACKING INTO SMALL MBUFS HERE */ 322 np = &n->m_next; 323 } 324 /* SHOULD NEVER RUN OUT OF m WHEN LEN */ 325 if (len) 326 printf("snd_copy: m %x len %d\n", m, len); 327 return (top); 328 nospace: 329 printf("snd_copy: no space\n"); 330 m_freem(top); 331 return (0); 332 } 333 334 tcp_enq(p, prev) 335 register struct th *p; 336 register struct th *prev; 337 { 338 339 p->t_prev = prev; 340 p->t_next = prev->t_next; 341 prev->t_next->t_prev = p; 342 prev->t_next = p; 343 } 344 345 tcp_deq(p) 346 register struct th *p; 347 { 348 349 p->t_prev->t_next = p->t_next; 350 p->t_next->t_prev = p->t_prev; 351 } 352