1 /* tcp_input.c 1.11 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_systm.h" 9 #include "../inet/imp.h" 10 #include "../inet/inet_host.h" 11 #include "../inet/ip.h" 12 #include "../inet/tcp.h" 13 #include "../inet/tcp_fsm.h" 14 15 extern int nosum; 16 17 tcp_input(mp) 18 register struct mbuf *mp; 19 { 20 register struct th *n; /* known to be r10 */ 21 register int j; /* known to be r9 */ 22 register struct tcb *tp; 23 int nstate; 24 struct mbuf *m; 25 struct ucb *up; 26 int hlen, tlen; 27 u_short lport, fport; 28 #ifdef TCPDEBUG 29 struct tcp_debug tdb; 30 #endif 31 COUNT(TCP_INPUT); 32 33 /* 34 * Build extended tcp header 35 */ 36 n = (struct th *)((int)mp + mp->m_off); 37 tlen = ((struct ip *)n)->ip_len; 38 n->t_len = htons(tlen); 39 n->t_next = NULL; 40 n->t_prev = NULL; 41 n->t_x1 = 0; 42 lport = ntohs(n->t_dst); 43 fport = ntohs(n->t_src); 44 45 /* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */ 46 if ((hlen = n->t_off << 2) > mp->m_len) 47 { printf("tcp header overflow\n"); m_freem(mp); return; } 48 49 /* 50 * Checksum extended header and data 51 */ 52 j = n->t_sum; n->t_sum = 0; 53 #ifdef vax 54 if (tlen == 20) { 55 asm("addl3 $8,r10,r0; movl (r0)+,r1; addl2 (r0)+,r1"); 56 asm("adwc (r0)+,r1; adwc (r0)+,r1; adwc (r0)+,r1"); 57 asm("adwc (r0)+,r1; adwc (r0)+,r1; adwc (r0)+,r1"); 58 asm("adwc $0,r1; ashl $-16,r1,r0; addw2 r0,r1"); 59 asm("adwc $0,r1"); /* ### */ 60 asm("mcoml r1,r1; movzwl r1,r1; subl2 r1,r9"); 61 } else 62 #endif 63 j -= cksum(mp, sizeof (struct ip) + tlen); 64 if (j != 0) { 65 netstat.t_badsum++; 66 if (nosum == 0) { 67 m_freem(mp); 68 return; 69 } 70 } 71 72 /* 73 * Find tcb for message (SHOULDN'T USE LINEAR SEARCH!) 74 */ 75 for (tp = tcb_head; tp != 0; tp = tp->t_tcb_next) 76 if (tp->t_lport == lport && tp->t_fport == fport && 77 tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr) 78 goto found; 79 for (tp = tcb_head; tp != 0; tp = tp->t_tcb_next) 80 if (tp->t_lport == lport && 81 (tp->t_fport==fport || tp->t_fport==0) && 82 (tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr || 83 tp->t_ucb->uc_host->h_addr.s_addr == 0)) 84 goto found; 85 goto notwanted; 86 found: 87 88 /* 89 * Byte swap header 90 */ 91 n->t_len = tlen - hlen; 92 n->t_src = fport; 93 n->t_dst = lport; 94 n->t_seq = ntohl(n->t_seq); 95 n->t_ackno = ntohl(n->t_ackno); 96 n->t_win = ntohs(n->t_win); 97 n->t_urp = ntohs(n->t_urp); 98 99 /* 100 * Check segment seq # and do rst processing 101 */ 102 switch (tp->t_state) { 103 104 case LISTEN: 105 if ((n->th_flags&TH_ACK) || !syn_ok(tp, n)) { 106 tcp_sndrst(tp, n); 107 goto badseg; 108 } 109 if (n->th_flags&TH_RST) 110 goto badseg; 111 goto goodseg; 112 113 case SYN_SENT: 114 if (!ack_ok(tp, n) || !syn_ok(tp, n)) { 115 tcp_sndrst(tp, n); /* 71,72,75 */ 116 goto badseg; 117 } 118 if (n->th_flags&TH_RST) { 119 tcp_close(tp, URESET); /* 70 */ 120 tp->t_state = CLOSED; 121 goto badseg; 122 } 123 goto goodseg; 124 125 default: 126 if ((n->th_flags&TH_RST) == 0) 127 goto common; 128 if (n->t_seq < tp->rcv_nxt) /* bad rst */ 129 goto badseg; /* 69 */ 130 switch (tp->t_state) { 131 132 case L_SYN_RCVD: 133 if (ack_ok(tp, n) == 0) 134 goto badseg; /* 69 */ 135 tp->t_rexmt = 0; 136 tp->t_rexmttl = 0; 137 tp->t_persist = 0; 138 h_free(tp->t_ucb->uc_host); 139 tp->t_state = LISTEN; 140 goto badseg; 141 142 default: 143 tcp_close(tp, URESET); /* 66 */ 144 tp->t_state = CLOSED; 145 goto badseg; 146 } 147 /*NOTREACHED*/ 148 149 case SYN_RCVD: 150 common: 151 if (ack_ok(tp, n) == 0) { 152 tcp_sndrst(tp, n); /* 74 */ 153 goto badseg; 154 } 155 if (syn_ok(tp, n) && n->t_seq != tp->irs) { 156 tcp_sndnull(tp); /* 74 */ 157 goto badseg; 158 } 159 goto goodseg; 160 } 161 badseg: 162 m_freem(mp); 163 return; 164 165 goodseg: 166 #ifdef notdef 167 /* 168 * Defer processing if no buffer space for this connection. 169 */ 170 up = tp->t_ucb; 171 if (up->uc_rcc > up->uc_rhiwat && 172 && n->t_len != 0 && mbstat.m_bufs < mbstat.m_lowat) { 173 mp->m_act = (struct mbuf *)0; 174 if ((m = tp->t_rcv_unack) != NULL) { 175 while (m->m_act != NULL) 176 m = m->m_act; 177 m->m_act = mp; 178 } else 179 tp->t_rcv_unack = mp; 180 return; 181 } 182 #endif 183 184 /* 185 * Discard ip header, and do tcp input processing. 186 */ 187 hlen += sizeof(struct ip); 188 mp->m_off += hlen; 189 mp->m_len -= hlen; 190 nstate = tp->t_state; 191 tp->tc_flags &= ~TC_NET_KEEP; 192 acounts[tp->t_state][INRECV]++; 193 #ifdef TCPDEBUG 194 if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 195 tdb_setup(tp, n, INRECV, &tdb); 196 } else 197 tdb.td_tod = 0; 198 #endif 199 switch (tp->t_state) { 200 201 case LISTEN: 202 if (!syn_ok(tp, n) || 203 ((tp->t_ucb->uc_host = h_make(&n->t_s)) == 0)) { 204 nstate = EFAILEC; 205 goto done; 206 } 207 tp->t_fport = n->t_src; 208 tp->t_ucb->uc_template = tcp_template(tp); 209 tcp_ctldat(tp, n, 1); 210 if (tp->tc_flags&TC_FIN_RCVD) { 211 tp->t_finack = T_2ML; /* 3 */ 212 tp->tc_flags &= ~TC_WAITED_2_ML; 213 nstate = CLOSE_WAIT; 214 } else { 215 tp->t_init = T_INIT / 2; /* 4 */ 216 nstate = L_SYN_RCVD; 217 } 218 goto done; 219 220 case SYN_SENT: 221 if (!syn_ok(tp, n)) { 222 nstate = EFAILEC; 223 goto done; 224 } 225 tcp_ctldat(tp, n, 1); 226 if (tp->tc_flags&TC_FIN_RCVD) { 227 if (n->th_flags&TH_ACK) { 228 if (n->t_ackno > tp->iss) 229 present_data(tp); /* 32 */ 230 } else { 231 tp->t_finack = T_2ML; /* 9 */ 232 tp->tc_flags &= ~TC_WAITED_2_ML; 233 } 234 nstate = CLOSE_WAIT; 235 goto done; 236 } 237 if (n->th_flags&TH_ACK) { 238 present_data(tp); /* 11 */ 239 nstate = ESTAB; 240 } else 241 nstate = SYN_RCVD; /* 8 */ 242 goto done; 243 244 case SYN_RCVD: 245 case L_SYN_RCVD: 246 if ((n->th_flags&TH_ACK) == 0 || 247 (n->th_flags&TH_ACK) && n->t_ackno <= tp->iss) { 248 nstate = EFAILEC; 249 goto done; 250 } 251 goto input; 252 253 case ESTAB: 254 case FIN_W1: 255 case FIN_W2: 256 case TIME_WAIT: 257 input: 258 tcp_ctldat(tp, n, 1); /* 39 */ 259 present_data(tp); 260 switch (tp->t_state) { 261 262 case ESTAB: 263 if (tp->tc_flags&TC_FIN_RCVD) 264 nstate = CLOSE_WAIT; 265 break; 266 267 case SYN_RCVD: 268 case L_SYN_RCVD: 269 nstate = (tp->tc_flags&TC_FIN_RCVD) ? 270 CLOSE_WAIT : ESTAB; /* 33:5 */ 271 break; 272 273 case FIN_W1: 274 j = ack_fin(tp, n); 275 if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 276 if (j) 277 nstate = FIN_W2; /* 27 */ 278 break; 279 } 280 tp->t_finack = T_2ML; 281 tp->tc_flags &= ~TC_WAITED_2_ML; 282 nstate = j ? TIME_WAIT : CLOSING1; /* 28:26 */ 283 break; 284 285 case FIN_W2: 286 if (tp->tc_flags&TC_FIN_RCVD) { 287 tp->t_finack = T_2ML; /* 29 */ 288 tp->tc_flags &= ~TC_WAITED_2_ML; 289 nstate = TIME_WAIT; 290 break; 291 } 292 break; 293 } 294 goto done; 295 296 case CLOSE_WAIT: 297 if (n->th_flags&TH_FIN) { 298 if ((n->th_flags&TH_ACK) && 299 n->t_ackno <= tp->seq_fin) { 300 tcp_ctldat(tp, n, 0); /* 30 */ 301 tp->t_finack = T_2ML; 302 tp->tc_flags &= ~TC_WAITED_2_ML; 303 } else 304 tcp_sndctl(tp); /* 31 */ 305 goto done; 306 } 307 goto input; 308 309 case CLOSING1: 310 j = ack_fin(tp, n); 311 if (n->th_flags&TH_FIN) { 312 tcp_ctldat(tp, n, 0); 313 tp->t_finack = T_2ML; 314 tp->tc_flags &= ~TC_WAITED_2_ML; 315 if (j) 316 nstate = TIME_WAIT; /* 23 */ 317 goto done; 318 } 319 if (j) { 320 if (tp->tc_flags&TC_WAITED_2_ML) 321 if (rcv_empty(tp)) { 322 tcp_close(tp, UCLOSED); /* 15 */ 323 nstate = CLOSED; 324 } else 325 nstate = RCV_WAIT; /* 18 */ 326 else 327 nstate = TIME_WAIT; 328 goto done; 329 } 330 goto input; 331 332 case CLOSING2: 333 if (ack_fin(tp, n)) { 334 if (rcv_empty(tp)) { /* 16 */ 335 tcp_close(tp, UCLOSED); 336 nstate = CLOSED; 337 } else 338 nstate = RCV_WAIT; /* 19 */ 339 goto done; 340 } 341 if (n->th_flags&TH_FIN) { 342 tcp_sndctl(tp); /* 31 */ 343 goto done; 344 } 345 goto input; 346 347 case RCV_WAIT: 348 if ((n->th_flags&TH_FIN) && (n->th_flags&TH_ACK) && 349 n->t_ackno <= tp->seq_fin) { 350 tcp_ctldat(tp, n, 0); 351 tp->t_finack = T_2ML; 352 tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 353 } 354 goto done; 355 } 356 panic("tcp_input"); 357 done: 358 359 /* 360 * Done with state*input specific processing. 361 * Form trace records, free input if not needed, 362 * and enter new state. 363 */ 364 #ifdef TCPDEBUG 365 if (tdb.td_tod) 366 tdb_stuff(&tdb, nstate); 367 #endif 368 switch (nstate) { 369 370 case EFAILEC: 371 m_freem(mp); 372 return; 373 374 default: 375 tp->t_state = nstate; 376 /* fall into ... */ 377 378 case CLOSED: 379 /* IF CLOSED CANT LOOK AT tc_flags */ 380 if ((tp->tc_flags&TC_NET_KEEP) == 0) 381 m_freem(mp); 382 return; 383 } 384 /* NOTREACHED */ 385 386 /* 387 * Unwanted packed; free everything 388 * but the header and return an rst. 389 */ 390 notwanted: 391 m_freem(mp->m_next); 392 mp->m_next = NULL; 393 mp->m_len = sizeof(struct th); 394 #define xchg(a,b) j=a; a=b; b=j 395 xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src); 396 #undef xchg 397 if (n->th_flags&TH_ACK) 398 n->t_seq = n->t_ackno; 399 else { 400 n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen); 401 n->t_seq = 0; 402 } 403 n->th_flags = TH_RST; /* not TH_FIN, TH_SYN */ 404 n->th_flags ^= TH_ACK; 405 n->t_len = htons(TCPSIZE); 406 n->t_off = 5; 407 n->t_sum = cksum(mp, sizeof(struct th)); 408 ((struct ip *)n)->ip_len = sizeof(struct th); 409 ip_output(mp); 410 netstat.t_badsegs++; 411 } 412 413 tcp_ctldat(tp, n, dataok) 414 register struct tcb *tp; 415 register struct th *n; 416 { 417 register sent; 418 register struct ucb *up; 419 register struct mbuf *m, *mn; 420 register len; 421 COUNT(RCV_CTLDAT); 422 423 tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW); 424 /* syn */ 425 if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (n->th_flags&TH_SYN)) { 426 tp->irs = n->t_seq; 427 tp->rcv_nxt = n->t_seq + 1; 428 tp->snd_wl = tp->rcv_urp = tp->irs; 429 tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 430 } 431 /* ack */ 432 if ((n->th_flags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 433 n->t_ackno > tp->snd_una) { 434 up = tp->t_ucb; 435 436 /* update snd_una and snd_nxt */ 437 tp->snd_una = n->t_ackno; 438 if (tp->snd_una > tp->snd_nxt) 439 tp->snd_nxt = tp->snd_una; 440 441 /* if timed msg acked, set retrans time value */ 442 if ((tp->tc_flags&TC_SYN_ACKED) && 443 tp->snd_una > tp->t_xmt_val) { 444 tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 445 if (tp->t_xmtime > T_REMAX) 446 tp->t_xmtime = T_REMAX; 447 } 448 449 /* remove acked data from send buf */ 450 len = tp->snd_una - tp->snd_off; 451 m = up->uc_sbuf; 452 while (len > 0 && m != NULL) 453 if (m->m_len <= len) { 454 len -= m->m_len; 455 if (m->m_off > MMAXOFF) 456 up->uc_ssize -= NMBPG; 457 MFREE(m, mn); 458 m = mn; 459 up->uc_ssize--; 460 } else { 461 m->m_len -= len; 462 m->m_off += len; 463 break; 464 } 465 up->uc_sbuf = m; 466 tp->snd_off = tp->snd_una; 467 if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 468 (tp->snd_una > tp->iss)) { 469 tp->tc_flags |= TC_SYN_ACKED; 470 tp->t_init = 0; 471 } 472 if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 473 tp->tc_flags &= ~TC_SND_FIN; 474 tp->t_rexmt = 0; 475 tp->t_rexmttl = 0; 476 tp->tc_flags |= TC_CANCELLED; 477 netwakeup(tp->t_ucb); /* wasteful */ 478 } 479 /* win */ 480 if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) { 481 tp->snd_wl = n->t_seq; 482 tp->snd_wnd = n->t_win; 483 tp->tc_flags |= TC_NEW_WINDOW; 484 tp->t_persist = 0; 485 } 486 if (dataok) { 487 /* text */ 488 if (n->t_len != 0) 489 tcp_text(tp, n); 490 /* urg */ 491 if (n->th_flags&TH_URG) { 492 unsigned urgent; 493 494 urgent = n->t_urp + n->t_seq; 495 if (tp->rcv_nxt < urgent) { 496 if (tp->rcv_urp <= tp->rcv_nxt) 497 to_user(tp->t_ucb, UURGENT); 498 tp->rcv_urp = urgent; 499 } 500 } 501 /* eol */ 502 if ((n->th_flags&TH_EOL) && 503 (tp->tc_flags&TC_DROPPED_TXT) == 0 && 504 tp->t_rcv_prev != (struct th *)tp) { 505 /* mark last mbuf */ 506 m = dtom(tp->t_rcv_prev); 507 if (m != NULL) { 508 while (m->m_next != NULL) 509 m = m->m_next; 510 m->m_act = 511 (struct mbuf *)(m->m_off + m->m_len - 1); 512 } 513 } 514 } 515 /* fin */ 516 if ((n->th_flags&TH_FIN) && (tp->tc_flags&TC_DROPPED_TXT) == 0) { 517 int last; 518 519 if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 520 /* do we really have fin ? */ 521 last = firstempty(tp); 522 if (tp->t_rcv_prev == (struct th *)tp || 523 last == t_end(tp->t_rcv_prev)) { 524 tp->tc_flags |= TC_FIN_RCVD; 525 netwakeup(tp->t_ucb); /* poke */ 526 } 527 if ((tp->tc_flags&TC_FIN_RCVD) && 528 tp->rcv_nxt >= last) { 529 tp->rcv_nxt = last + 1; /* fin seq */ 530 tp->tc_flags |= TC_ACK_DUE; 531 } 532 } else 533 tp->tc_flags |= TC_ACK_DUE; 534 } 535 536 /* respond */ 537 sent = 0; 538 if (tp->tc_flags&TC_ACK_DUE) 539 sent = tcp_sndctl(tp); 540 else if (tp->tc_flags&TC_NEW_WINDOW) { 541 seq_t last = tp->snd_off; 542 up = tp->t_ucb; 543 for (m = up->uc_sbuf; m != NULL; m = m->m_next) 544 last += m->m_len; 545 if (tp->snd_nxt <= last || (tp->tc_flags&TC_SND_FIN)) 546 sent = tcp_send(tp); 547 } 548 549 /* set for retrans */ 550 if (!sent && tp->snd_una < tp->snd_nxt && 551 (tp->tc_flags&TC_CANCELLED)) { 552 tp->t_rexmt = tp->t_xmtime; 553 tp->t_rexmttl = T_REXMTTL; 554 tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 555 tp->tc_flags &= ~TC_CANCELLED; 556 } 557 } 558 559 tcp_text(tp, n) 560 register struct tcb *tp; 561 register struct th *n; 562 { 563 register int i; 564 register struct th *p, *q; 565 register struct mbuf *m; 566 int overage; 567 COUNT(RCV_TEXT); 568 569 /* 570 * Discard duplicate data already passed to user. 571 */ 572 if (SEQ_LT(n->t_seq, tp->rcv_nxt)) { 573 i = tp->rcv_nxt - n->t_seq; 574 if (i >= n->t_len) 575 goto dropseg; 576 n->t_seq += i; 577 n->t_len -= i; 578 m_adj(dtom(n), i); 579 } 580 581 /* 582 * Find a segment which begins after this one does. 583 */ 584 for (q = tp->t_rcv_next; q != (struct th *)tp; q = q->t_next) 585 if (SEQ_GT(q->t_seq, n->t_seq)) 586 break; 587 588 /* 589 * If there is a preceding segment, it may provide some of 590 * our data already. If so, drop the data from the incoming 591 * segment. If it provides all of our data, drop us. 592 */ 593 if (q->t_prev != (struct th *)tp) { 594 /* conversion to int (in i) handles seq wraparound */ 595 i = q->t_prev->t_seq + q->t_prev->t_len - n->t_seq; 596 if (i > 0) { 597 if (i >= n->t_len) 598 goto dropseg; 599 m_adj(dtom(tp), i); 600 n->t_len -= i; 601 n->t_seq += i; 602 } 603 } 604 605 /* 606 * While we overlap succeeding segments trim them or, 607 * if they are completely covered, dequeue them. 608 */ 609 while (q != (struct th *)tp && SEQ_GT(n->t_seq + n->t_len, q->t_seq)) { 610 i = (n->t_seq + n->t_len) - q->t_seq; 611 if (i < q->t_len) { 612 q->t_len -= i; 613 m_adj(dtom(q), i); 614 break; 615 } 616 q = q->t_next; 617 m_freem(dtom(q->t_prev)); 618 remque(q->t_prev); 619 } 620 621 /* 622 * Stick new segment in its place. 623 */ 624 insque(n, q->t_prev); 625 tp->seqcnt += n->t_len; 626 627 #ifdef notdef 628 /* 629 * Calculate available space and discard segments for 630 * which there is too much. 631 */ 632 q = tp->t_rcv_prev; 633 overage = 634 (tp->t_socket->uc_rcc + tp->rcv_seqcnt) - tp->t_socket->uc_rhiwat; 635 if (overage > 0) 636 for (;;) { 637 i = MIN(q->t_len, overage); 638 overage -= i; 639 q->t_len -= i; 640 m_adj(q, -i); 641 if (q == n) 642 tp->tc_flags |= TC_DROPPED_TXT; 643 if (q->t_len) 644 break; 645 if (q == n) 646 panic("tcp_text dropall"); 647 q = q->t_prev; 648 remque(q->t_next); 649 } 650 #endif 651 652 /* 653 * Advance rcv_next through 654 * newly completed sequence space 655 * and return forcing an ack. 656 */ 657 while (n->t_seq == tp->rcv_nxt) { 658 /* present data belongs here */ 659 tp->rcv_nxt += n->t_len; 660 n = n->t_next; 661 if (n == (struct th *)tp) 662 break; 663 } 664 tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP); 665 return; 666 667 dropseg: 668 /* don't set TC_NET_KEEP, so that mbuf's will get dropped */ 669 return; 670 } 671 672 #define socket ucb /* ### */ 673 #define t_socket t_ucb /* ### */ 674 675 present_data(tp) 676 register struct tcb *tp; 677 { 678 register struct th *t; 679 register struct socket *up; 680 register struct mbuf *m, **mp; 681 seq_t ready; 682 COUNT(PRESENT_DATA); 683 684 /* connection must be synced and data available for user */ 685 if ((tp->tc_flags&TC_SYN_ACKED) == 0) 686 return; 687 up = tp->t_socket; 688 mp = &up->uc_rbuf; 689 while (*mp) 690 mp = &(*mp)->m_next; 691 t = tp->t_rcv_next; 692 /* SHOULD PACK DATA IN HERE */ 693 while (t != (struct th *)tp && t->t_seq < tp->rcv_nxt) { 694 remque(t); 695 m = dtom(t); 696 up->uc_rcc += t->t_len; 697 tp->seqcnt -= t->t_len; 698 if (tp->seqcnt < 0) panic("present_data"); 699 t = t->t_next; 700 while (m) { 701 if (m->m_len == 0) { 702 m = m_free(m); 703 continue; 704 } 705 *mp = m; 706 mp = &m->m_next; 707 m = *mp; 708 } 709 } 710 if (up->uc_rcc != 0) 711 netwakeup(up); 712 if ((tp->tc_flags&TC_FIN_RCVD) && /* ### */ 713 (tp->tc_flags&TC_USR_CLOSED) == 0 && /* ### */ 714 rcv_empty(tp)) /* ### */ 715 to_user(up, UCLOSED); /* ### */ 716 } 717