1 /* 2 $Log: rdp_states.c,v $ 3 * Revision 2.14 85/06/18 14:38:50 walsh 4 * eliminated inpcb flags. 5 * 6 * Revision 2.13 85/05/31 14:39:06 walsh 7 * copy sequential delivery desires when fork off a new socket. 8 * 9 * Revision 2.12 84/12/03 09:42:20 walsh 10 * Keep no route messages from flooding console. 11 * 12 * Revision 2.11 84/11/29 13:06:17 walsh 13 * Have the NULL message retransmission back off so that don't load 14 * a jammed network and so that don't wake user up so often when 15 * some intermediary hop has gone down on a (normally) fast connection. 16 * 17 * Revision 2.10 84/11/15 09:56:14 walsh 18 * redid how we deal with compiler padding in the RDP header structure. 19 * 20 * Revision 2.9 84/11/08 16:12:06 walsh 21 * Added code to gather statistics on RDP traffic. This makes the RDPCB 22 * too big unles you make mbufs 512 bytes large. RDP_CS should be turned off 23 * unless you do. 24 * 25 * Revision 2.8 84/11/06 15:24:54 walsh 26 * *** empty log message *** 27 * 28 * Revision 2.7 84/11/05 15:54:34 walsh 29 * update_nulltimer() macro began to look inappropriate with recent 30 * changes, so its been stripped out and put in-line. 31 * 32 * Revision 2.6 84/11/05 12:42:34 walsh 33 * Set things up so can debug RDP connections just like can debug TCP 34 * connections. 35 * 36 * Revision 2.5 84/11/05 11:34:36 walsh 37 * Don't let round trip time estimate drift upward on lossy networks. 38 * Check for retransmissions of packets used to measure round trip time. 39 * 40 * Revision 2.4 84/11/05 10:47:38 walsh 41 * More changes to go with NULL messages getting their own sequence 42 * number. 43 * 44 * Revision 2.3 84/11/02 18:24:20 walsh 45 * Protocol specifiers want NULL message to have own sequence number in 46 * case of slow (t>NULL msg timeout) packets. I don't see this as a problem, 47 * and even if happened (dubious) would only delay discovery, but I 48 * didn't win this one. Initially not designed for this, but fixes are 49 * in almost neatly. 50 * 51 * Revision 2.2 84/11/02 15:29:32 walsh 52 * Allow for RDP header fields not on natural boundries. (Protocol 53 * specifiers say will be part of next version in 6-12 months). 54 * Until then, there goes the speed... Yucho modifications. 55 * 56 * Revision 2.1 84/11/02 10:14:11 walsh 57 * Fixed to include RCS comments in checked out source. 58 * 59 * 60 * description: 61 * The state transition functions for the Reliable Datagram Protocol. 62 * 63 * revision 1.17 64 * date: 84/07/24 16:58:17; author: walsh; state: Exp; lines added/del: 2/2 65 * When had gone to making retransmit took too long advisory, 66 * had forgotten to change RDP_sCLOSED to RDP_sSAME. 67 * 68 * revision 1.16 69 * date: 84/07/23 12:58:31; author: walsh; state: Exp; lines added/del: 27/6 70 * Clear all timers when enter close state. Updates to protocol had not 71 * been complete in this respect. 72 * 73 * Retransmission and acceptance in CLOSEWAIT do not seem to be in the cards 74 * in dealing with protocol specifiers, so removed ### markers and commented. 75 * 76 * revision 1.15 77 * date: 84/07/22 19:45:31; author: walsh; state: Exp; lines added/del: 19/0 78 * Added a state transition function rdp_closew_rcv() to compensate for 79 * socket code's dropping of system priority level for a brief period of time. 80 * 81 * revision 1.14 82 * date: 84/07/19 10:21:42; author: walsh; state: Exp; lines added/del: 14/85 83 * Organized macros and classified their definitions in rdp_macros.h. 84 * 85 * revision 1.13 86 * date: 84/07/19 08:54:01; author: walsh; state: Exp; lines added/del: 4/0 87 * NULL message processing should start before receive a packet in ESTAB, 88 * so start up NULL timer when enter ESTAB. 89 * 90 * revision 1.12 91 * date: 84/07/18 18:50:55; author: walsh; state: Exp; lines added/del: 36/5 92 * Added provision for sending of NULL messages. These are sent on an idle 93 * connection to determine that the other side still exists. 94 * 95 * revision 1.11 96 * date: 84/07/18 13:35:36; author: walsh; state: Exp; lines added/del: 6/6 97 * made provisions for user-adjustable RTTL time period. 98 * 99 * revision 1.10 100 * date: 84/07/13 09:50:33; author: walsh; state: Exp; lines added/del: 22/19 101 * When first send datagram, we determine its length. 102 * Might as wellsave that length in m_act for retransmission. 103 * 104 * revision 1.9 105 * date: 84/07/12 13:48:22; author: walsh; state: Exp; lines added/del: 1/0 106 * Rather than in-line stuffing of IP/RDP headers, at least half of which are 107 * constant, copy headers in from a template of what the headers are like. The 108 * bcopy() call is turned into a movc3 instruction on the VAX by a sed script 109 * run over the assembler output of the C compiler. Marginal speed-up. 110 * 111 * revision 1.8 112 * date: 84/07/12 09:55:02; author: walsh; state: Exp; lines added/del: 5/13 113 * some small optimizations. 114 * 115 * revision 1.7 116 * date: 84/07/10 14:48:13; author: walsh; state: Exp; lines added/del: 1/1 117 * Reduced amount of unnecessary wakeup action. 118 * 119 * revision 1.6 120 * date: 84/07/10 10:28:33; author: walsh; state: Exp; lines added/del: 35/35 121 * Added register declarations. 122 * 123 * revision 1.5 124 * date: 84/07/09 14:31:33; author: walsh; state: Exp; lines added/del: 11/2 125 * Added an ACK-delay algorithm to reduce cpu and network loading. 126 * 127 * revision 1.4 128 * date: 84/07/08 21:36:47; author: walsh; state: Exp; lines added/del: 3/3 129 * changed some references to r_sendq.rq_baseseq to r_snduna for clarity. 130 * 131 * revision 1.3 132 * date: 84/07/06 15:13:50; author: wjacobso; state: Exp; lines added/del: 17/17 133 * add register var definitions; use sndnxt-baseseq instead of maxqlen 134 * to determine number of passes 135 * 136 * revision 1.2 137 * date: 84/07/06 09:49:52; author: root; state: Exp; lines added/del: 93/35 138 * This version seems to run bug-free. 139 * 140 * revision 1.1 141 * date: 84/06/26 14:18:09; author: walsh; state: Exp; 142 * Initial revision 143 */ 144 145 146 #ifdef RDP 147 #include "../h/param.h" 148 #include "../h/dir.h" 149 #include "../h/user.h" 150 #include "../h/kernel.h" 151 #include "../h/inode.h" 152 #include "../h/mbuf.h" 153 #include "../h/socket.h" 154 #include "../h/socketvar.h" 155 #include "../h/errno.h" 156 #include "../h/syslog.h" 157 158 #include "../net/if.h" 159 #include "../net/route.h" 160 161 #include "../bbnnet/in.h" 162 #include "../bbnnet/net.h" 163 #include "../bbnnet/in_pcb.h" 164 #include "../bbnnet/in_var.h" 165 #include "../bbnnet/ip.h" 166 #include "../bbnnet/rdp.h" 167 #include "../bbnnet/seq.h" 168 #include "../bbnnet/rdp_macros.h" 169 170 extern struct rtentry *ip_route(); 171 172 /* 173 * Since a message just got through, re-associating rttl (retransmit 174 * took too long) with some other current outstanding datagram (cf. wait 175 * until some new dgram) is a little paranoid, but let's be careful 176 * in case that new dgram doesn't come along for a while. This also 177 * allows us to decide that the check-for-retransmit and 178 * retransmit-took-too-long timers can be cancelled. 179 */ 180 clear_rxtimer(rdpcb, N) 181 register RDPCB *rdpcb; 182 { 183 int Xi; 184 int pass; 185 186 rdpcb->r_rxtimers[N] = 0; 187 if (rdpcb->r_rttlindex == N) 188 { 189 /* 190 * look for new dgram of which to check rttl 191 */ 192 Xi = rdpcb->r_sendq.rq_front; 193 pass = rdpcb->r_sndnxt - rdpcb->r_snduna; 194 while (--pass >= 0) 195 { 196 if (rdpcb->r_rxtimers[Xi]) 197 { 198 rdpcb->r_rttlindex = Xi; 199 rdpcb->r_timers[RDP_tRTTL] = rdpcb->r_rttl; 200 return; 201 } 202 Xi = (Xi + 1) % rdpcb->r_sendq.rq_maxqlen; 203 } 204 /* 205 * No outstanding dgrams left. 206 */ 207 rdpcb->r_rttlindex = (-1); 208 rdpcb->r_timers[RDP_tRTTL] = 0; 209 rdpcb->r_timers[RDP_tRXMIT] = 0; 210 } 211 } 212 213 /* 214 * set up things to discover the rtt (round trip time) for this 215 * DATA-containing packet. 216 */ 217 #define time_rtt(rdpcb, seqnum) \ 218 if (! (rdpcb)->r_rttiming){ \ 219 (rdpcb)->r_rttiming = TRUE; \ 220 (rdpcb)->r_rtt = 0; \ 221 (rdpcb)->r_rttimed = (seqnum); \ 222 } 223 224 225 /* 226 * Since we play with sb_cc for the socket send buffer to prevent the 227 * user process from sending packets we can't buffer, must ensure it 228 * is restored to a reasonable value before call upon socket code to clean 229 * up or we'll get a "panic: sbdrop". Socket code is called by 230 * in_pcbdetach(). 231 */ 232 trash_pcbs(rdpcb) 233 RDPCB *rdpcb; 234 { 235 register struct sockbuf *sosnd; 236 237 sosnd = &rdpcb->r_inpcb->inp_socket->so_snd; 238 if ((sosnd->sb_cc == sosnd->sb_hiwat) && (sosnd->sb_mb == NULL)) 239 sosnd->sb_cc = 0; 240 in_pcbdetach (rdpcb->r_inpcb, rdp_pcbdisconnect); 241 } 242 243 cancel_timers(rdpcb) 244 register RDPCB *rdpcb; 245 { 246 register int i; 247 248 for (i=0; i<RDP_NTIMERS; i++) 249 rdpcb->r_timers[i] = 0; 250 } 251 252 /************************************************************************/ 253 254 /* 255 * state: RDP_sUNOPENED 256 * input: RDP_iCONNECT 257 */ 258 /*ARGSUSED*/ 259 rdp_unop_connect (rdpcb, nil) 260 register RDPCB *rdpcb; 261 { 262 /* 263 * Send a SYN 264 * and set re-transmission timer to ensure SYN eventually gets there 265 */ 266 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_iss); 267 set_rxtimer (rdpcb, 0); 268 return (RDP_sSYNSENT); 269 } 270 271 /* 272 * state: RDP_sUNOPENED 273 * input: RDP_iLISTEN 274 */ 275 /*ARGSUSED*/ 276 rdp_unop_listen (rdpcb, nil) 277 RDPCB *rdpcb; 278 { 279 return (RDP_sLISTEN); 280 } 281 282 /* 283 * state: RDP_sUNOPENED 284 * input: RDP_iNETR 285 */ 286 /*ARGSUSED*/ 287 rdp_unop_netr (rdpcb, pkt) 288 RDPCB *rdpcb; 289 register RDPHDR *pkt; 290 { 291 if (pkt->rh_flags & (RDP_fACK|RDP_fEACK|RDP_fNULL)) 292 /* 293 * We haven't sent anything to (e)ack. Nor have we 294 * established a connection and received something 295 * that we should ack (null). The sender is very mixed 296 * up, so we'll send him a reset. 297 */ 298 rdp_uncon_rst (pkt); 299 else 300 /* 301 * ignore packet in hope user connect(2)s or listen(2)s before 302 * it's re-transmission comes in. 303 */ 304 m_freem(dtom(pkt)); 305 306 return (RDP_sSAME); 307 } 308 309 /* 310 * state: RDP_sUNOPENED 311 * input: RDP_iUCLOSE 312 */ 313 /*ARGSUSED*/ 314 rdp_unop_close (rdpcb, nil) 315 RDPCB *rdpcb; 316 { 317 trash_pcbs(rdpcb); 318 return (RDP_sCLOSED); 319 } 320 321 /************************************************************************/ 322 323 /* 324 * state: RDP_sLISTEN 325 * input: RDP_iLISTEN 326 */ 327 /*ARGSUSED*/ 328 rdp_lis_listen (rdpcb, nil) 329 RDPCB *rdpcb; 330 { 331 return (RDP_sSAME); 332 } 333 334 /* 335 * state: RDP_sLISTEN 336 * input: RDP_iNETR 337 */ 338 rdp_lis_netr (rdpcb, pkt) 339 RDPCB *rdpcb; 340 register RDPHDR *pkt; 341 { 342 INPCB *inp; 343 struct socket *so; 344 struct rtentry *rt; 345 register RDPCB *newrdpcb; 346 register INPCB *newinp; 347 struct socket *newso; 348 register struct ip *ip; 349 register SYNOPTIONS *synopt; 350 351 if (pkt->rh_flags & (RDP_fRST|RDP_fACK|RDP_fEACK|RDP_fNULL)) 352 { 353 if (pkt->rh_flags & RDP_fRST) 354 /* 355 * Ignore resets since we haven't sent anything to 356 * reset. The packet may be a slow arrival meant to 357 * close a child socket of ours that has already 358 * finished close protocol with this sender. We 359 * ignore it and the other end closes/closed on its own. 360 */ 361 m_freem(dtom(pkt)); 362 else 363 /* 364 * We haven't sent anything to (e)ack. Nor have we 365 * established a connection and received something 366 * that we should ack (null). The sender is very mixed 367 * up, so we'll send him a reset. 368 */ 369 rdp_uncon_rst (pkt); 370 371 return (RDP_sSAME); 372 } 373 374 if (pkt->rh_flags & RDP_fSYN) 375 { 376 /* normal case, someone is trying to connect to us. */ 377 378 ip = (struct ip *) (((char *) pkt) - sizeof(struct ip)); 379 380 /* 381 * O.k., let's get a route back to him 382 */ 383 if (!(rt = ip_route(&ip->ip_dst, &ip->ip_src))) 384 { 385 /* 386 * Can't talk to him. Leave socket in receive state 387 * so we can connect to someone else, since we haven't 388 * been committed to anything yet anyway. 389 * Drop his info on the floor. 390 * Let the other machine figure out on it's own 391 * that it can't reach us that way. 392 */ 393 no_route ("rdp", ip->ip_dst, ip->ip_src); 394 m_freem(dtom(pkt)); 395 return(RDP_sSAME); 396 } 397 398 inp = rdpcb->r_inpcb; 399 so = inp->inp_socket; 400 401 /* 402 * This socket is in the listen state, so the socket should have 403 * so_options & SO_ACCEPTCONN set (solisten()). 404 * 405 * The order of sonewconn() and soisconnected() is 406 * important, in order for the process to be woken up 407 * at a time when the sleep condition is fulfilled. 408 * sonewconn() is done here on the original socket, and 409 * soisconnected() is done later in rdp_lsynrcvd_netr() on 410 * the new socket. 411 */ 412 if (newso = sonewconn(so)) 413 { 414 newinp = (INPCB *) newso->so_pcb; 415 newrdpcb = (RDPCB *) newinp->inp_ppcb; 416 /* 417 * Remember our peer for this connection. 418 */ 419 newinp->inp_faddr = ip->ip_src; 420 newinp->inp_fport = pkt->rh_sport; 421 newinp->inp_laddr = ip->ip_dst; 422 /* 423 * and copy fields into the new inpcb 424 */ 425 newinp->inp_lport = inp->inp_lport; 426 newinp->inp_route.ro_rt = rt; 427 /* 428 * and copy fields into the new rdpcb. In particular, 429 * the user's desired buffering allocations should be 430 * propogated. 431 */ 432 newrdpcb->r_ournbuf = rdpcb->r_ournbuf; 433 sbreserve (&newrdpcb->r_inpcb->inp_socket->so_rcv, 434 rdpcb->r_inpcb->inp_socket->so_rcv.sb_hiwat); 435 pick_ourmaxlen(newrdpcb); 436 /* 437 * Sequential delivery is a combination of both side's 438 * desires, and must be copied from server socket since 439 * user does not have a handle on the child socket in 440 * it's early states. 441 */ 442 newrdpcb->r_sequential = rdpcb->r_sequential; 443 444 /* 445 * and stuff new information 446 */ 447 got_syn(newrdpcb, RDP_SEQNO(pkt)); 448 synopt = RDP_OPT(pkt, SYNOPTIONS *); 449 process_synopt(newrdpcb, synopt); 450 451 /* 452 * So can debug connection problems without having to 453 * change every program or apply debugging flag to each 454 * program every time run it. 455 */ 456 dowedebug(newinp, newso, &rdp_dfilter); 457 458 /* 459 * send other guy our SYN and ACK his syn. 460 * set re-transmission timer to ensure eventually gets 461 * to him. 462 */ 463 rdp_template(newrdpcb); 464 (void) rdp_sendpkt (newrdpcb, (MBUF *) NULL, 0, 465 newrdpcb->r_iss); 466 set_rxtimer (newrdpcb, 0); 467 468 newrdpcb->r_state = RDP_sLSYNRCVD; 469 } 470 else 471 rtfree(rt); 472 } 473 m_freem(dtom(pkt)); 474 return (RDP_sSAME); 475 } 476 477 /* 478 * state: RDP_sLISTEN 479 * input: RDP_iUCLOSE 480 */ 481 /*ARGSUSED*/ 482 rdp_lis_close (rdpcb, nil) 483 RDPCB *rdpcb; 484 { 485 trash_pcbs(rdpcb); 486 return (RDP_sCLOSED); 487 } 488 489 /************************************************************************/ 490 491 /* 492 * state: RDP_sSYNSENT 493 * input: RDP_iNETR 494 */ 495 rdp_synsent_netr (rdpcb, pkt) 496 register RDPCB *rdpcb; 497 register RDPHDR *pkt; 498 { 499 register rdpstate newstate; 500 501 if (pkt->rh_flags & RDP_fACK) 502 { 503 if (RDP_ACKNO(pkt) != rdpcb->r_iss) 504 { 505 /* 506 * We haven't sent any data yet, only SYNs. 507 * He's confused. 508 */ 509 rdp_uncon_rst (pkt); 510 return (RDP_sSAME); 511 } 512 } 513 514 if (pkt->rh_flags & RDP_fRST) 515 { 516 /* 517 * Require (rst, ack, ackno) to know rst meant for this, not 518 * a previous, incarnation of the socket. Is an "in window" 519 * check. Avoids problems with "slow" packets. 520 */ 521 if (pkt->rh_flags & RDP_fACK) 522 { 523 set_error (rdpcb, ECONNREFUSED); 524 trash_pcbs(rdpcb); 525 newstate = RDP_sCLOSED; 526 } 527 else 528 newstate = RDP_sSAME; 529 m_freem(dtom(pkt)); 530 return (newstate); 531 } 532 533 newstate = RDP_sSAME; 534 if (pkt->rh_flags & RDP_fSYN) 535 { 536 register SYNOPTIONS *synopt; 537 rdpsequence seqnum; 538 539 got_syn(rdpcb, RDP_SEQNO(pkt)); 540 synopt = RDP_OPT(pkt, SYNOPTIONS *); 541 process_synopt(rdpcb, synopt); 542 543 if (pkt->rh_flags & RDP_fACK) 544 { 545 rdpcb->r_synacked = TRUE; 546 rdpisconnected(rdpcb); 547 newstate = RDP_sESTAB; 548 seqnum = rdpcb->r_iss +1; 549 /* clear re-xmit syn timer set in rdp_unop_connect() */ 550 clear_rxtimer (rdpcb, 0); 551 /* start up connection loss detection */ 552 rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull; 553 } 554 else 555 { 556 newstate = RDP_sSYNRCVD; 557 seqnum = rdpcb->r_iss; 558 /* keep sending syn until he acks it */ 559 set_rxtimer (rdpcb, 0); 560 } 561 /* and ack his syn, retransmit ours if necessary */ 562 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, seqnum); 563 } 564 565 m_freem(dtom(pkt)); 566 return (newstate); 567 } 568 569 /* 570 * state: RDP_sSYNSENT 571 * input: RDP_iUCLOSE 572 */ 573 /*ARGSUSED*/ 574 rdp_synsent_close (rdpcb, nil) 575 register RDPCB *rdpcb; 576 { 577 /* send RST */ 578 rdpcb->r_sendrst = TRUE; 579 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt); 580 trash_pcbs(rdpcb); 581 return (RDP_sCLOSED); 582 } 583 584 585 /* 586 * state: RDP_sSYNSENT 587 * input: RDP_iTIMER 588 */ 589 rdp_synsent_timer (rdpcb, timer) 590 register RDPCB *rdpcb; 591 { 592 switch (timer) 593 { 594 case RDP_tRTTL: 595 /* retransmission took too long */ 596 rttl(rdpcb); 597 return (RDP_sSAME); 598 599 case RDP_tRXMIT: 600 /* 601 * re-transmit our SYN. Not every 0.5 second, though, 602 * but every RDP_tvRXMIN units. 603 */ 604 rdpcb->r_rxtimers[0] --; 605 if (rdpcb->r_rxtimers[0] == 0) 606 { 607 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, 608 rdpcb->r_iss); 609 set_rxtimer (rdpcb, 0); 610 #ifdef RDP_CS 611 rdpcb->r_sent.r_retrans ++; 612 #endif 613 } 614 else 615 /* 616 * ensure keep checking even if no packet goes 617 * out this time. ACK will stop this. 618 */ 619 rdpcb->r_timers[RDP_tRXMIT] = RDP_tvRXCHECK; 620 break; 621 622 default: 623 log(LOG_INFO, "rdp_synsent_timer: timer %d\n", timer); 624 } 625 626 return(RDP_sSAME); 627 } 628 629 /************************************************************************/ 630 631 /* 632 * state: RDP_sLSYNRCVD 633 * input: RDP_iNETR 634 */ 635 rdp_lsynrcvd_netr (rdpcb, pkt) 636 register RDPCB *rdpcb; 637 register RDPHDR *pkt; 638 { 639 /* 640 * If it's a duplicate syn (seqno == irs), re-send ack since he must 641 * have missed our ack. If it's out of the window, well, let's give 642 * him the benefit of the doubt and assume it's junk from an old 643 * connection/window that took a while to get to us. 644 */ 645 if (SEQ_LEQ(RDP_SEQNO(pkt), rdpcb->r_irs) || 646 SEQ_GEQ(RDP_SEQNO(pkt), rdpcb->r_rcvq.rq_baseseq + rdpcb->r_rcvq.rq_maxqlen)) 647 { 648 649 #ifdef RDP_CS 650 rdpcb->r_rcvd.r_retrans ++; 651 #endif 652 /* try to synchronize again */ 653 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_iss); 654 m_freem(dtom(pkt)); 655 return(RDP_sSAME); 656 } 657 658 if (pkt->rh_flags & (RDP_fRST|RDP_fEACK|RDP_fSYN)) 659 { 660 if (pkt->rh_flags & RDP_fRST) 661 { 662 /* 663 * User closed while his socket was in synsent state. 664 */ 665 set_error (rdpcb, ECONNREFUSED); 666 trash_pcbs(rdpcb); 667 m_freem(dtom(pkt)); 668 return (RDP_sCLOSED); 669 } 670 if (pkt->rh_flags & RDP_fEACK) 671 { 672 /* 673 * shouldn't be EACK, since we haven't sent anything yet 674 */ 675 rdp_uncon_rst (pkt); /* frees mbufs for pkt */ 676 return(RDP_sSAME); 677 } 678 if (pkt->rh_flags & RDP_fSYN) 679 { 680 /* 681 * Boy, is the other end confused! His syn has changed 682 * sequence numbers. 683 */ 684 rdp_uncon_rst (pkt); 685 set_error (rdpcb, ECONNRESET); 686 trash_pcbs(rdpcb); 687 return (RDP_sCLOSED); 688 } 689 } 690 691 if (pkt->rh_flags & RDP_fACK) 692 { 693 if (RDP_ACKNO(pkt) != rdpcb->r_iss) 694 { 695 rdp_uncon_rst (pkt); /* frees mbufs for pkt */ 696 return(RDP_sSAME); 697 } 698 } 699 else 700 { 701 m_freem(dtom(pkt)); 702 return(RDP_sSAME); 703 } 704 705 /* 706 * clear timer for re-transmission of syn that we set in 707 * rdp_lis_netr(). 708 */ 709 clear_rxtimer (rdpcb, 0); 710 rdpcb->r_synacked = TRUE; 711 712 713 if (pkt->rh_dlen > rdpcb->r_ourmaxlen) 714 { 715 log(LOG_INFO, "RDP too large packet %d > %d\n", 716 pkt->rh_dlen, rdpcb->r_ourmaxlen); 717 theygoofed : 718 rdp_uncon_rst(pkt); 719 rdpcb->r_timers[RDP_tCLOSEWAIT] = rdpcb->r_closewait; 720 set_error(rdpcb, ECONNRESET); 721 return (RDP_sCLOSEWAIT); 722 } 723 /* 724 * zero length packets can be NULL messages or (E)ACKs, 725 * but all NULL messages must be zero length 726 */ 727 if (pkt->rh_flags & RDP_fNULL) 728 { 729 if (pkt->rh_dlen != 0) 730 { 731 log(LOG_INFO, "RDP %d length NULL packet\n", pkt->rh_dlen); 732 goto theygoofed; 733 } 734 if (RDP_SEQNO(pkt) != rdpcb->r_rcvq.rq_baseseq) 735 { 736 log(LOG_INFO, "RDP NULL 0x%x rcvq baseseq 0x%x\n", 737 RDP_SEQNO(pkt), rdpcb->r_rcvq.rq_baseseq); 738 goto theygoofed; 739 } 740 rdpcb->r_rcvq.rq_msgs[rdpcb->r_rcvq.rq_front] = NULL; 741 rdpcb->r_rcvq.rq_front = 742 (rdpcb->r_rcvq.rq_front +1) % rdpcb->r_rcvq.rq_maxqlen; 743 rdpcb->r_rcvq.rq_baseseq ++; 744 745 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt); 746 m_freem(dtom(pkt)); 747 } 748 else if (pkt->rh_dlen) 749 { 750 #ifdef RDP_CS 751 if (rdp_qinsert (&rdpcb->r_rcvq, dtom(pkt), RDP_SEQNO(pkt)) == -1) 752 rdpcb->r_rcvd.r_retrans ++; 753 #else 754 (void) rdp_qinsert (&rdpcb->r_rcvq, dtom(pkt), RDP_SEQNO(pkt)); 755 #endif 756 /* No (e)ack now. Wait til gets to user */ 757 } 758 else 759 /* Was an ACK-only packet */ 760 m_freem(dtom(pkt)); 761 762 763 rdpisconnected(rdpcb); 764 /* start up connection loss detection */ 765 rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull; 766 return (RDP_sESTAB); 767 } 768 769 /* 770 * state: RDP_sLSYNRCVD 771 * input: RDP_iUCLOSE 772 */ 773 /*ARGSUSED*/ 774 rdp_lsynrcvd_close (rdpcb, nil) 775 register RDPCB *rdpcb; 776 { 777 /* send RST */ 778 rdpcb->r_sendrst = TRUE; 779 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt); 780 trash_pcbs(rdpcb); 781 return (RDP_sCLOSED); 782 } 783 784 /* 785 * state: RDP_sLSYNRCVD 786 * input: RDP_iTIMER 787 */ 788 rdp_lsynrcvd_timer (rdpcb, timer) 789 RDPCB *rdpcb; 790 { 791 /* whether connecting via connect(2) (SYNSENT) or child of 792 * or via child of a listen(2)ing socket (LSYNRCVD), need to 793 * retransmit out syn until it gets acked. 794 */ 795 796 797 return (rdp_synsent_timer (rdpcb, timer)); 798 } 799 800 /************************************************************************/ 801 802 /* 803 * state: RDP_sSYNRCVD 804 * input: RDP_iNETR 805 */ 806 rdp_synrcvd_netr (rdpcb, pkt) 807 RDPCB *rdpcb; 808 RDPHDR *pkt; 809 { 810 return (rdp_lsynrcvd_netr(rdpcb, pkt)); 811 } 812 813 /* 814 * state: RDP_sSYNRCVD 815 * input: RDP_iUCLOSE 816 */ 817 rdp_synrcvd_close (rdpcb, nil) 818 RDPCB *rdpcb; 819 { 820 return (rdp_lsynrcvd_close(rdpcb, nil)); 821 } 822 823 /* 824 * state: RDP_sSYNRCVD 825 * input: RDP_iTIMER 826 */ 827 rdp_synrcvd_timer (rdpcb, timer) 828 RDPCB *rdpcb; 829 { 830 return (rdp_lsynrcvd_timer (rdpcb, timer)); 831 } 832 833 /************************************************************************/ 834 835 /* 836 * state: RDP_sESTAB 837 * input: RDP_iNETR 838 */ 839 rdp_estab_netr (rdpcb, pkt) 840 register RDPCB *rdpcb; 841 register RDPHDR *pkt; 842 { 843 /* 844 * ensure packet is in window. If not, ack him to straighten things 845 * out. 846 */ 847 if (SEQ_LT(RDP_SEQNO(pkt), rdpcb->r_rcvq.rq_baseseq) || 848 SEQ_GEQ(RDP_SEQNO(pkt), rdpcb->r_rcvq.rq_baseseq + rdpcb->r_rcvq.rq_maxqlen)) 849 { 850 #ifdef RDP_CS 851 rdpcb->r_rcvd.r_retrans ++; 852 #endif 853 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt); 854 m_freem(dtom(pkt)); 855 return (RDP_sSAME); 856 } 857 858 /* 859 * Whenever we receive a packet and we're not already waiting for 860 * an ack of a NULL we sent, reset NULL timer. Connection is alive. 861 * 862 * Don't reset for any packet if have an outstanding NULL since want 863 * to keep timer at zero and not generate a new NULL segment until 864 * current one is acknowledged. (This might be a new message, not 865 * the NULL's ack. Send and receive paths may differ?) 866 * 867 * Don't reset NULL timer on datagram transmissions since those imply 868 * receiving ACKs. Besides, we want to know if he is up, not if we're 869 * up. 870 */ 871 if (rdpcb->r_nullsent == 0) 872 rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull; 873 874 if (pkt->rh_flags & (RDP_fSYN|RDP_fRST)) 875 { 876 m_freem(dtom(pkt)); 877 set_error(rdpcb, ECONNRESET); 878 879 if (pkt->rh_flags & RDP_fSYN) 880 { 881 /* 882 * We've gotten past the syn stage. He's confused. 883 * His syn has also changed sequence numbers. 884 */ 885 rdpcb->r_sendrst = TRUE; 886 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt); 887 trash_pcbs(rdpcb); 888 return (RDP_sCLOSED); 889 } 890 891 /* 892 * Since we've been reset, the user cannot send anymore 893 * datagrams. user_cantsendmore() also wakes writers up 894 * in case he is doing synchronous i/o and is waiting for 895 * buffering space at the (socket) level. 896 */ 897 user_cantsendmore(rdpcb); 898 /* 899 * User can't read anymore either, per specification. 900 * Reliable delivery and acceptance must be determined 901 * by the application before closing. 902 */ 903 user_cantreadmore(rdpcb); 904 cancel_timers(rdpcb); 905 rdpcb->r_timers[RDP_tCLOSEWAIT] = rdpcb->r_closewait; 906 return (RDP_sCLOSEWAIT); 907 } 908 909 if (pkt->rh_flags & RDP_fACK) 910 he_acked (rdpcb, RDP_ACKNO(pkt)); 911 912 if (pkt->rh_flags & RDP_fEACK) 913 { 914 register int neacks; 915 register EACKOPTIONS *eackopt; 916 917 neacks = (hdrlen(pkt) - RDPHDRSZ) / sizeof(EACKOPTIONS); 918 eackopt = RDP_OPT(pkt, EACKOPTIONS *); 919 while (--neacks >= 0) 920 { 921 he_eacked (rdpcb, ntohl(eackopt->rh_eackno)); 922 eackopt ++; 923 } 924 } 925 926 if (pkt->rh_dlen > rdpcb->r_ourmaxlen) 927 { 928 log(LOG_INFO, "RDP pkt too large %d > %d\n", 929 pkt->rh_dlen, rdpcb->r_ourmaxlen); 930 theygoofed : 931 rdp_uncon_rst(pkt); 932 set_error(rdpcb, ECONNRESET); 933 user_cantsendmore(rdpcb); 934 user_cantreadmore(rdpcb); 935 cancel_timers(rdpcb); 936 rdpcb->r_timers[RDP_tCLOSEWAIT] = rdpcb->r_closewait; 937 return (RDP_sCLOSEWAIT); 938 } 939 940 if (pkt->rh_flags & RDP_fNULL) 941 { 942 if (pkt->rh_dlen != 0) 943 { 944 log(LOG_INFO, "RDP %d length NULL pkt\n", pkt->rh_dlen); 945 goto theygoofed; 946 } 947 if (RDP_SEQNO(pkt) != rdpcb->r_rcvq.rq_baseseq) 948 { 949 log(LOG_INFO, "RDP NULL 0x%x rcvq baseseq 0x%x\n", 950 RDP_SEQNO(pkt), rdpcb->r_rcvq.rq_baseseq); 951 goto theygoofed; 952 } 953 rdpcb->r_rcvq.rq_msgs[rdpcb->r_rcvq.rq_front] = NULL; 954 rdpcb->r_rcvq.rq_front = 955 (rdpcb->r_rcvq.rq_front +1) % rdpcb->r_rcvq.rq_maxqlen; 956 rdpcb->r_rcvq.rq_baseseq ++; 957 958 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt); 959 m_freem(dtom(pkt)); 960 } 961 else if (pkt->rh_dlen) 962 { 963 #ifdef RDP_CS 964 if (rdp_qinsert (&rdpcb->r_rcvq, dtom(pkt), RDP_SEQNO(pkt)) == -1) 965 rdpcb->r_rcvd.r_retrans ++; 966 #else 967 (void) rdp_qinsert (&rdpcb->r_rcvq, dtom(pkt), RDP_SEQNO(pkt)); 968 #endif 969 } 970 else 971 /* Was an ACK-only packet */ 972 m_freem(dtom(pkt)); 973 974 975 if (usr_rbuf_is_empty(rdpcb)) 976 { 977 register MBUF *m; 978 979 if (m = rdp_qremove(&rdpcb->r_rcvq, !rdpcb->r_sequential)) 980 { 981 /* 982 * IP and RDP headers should be in the first mbuf. 983 * User does not see them. 984 */ 985 pkt = (RDPHDR *) (mtod(m, char *) + sizeof(struct ip)); 986 #ifdef RDP_CS 987 rdpcb->r_rcvd.r_nbytes += pkt->rh_dlen; 988 #endif 989 m->m_off += sizeof(struct ip) + hdrlen(pkt); 990 m->m_len -= sizeof(struct ip) + hdrlen(pkt); 991 992 usr_rbuf_append(rdpcb, m); 993 wakeup_reader(rdpcb); 994 } 995 } 996 997 /* 998 * datagrams go straight out in response to the send(2) PRU_SEND, 999 * so getting (e)acks doesn't cause an outgoing datagram. 1000 * Hold off on (e)ack of incoming packet until user receives it 1001 * and we know that by PRU_RCV. 1002 */ 1003 return (RDP_sSAME); 1004 } 1005 1006 /* 1007 * state: RDP_sESTAB 1008 * input: RDP_iUCLOSE 1009 */ 1010 /*ARGSUSED*/ 1011 rdp_estab_close (rdpcb, nil) 1012 register RDPCB *rdpcb; 1013 { 1014 /* send RST */ 1015 rdpcb->r_sendrst = TRUE; 1016 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt); 1017 1018 /* 1019 * Don't retransmit unacked datagrams, since user can't pick them 1020 * up anymore once he's been reset (according to specification). 1021 * Reliable delivery and acceptance must be determined by the 1022 * application before closing. 1023 */ 1024 cancel_timers(rdpcb); 1025 rdpcb->r_timers[RDP_tCLOSEWAIT] = rdpcb->r_closewait; 1026 return (RDP_sCLOSEWAIT); 1027 } 1028 1029 /* 1030 * state: RDP_sESTAB 1031 * input: RDP_iTIMER 1032 */ 1033 rdp_estab_timer (rdpcb, timer) 1034 register RDPCB *rdpcb; 1035 { 1036 register MBUF *rxmit_data; 1037 register int index, passes; 1038 rdpsequence seqno; 1039 1040 switch (timer) 1041 { 1042 case RDP_tRTTL: 1043 /* retransmission took too long */ 1044 rttl(rdpcb); 1045 return (RDP_sSAME); 1046 1047 case RDP_tRXMIT: 1048 /* 1049 * ensure keep checking even if no packet goes 1050 * out this time. ACK will stop this. 1051 */ 1052 rdpcb->r_timers[RDP_tRXMIT] = RDP_tvRXCHECK; 1053 1054 index = rdpcb->r_sendq.rq_front; 1055 passes = rdpcb->r_sndnxt - rdpcb->r_snduna; 1056 seqno = rdpcb->r_sendq.rq_baseseq; /* == r_snduna */ 1057 1058 while (--passes >= 0) 1059 { 1060 if (rdpcb->r_rxtimers[index]) 1061 { 1062 rdpcb->r_rxtimers[index] --; 1063 if (rdpcb->r_rxtimers[index] == 0) 1064 { 1065 MBUF *m; 1066 1067 /* 1068 * Over lossy networks, do not let 1069 * the round trip time estimate 1070 * drift unecessarily high. If we're 1071 * considering the round-trip-time- 1072 * measuring packet lost, and are 1073 * retransmitting it, then we should 1074 * reset the round trip time measurment 1075 */ 1076 if (rdpcb->r_rttiming) 1077 if (seqno == rdpcb->r_rttimed) 1078 rdpcb->r_rttiming = FALSE; 1079 1080 m = rdpcb->r_sendq.rq_msgs[index]; 1081 if (m == RDP_NULLMSG) 1082 { 1083 rdpcb->r_sendnull = TRUE; 1084 if (rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, seqno) == 0) 1085 time_rtt(rdpcb, seqno); 1086 1087 /* 1088 * Back off on retransmissions, 1089 * because the host might be 1090 * down or the network could be 1091 * jammed. rxmitime will drop 1092 * to normal when we get the ACK 1093 */ 1094 rdpcb->r_rxmitime = MIN (RDP_tvRXMAX, 1095 rdpcb->r_rxmitime << 1); 1096 1097 if (++rdpcb->r_nullsent > RDP_MAXNULL) 1098 { 1099 /* advisory only */ 1100 set_error(rdpcb, ETIMEDOUT); 1101 wakeup_reader(rdpcb); 1102 /* writer timeout via rttl */ 1103 1104 /* avoid rollover to zero 1105 * 1106 * NOTE: user will get 1107 * ETIMEDOUT on every 1108 * rxmit, another reason 1109 * to back off above. 1110 */ 1111 rdpcb->r_nullsent --; 1112 } 1113 } 1114 else 1115 { 1116 if (rxmit_data =m_copy(m, 0, M_COPYALL)) 1117 /* 1118 * When we 1st sent it, we 1119 * remembered the len in m_act 1120 */ 1121 if (rdp_sendpkt(rdpcb,rxmit_data,(int)m->m_act,seqno)==0) 1122 time_rtt(rdpcb, seqno); 1123 1124 /* 1125 * We aren't backing off here, 1126 * since the single number is 1127 * used for all datagrams, 1128 * each of which may be at a 1129 * different nth rxmission 1130 */ 1131 } 1132 1133 #ifdef RDP_CS 1134 rdpcb->r_sent.r_retrans ++; 1135 #endif 1136 set_rxtimer (rdpcb, index); 1137 } 1138 } 1139 index = (index + 1) % rdpcb->r_sendq.rq_maxqlen; 1140 seqno ++; 1141 } 1142 break; 1143 1144 case RDP_tACKDELAY: 1145 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt); 1146 break; 1147 1148 case RDP_tNULL: 1149 /* 1150 * If we're retransmitting, then we don't need to 1151 * send NULL messages. The NULL timer drops to zero 1152 * and gets restarted when we get some packet from 1153 * them (rdp_estab_netr). User will get ETIMEDOUT 1154 * from retransmit took too long if we don't get a 1155 * packet. 1156 */ 1157 if (rdpcb->r_rttlindex < 0) 1158 { 1159 /* are not retransmitting */ 1160 1161 /* 1162 * Idea: The connection has been idle for too 1163 * long. send a NULL packet which has its own 1164 * sequence number (so can distinguish slow to 1165 * arrive ack from ack of this NULL) and 1166 * retransmit it via normal packet 1167 * retransmission algorithm. 1168 */ 1169 1170 if (rdp_qinsert(&rdpcb->r_sendq, RDP_NULLMSG, rdpcb->r_sndnxt) != 1) 1171 panic("rdp RDP_tNULL"); 1172 1173 rdpcb->r_sendnull = TRUE; 1174 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt); 1175 index = rdpcb->r_sendq.rq_front + (rdpcb->r_sndnxt - rdpcb->r_snduna); 1176 index %= rdpcb->r_sendq.rq_maxqlen; 1177 set_rxtimer (rdpcb, index); 1178 rdpcb->r_sndnxt ++; 1179 rdpcb->r_nullsent = 1; 1180 } 1181 break; 1182 1183 default: 1184 log(LOG_INFO, "rdp_estab_timer: timer %d\n", timer); 1185 } 1186 1187 return(RDP_sSAME); 1188 } 1189 1190 /* 1191 * state: RDP_sESTAB 1192 * input: RDP_iRCV 1193 */ 1194 /*ARGSUSED*/ 1195 rdp_estab_rcv (rdpcb, nil) 1196 register RDPCB *rdpcb; 1197 { 1198 MBUF *m; 1199 1200 /* 1201 * Now that user has received the packet, bump the front so that 1202 * we can ACK it and move the window along. 1203 */ 1204 rdp_received (&rdpcb->r_rcvq); 1205 1206 /* 1207 * user picked up the packet we left on the socket for him. 1208 * Let's put another one there. 1209 */ 1210 if (m = rdp_qremove(&rdpcb->r_rcvq, !rdpcb->r_sequential)) 1211 { 1212 RDPHDR *pkt; 1213 1214 /* 1215 * IP and RDP headers should be in the first mbuf. 1216 * User does not see them. 1217 */ 1218 pkt = (RDPHDR *) (mtod(m, char *) + sizeof(struct ip)); 1219 #ifdef RDP_CS 1220 rdpcb->r_rcvd.r_nbytes += pkt->rh_dlen; 1221 #endif 1222 m->m_off += sizeof(struct ip) + hdrlen(pkt); 1223 m->m_len -= sizeof(struct ip) + hdrlen(pkt); 1224 1225 usr_rbuf_append(rdpcb, m); 1226 /* wakeup_reader(rdpcb); is awake, performing read(2) */ 1227 } 1228 1229 /* 1230 * Send an ACK, but apply an ACK-delay algorithm in order to 1231 * reduce CPU loading on both hosts involved. Reduces network 1232 * load, too. Skip at most one ACK. 1233 */ 1234 if (rdpcb->r_timers[RDP_tACKDELAY]) 1235 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt); 1236 else 1237 rdpcb->r_timers[RDP_tACKDELAY] = 1; 1238 1239 return (RDP_sSAME); 1240 } 1241 1242 /* 1243 * state: RDP_sESTAB 1244 * input: RDP_iSEND 1245 */ 1246 rdp_estab_send (rdpcb, m) 1247 register RDPCB *rdpcb; 1248 register MBUF *m; 1249 { 1250 register MBUF *copym; 1251 register int len; 1252 register int index; 1253 1254 /* 1255 * q message on send q. 1256 */ 1257 if (rdp_qinsert(&rdpcb->r_sendq, m, rdpcb->r_sndnxt) != 1) 1258 panic("rdp_estab_send"); 1259 1260 /* 1261 * Remember the length of the datagram for sending now, 1262 * and for retransmissions later. 1263 */ 1264 len = 0; 1265 for (copym = m; copym; copym = copym->m_next) 1266 len += copym->m_len; 1267 m->m_act = ((MBUF *) len); 1268 1269 /* 1270 * if reached end of window, block socket code from allowing 1271 * sends until get an ACK 1272 */ 1273 if (SEQ_GEQ(rdpcb->r_sndnxt, rdpcb->r_snduna + rdpcb->r_hisnbuf -1)) 1274 sendbufisfull(rdpcb); 1275 1276 /* 1277 * send a copy of the datagram 1278 */ 1279 if (copym = m_copy(m, 0, M_COPYALL)) 1280 if (rdp_sendpkt(rdpcb, copym, len, rdpcb->r_sndnxt) == 0) 1281 time_rtt (rdpcb, rdpcb->r_sndnxt); 1282 1283 index = rdpcb->r_sendq.rq_front + (rdpcb->r_sndnxt - rdpcb->r_snduna); 1284 index %= rdpcb->r_sendq.rq_maxqlen; 1285 set_rxtimer(rdpcb, index); 1286 1287 rdpcb->r_sndnxt ++; 1288 1289 return (RDP_sSAME); 1290 } 1291 1292 /************************************************************************/ 1293 1294 /* 1295 * state: RDP_sCLOSEWAIT 1296 * input: RDP_iNETR 1297 */ 1298 rdp_closew_netr (rdpcb, pkt) 1299 RDPCB *rdpcb; 1300 RDPHDR *pkt; 1301 { 1302 rdpstate newstate; 1303 1304 if (pkt->rh_flags & RDP_fRST) 1305 { 1306 /* 1307 * We've both agreed to shut down the connection 1308 */ 1309 trash_pcbs(rdpcb); 1310 newstate = RDP_sCLOSED; 1311 } 1312 else 1313 newstate = RDP_sSAME; 1314 1315 m_freem(dtom(pkt)); 1316 return(newstate); 1317 } 1318 1319 /* 1320 * state: RDP_sCLOSEWAIT 1321 * input: RDP_iUCLOSE 1322 */ 1323 /*ARGSUSED*/ 1324 rdp_closew_close (rdpcb, nil) 1325 register RDPCB *rdpcb; 1326 { 1327 /* 1328 * rdp_usrreq() only allows one close call to the finite state machine. 1329 * Therefore, we entered CLOSEWAIT in response to a RST, not a close. 1330 * So, now both sides agree to close co-operatively. 1331 */ 1332 rdpcb->r_sendrst = TRUE; 1333 (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt); 1334 1335 trash_pcbs(rdpcb); 1336 return(RDP_sCLOSED); 1337 } 1338 1339 /* 1340 * state: RDP_sCLOSEWAIT 1341 * input: RDP_iTIMER 1342 */ 1343 rdp_closew_timer (rdpcb, timer) 1344 RDPCB *rdpcb; 1345 { 1346 if (timer != RDP_tCLOSEWAIT) 1347 { 1348 log(LOG_INFO, "rdp_closew_timer: timer %d\n", timer); 1349 return(RDP_sSAME); 1350 } 1351 1352 trash_pcbs(rdpcb); 1353 return(RDP_sCLOSED); 1354 } 1355 1356 /* 1357 * state: RDP_sCLOSEWAIT 1358 * input: RDP_iRCV 1359 */ 1360 /*ARGSUSED*/ 1361 rdp_closew_rcv(rdpcb, nil) 1362 { 1363 /* 1364 * Technically, an illegal transition. However, socket code drops 1365 * system priority level, allowing processing of a network packet 1366 * containing RDP reset to cause ESTAB -> CLOSEWAIT in the middle of 1367 * passing the user a packet. 1368 * 1369 * ESTAB ... user receives packet, priority dropped for uiomove() 1370 * --- network packet processed --- 1371 * CLOSEWAIT ... socket code continues, causing this action. 1372 * 1373 * ### This can be a serious problem in general. 1374 */ 1375 } 1376 #endif 1377