1 /*********************************************************** 2 Copyright IBM Corporation 1987 3 4 All Rights Reserved 5 6 Permission to use, copy, modify, and distribute this software and its 7 documentation for any purpose and without fee is hereby granted, 8 provided that the above copyright notice appear in all copies and that 9 both that copyright notice and this permission notice appear in 10 supporting documentation, and that the name of IBM not be 11 used in advertising or publicity pertaining to distribution of the 12 software without specific, written prior permission. 13 14 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20 SOFTWARE. 21 22 ******************************************************************/ 23 24 /* 25 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26 */ 27 /* 28 * ARGO TP 29 * 30 * $Header: tp_pcb.c,v 5.4 88/11/18 17:28:24 nhall Exp $ 31 * $Source: /usr/argo/sys/netiso/RCS/tp_pcb.c,v $ 32 * @(#)tp_pcb.c 7.5 (Berkeley) 01/16/90 * 33 * 34 * 35 * This is the initialization and cleanup stuff - 36 * for the tp machine in general as well as for the individual pcbs. 37 * tp_init() is called at system startup. tp_attach() and tp_getref() are 38 * called when a socket is created. tp_detach() and tp_freeref() 39 * are called during the closing stage and/or when the reference timer 40 * goes off. 41 * tp_soisdisconnecting() and tp_soisdisconnected() are tp-specific 42 * versions of soisconnect* 43 * and are called (obviously) during the closing phase. 44 * 45 */ 46 47 #ifndef lint 48 static char *rcsid = "$Header: tp_pcb.c,v 5.4 88/11/18 17:28:24 nhall Exp $"; 49 #endif lint 50 51 #include "argoxtwentyfive.h" 52 #include "types.h" 53 #include "param.h" 54 #include "mbuf.h" 55 #include "socket.h" 56 #include "socketvar.h" 57 #include "protosw.h" 58 #include "errno.h" 59 #include "time.h" 60 #include "argo_debug.h" 61 #include "tp_param.h" 62 #include "tp_timer.h" 63 #include "tp_ip.h" 64 #include "tp_stat.h" 65 #include "tp_pcb.h" 66 #include "tp_tpdu.h" 67 #include "tp_trace.h" 68 #include "tp_meas.h" 69 #include "tp_seq.h" 70 #include "tp_clnp.h" 71 72 /* list of reference structures */ 73 struct tp_ref tp_ref[N_TPREF]; 74 75 struct tp_param tp_param = { 76 1, /* configured */ 77 }; 78 79 /* ticks are in units of: 80 * 500 nano-fortnights ;-) or 81 * 500 ms or 82 * 1/2 second 83 */ 84 85 struct tp_conn_param tp_conn_param[] = { 86 /* ISO_CLNS: TP4 CONNECTION LESS */ 87 { 88 TP_NRETRANS, /* short p_Nretrans; */ 89 20, /* 10 sec */ /* short p_dr_ticks; */ 90 91 20, /* 10 sec */ /* short p_cc_ticks; */ 92 20, /* 10 sec */ /* short p_dt_ticks; */ 93 94 40, /* 20 sec */ /* short p_x_ticks; */ 95 80, /* 40 sec */ /* short p_cr_ticks;*/ 96 97 240, /* 2 min */ /* short p_keepalive_ticks;*/ 98 10, /* 5 sec */ /* short p_sendack_ticks; */ 99 100 600, /* 5 min */ /* short p_ref_ticks; */ 101 360, /* 3 min */ /* short p_inact_ticks; */ 102 103 (short) 100, /* short p_lcdtfract */ 104 (short) TP_SOCKBUFSIZE, /* short p_winsize */ 105 TP_TPDUSIZE, /* u_char p_tpdusize */ 106 107 TPACK_WINDOW, /* 4 bits p_ack_strat */ 108 TPRX_USE_CW | TPRX_FASTSTART, 109 /* 4 bits p_rx_strat*/ 110 TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */ 111 1, /* 1 bit xtd format */ 112 1, /* 1 bit xpd service */ 113 1, /* 1 bit use_checksum */ 114 0, /* 1 bit use net xpd */ 115 0, /* 1 bit use rcc */ 116 0, /* 1 bit use efc */ 117 1, /* no disc indications */ 118 0, /* don't change params */ 119 ISO_CLNS, /* p_netservice */ 120 }, 121 /* IN_CLNS: TP4 CONNECTION LESS */ 122 { 123 TP_NRETRANS, /* short p_Nretrans; */ 124 20, /* 10 sec */ /* short p_dr_ticks; */ 125 126 20, /* 10 sec */ /* short p_cc_ticks; */ 127 20, /* 10 sec */ /* short p_dt_ticks; */ 128 129 40, /* 20 sec */ /* short p_x_ticks; */ 130 80, /* 40 sec */ /* short p_cr_ticks;*/ 131 132 240, /* 2 min */ /* short p_keepalive_ticks;*/ 133 10, /* 5 sec */ /* short p_sendack_ticks; */ 134 135 600, /* 5 min */ /* short p_ref_ticks; */ 136 360, /* 3 min */ /* short p_inact_ticks; */ 137 138 (short) 100, /* short p_lcdtfract */ 139 (short) TP_SOCKBUFSIZE, /* short p_winsize */ 140 TP_TPDUSIZE, /* u_char p_tpdusize */ 141 142 TPACK_WINDOW, /* 4 bits p_ack_strat */ 143 TPRX_USE_CW | TPRX_FASTSTART, 144 /* 4 bits p_rx_strat*/ 145 TP_CLASS_4, /* 5 bits p_class */ 146 1, /* 1 bit xtd format */ 147 1, /* 1 bit xpd service */ 148 1, /* 1 bit use_checksum */ 149 0, /* 1 bit use net xpd */ 150 0, /* 1 bit use rcc */ 151 0, /* 1 bit use efc */ 152 1, /* no disc indications */ 153 0, /* don't change params */ 154 IN_CLNS, /* p_netservice */ 155 }, 156 /* ISO_CONS: TP0 CONNECTION MODE */ 157 { 158 TP_NRETRANS, /* short p_Nretrans; */ 159 0, /* n/a */ /* short p_dr_ticks; */ 160 161 40, /* 20 sec */ /* short p_cc_ticks; */ 162 0, /* n/a */ /* short p_dt_ticks; */ 163 164 0, /* n/a */ /* short p_x_ticks; */ 165 360, /* 3 min */ /* short p_cr_ticks;*/ 166 167 0, /* n/a */ /* short p_keepalive_ticks;*/ 168 0, /* n/a */ /* short p_sendack_ticks; */ 169 170 600, /* for cr/cc to clear *//* short p_ref_ticks; */ 171 0, /* n/a */ /* short p_inact_ticks; */ 172 173 /* Use tp4 defaults just in case the user changes ONLY 174 * the class 175 */ 176 (short) 100, /* short p_lcdtfract */ 177 (short) TP0_SOCKBUFSIZE, /* short p_winsize */ 178 TP0_TPDUSIZE, /* 8 bits p_tpdusize */ 179 180 0, /* 4 bits p_ack_strat */ 181 0, /* 4 bits p_rx_strat*/ 182 TP_CLASS_0, /* 5 bits p_class */ 183 0, /* 1 bit xtd format */ 184 0, /* 1 bit xpd service */ 185 0, /* 1 bit use_checksum */ 186 0, /* 1 bit use net xpd */ 187 0, /* 1 bit use rcc */ 188 0, /* 1 bit use efc */ 189 0, /* no disc indications */ 190 0, /* don't change params */ 191 ISO_CONS, /* p_netservice */ 192 }, 193 /* ISO_COSNS: TP4 CONNECTION LESS SERVICE over CONSNS */ 194 { 195 TP_NRETRANS, /* short p_Nretrans; */ 196 40, /* 20 sec */ /* short p_dr_ticks; */ 197 198 40, /* 20 sec */ /* short p_cc_ticks; */ 199 80, /* 40 sec */ /* short p_dt_ticks; */ 200 201 120, /* 1 min */ /* short p_x_ticks; */ 202 360, /* 3 min */ /* short p_cr_ticks;*/ 203 204 360, /* 3 min */ /* short p_keepalive_ticks;*/ 205 20, /* 10 sec */ /* short p_sendack_ticks; */ 206 207 600, /* 5 min */ /* short p_ref_ticks; */ 208 480, /* 4 min */ /* short p_inact_ticks; */ 209 210 (short) 100, /* short p_lcdtfract */ 211 (short) TP0_SOCKBUFSIZE, /* short p_winsize */ 212 TP0_TPDUSIZE, /* u_char p_tpdusize */ 213 214 TPACK_WINDOW, /* 4 bits p_ack_strat */ 215 TPRX_USE_CW , /* No fast start */ 216 /* 4 bits p_rx_strat*/ 217 TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */ 218 0, /* 1 bit xtd format */ 219 1, /* 1 bit xpd service */ 220 1, /* 1 bit use_checksum */ 221 0, /* 1 bit use net xpd */ 222 0, /* 1 bit use rcc */ 223 0, /* 1 bit use efc */ 224 0, /* no disc indications */ 225 0, /* don't change params */ 226 ISO_COSNS, /* p_netservice */ 227 }, 228 }; 229 230 #ifdef INET 231 int in_putnetaddr(); 232 int in_getnetaddr(); 233 int in_putsufx(); 234 int in_getsufx(); 235 int in_recycle_tsuffix(); 236 int tpip_mtu(); 237 int in_pcbbind(); 238 int in_pcbconnect(); 239 int in_pcbdisconnect(); 240 int in_pcbdetach(); 241 int in_pcballoc(); 242 int tpip_output(); 243 int tpip_output_dg(); 244 struct inpcb tp_inpcb; 245 #endif INET 246 #ifdef ISO 247 int iso_putnetaddr(); 248 int iso_getnetaddr(); 249 int iso_putsufx(); 250 int iso_getsufx(); 251 int iso_recycle_tsuffix(); 252 int tpclnp_mtu(); 253 int iso_pcbbind(); 254 int iso_pcbconnect(); 255 int iso_pcbdisconnect(); 256 int iso_pcbdetach(); 257 int iso_pcballoc(); 258 int tpclnp_output(); 259 int tpclnp_output_dg(); 260 int iso_nlctloutput(); 261 struct isopcb tp_isopcb; 262 #endif ISO 263 #if NARGOXTWENTYFIVE > 0 264 int iso_putnetaddr(); 265 int iso_getnetaddr(); 266 int iso_putsufx(); 267 int iso_getsufx(); 268 int iso_recycle_tsuffix(); 269 int tpcons_mtu(); 270 int iso_pcbbind(); 271 int iso_pcbconnect(); 272 int iso_pcbdisconnect(); 273 int iso_pcbdetach(); 274 int iso_pcballoc(); 275 int tpcons_output(); 276 int tpcons_output_dg(); 277 struct isopcb tp_isopcb; 278 #endif NARGOXTWENTYFIVE 279 280 281 struct nl_protosw nl_protosw[] = { 282 /* ISO_CLNS */ 283 #ifdef ISO 284 { AF_ISO, iso_putnetaddr, iso_getnetaddr, 285 iso_putsufx, iso_getsufx, 286 iso_recycle_tsuffix, 287 tpclnp_mtu, iso_pcbbind, iso_pcbconnect, 288 iso_pcbdisconnect, iso_pcbdetach, 289 iso_pcballoc, 290 tpclnp_output, tpclnp_output_dg, iso_nlctloutput, 291 (caddr_t) &tp_isopcb, 292 }, 293 #else 294 { 0 }, 295 #endif ISO 296 /* IN_CLNS */ 297 #ifdef INET 298 { AF_INET, in_putnetaddr, in_getnetaddr, 299 in_putsufx, in_getsufx, 300 in_recycle_tsuffix, 301 tpip_mtu, in_pcbbind, in_pcbconnect, 302 in_pcbdisconnect, in_pcbdetach, 303 in_pcballoc, 304 tpip_output, tpip_output_dg, /* nl_ctloutput */ NULL, 305 (caddr_t) &tp_inpcb, 306 }, 307 #else 308 { 0 }, 309 #endif INET 310 /* ISO_CONS */ 311 #if defined(ISO) && (NARGOXTWENTYFIVE > 0) 312 { AF_ISO, iso_putnetaddr, iso_getnetaddr, 313 iso_putsufx, iso_getsufx, 314 iso_recycle_tsuffix, 315 tpcons_mtu, iso_pcbbind, iso_pcbconnect, 316 iso_pcbdisconnect, iso_pcbdetach, 317 iso_pcballoc, 318 tpcons_output, tpcons_output_dg, iso_nlctloutput, 319 (caddr_t) &tp_isopcb, 320 }, 321 #else 322 { 0 }, 323 #endif ISO_CONS 324 /* End of protosw marker */ 325 { 0 } 326 }; 327 328 /* 329 * NAME: tp_init() 330 * 331 * CALLED FROM: 332 * autoconf through the protosw structure 333 * 334 * FUNCTION: 335 * initialize tp machine 336 * 337 * RETURNS: Nada 338 * 339 * SIDE EFFECTS: 340 * 341 * NOTES: 342 */ 343 int 344 tp_init() 345 { 346 static int init_done=0; 347 void tp_timerinit(); 348 349 if (init_done++) 350 return 0; 351 352 353 /* FOR INET */ 354 tp_inpcb.inp_next = tp_inpcb.inp_prev = &tp_inpcb; 355 /* FOR ISO */ 356 tp_isopcb.isop_next = tp_isopcb.isop_prev = &tp_isopcb; 357 358 tp_start_win = 2; 359 360 tp_timerinit(); 361 bzero((caddr_t)&tp_stat, sizeof(struct tp_stat)); 362 return 0; 363 } 364 365 /* 366 * NAME: tp_soisdisconnecting() 367 * 368 * CALLED FROM: 369 * tp.trans 370 * 371 * FUNCTION and ARGUMENTS: 372 * Set state of the socket (so) to reflect that fact that we're disconnectING 373 * 374 * RETURNS: Nada 375 * 376 * SIDE EFFECTS: 377 * 378 * NOTES: 379 * This differs from the regular soisdisconnecting() in that the latter 380 * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags. 381 * We don't want to set those flags because those flags will cause 382 * a SIGPIPE to be delivered in sosend() and we don't like that. 383 * If anyone else is sleeping on this socket, wake 'em up. 384 */ 385 void 386 tp_soisdisconnecting(so) 387 register struct socket *so; 388 { 389 soisdisconnecting(so); 390 so->so_state &= ~SS_CANTSENDMORE; 391 IFPERF(sototpcb(so)) 392 register struct tp_pcb *tpcb = sototpcb(so); 393 u_int fsufx, lsufx; 394 395 bcopy ((caddr_t)tpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) ); 396 bcopy ((caddr_t)tpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) ); 397 398 tpmeas(tpcb->tp_lref, TPtime_close, &time, fsufx, lsufx, tpcb->tp_fref); 399 tpcb->tp_perf_on = 0; /* turn perf off */ 400 ENDPERF 401 } 402 403 404 /* 405 * NAME: tp_soisdisconnected() 406 * 407 * CALLED FROM: 408 * tp.trans 409 * 410 * FUNCTION and ARGUMENTS: 411 * Set state of the socket (so) to reflect that fact that we're disconnectED 412 * Set the state of the reference structure to closed, and 413 * recycle the suffix. 414 * Start a reference timer. 415 * 416 * RETURNS: Nada 417 * 418 * SIDE EFFECTS: 419 * 420 * NOTES: 421 * This differs from the regular soisdisconnected() in that the latter 422 * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags. 423 * We don't want to set those flags because those flags will cause 424 * a SIGPIPE to be delivered in sosend() and we don't like that. 425 * If anyone else is sleeping on this socket, wake 'em up. 426 */ 427 void 428 tp_soisdisconnected(tpcb) 429 register struct tp_pcb *tpcb; 430 { 431 register struct socket *so = tpcb->tp_sock; 432 433 soisdisconnecting(so); 434 so->so_state &= ~SS_CANTSENDMORE; 435 IFPERF(sototpcb(so)) 436 register struct tp_pcb *ttpcb = sototpcb(so); 437 u_int fsufx, lsufx; 438 439 /* CHOKE */ 440 bcopy ((caddr_t)ttpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) ); 441 bcopy ((caddr_t)ttpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) ); 442 443 tpmeas(ttpcb->tp_lref, TPtime_close, 444 &time, &lsufx, &fsufx, ttpcb->tp_fref); 445 tpcb->tp_perf_on = 0; /* turn perf off */ 446 ENDPERF 447 448 tpcb->tp_refp->tpr_state = REF_FROZEN; 449 tp_recycle_tsuffix( tpcb ); 450 tp_etimeout(tpcb->tp_refp, TM_reference, 0,0,0, (int)tpcb->tp_refer_ticks); 451 } 452 453 int tp_maxrefopen; /* highest reference # of the set of open tp connections */ 454 455 /* 456 * NAME: tp_freeref() 457 * 458 * CALLED FROM: 459 * tp.trans when the reference timer goes off, and 460 * from tp_attach() and tp_detach() when a tpcb is partially set up but not 461 * set up enough to have a ref timer set for it, and it's discarded 462 * due to some sort of error or an early close() 463 * 464 * FUNCTION and ARGUMENTS: 465 * Frees the reference represented by (r) for re-use. 466 * 467 * RETURNS: Nothing 468 * 469 * SIDE EFFECTS: 470 * 471 * NOTES: better be called at clock priority !!!!! 472 */ 473 void 474 tp_freeref(r) 475 register struct tp_ref *r; 476 { 477 IFDEBUG(D_TIMER) 478 printf("tp_freeref called for ref %d maxrefopen %d\n", 479 r - tp_ref, tp_maxrefopen); 480 ENDDEBUG 481 IFTRACE(D_TIMER) 482 tptrace(TPPTmisc, "tp_freeref ref tp_maxrefopen", 483 r - tp_ref, tp_maxrefopen, 0, 0); 484 ENDTRACE 485 r->tpr_state = REF_FREE; 486 IFDEBUG(D_CONN) 487 printf("tp_freeref: CLEARING tpr_pcb 0x%x\n", r->tpr_pcb); 488 ENDDEBUG 489 r->tpr_pcb = (struct tp_pcb *)0; 490 491 r = &tp_ref[tp_maxrefopen]; 492 493 while( tp_maxrefopen > 0 ) { 494 if(r->tpr_state ) 495 break; 496 tp_maxrefopen--; 497 r--; 498 } 499 IFDEBUG(D_TIMER) 500 printf("tp_freeref ends w/ maxrefopen %d\n", tp_maxrefopen); 501 ENDDEBUG 502 } 503 504 /* 505 * NAME: tp_getref() 506 * 507 * CALLED FROM: 508 * tp_attach() 509 * 510 * FUNCTION and ARGUMENTS: 511 * obtains the next free reference and allocates the appropriate 512 * ref structure, links that structure to (tpcb) 513 * 514 * RETURN VALUE: 515 * a reference number 516 * or TP_ENOREF 517 * 518 * SIDE EFFECTS: 519 * 520 * NOTES: 521 */ 522 static RefNum 523 tp_getref(tpcb) 524 register struct tp_pcb *tpcb; 525 { 526 register struct tp_ref *r = tp_ref; 527 register int i=1; 528 529 r++; /* tp_ref[0] is never used */ 530 531 /* REF_FREE is zero */ 532 while( r->tpr_state ) { 533 r++; 534 if ( i == N_TPREF ) { 535 return TP_ENOREF; 536 } 537 i++; 538 } 539 r->tpr_state = REF_OPENING; 540 if (tp_maxrefopen < i) 541 tp_maxrefopen = i; 542 r->tpr_pcb = tpcb; 543 tpcb->tp_refp = r; 544 545 return i; 546 } 547 548 /* 549 * NAME: tp_attach() 550 * 551 * CALLED FROM: 552 * tp_usrreq, PRU_ATTACH 553 * 554 * FUNCTION and ARGUMENTS: 555 * given a socket (so) and a protocol family (dom), allocate a tpcb 556 * and ref structure, initialize everything in the structures that 557 * needs to be initialized. 558 * 559 * RETURN VALUE: 560 * 0 ok 561 * EINVAL if DEBUG(X) in is on and a disaster has occurred 562 * ENOPROTOOPT if TP hasn't been configured or if the 563 * socket wasn't created with tp as its protocol 564 * EISCONN if this socket is already part of a connection 565 * ETOOMANYREFS if ran out of tp reference numbers. 566 * E* whatever error is returned from soreserve() 567 * for from the network-layer pcb allocation routine 568 * 569 * SIDE EFFECTS: 570 * 571 * NOTES: 572 */ 573 tp_attach(so, dom) 574 struct socket *so; 575 int dom; 576 { 577 register struct tp_pcb *tpcb; 578 int error; 579 int protocol = so->so_proto->pr_protocol; 580 extern struct tp_conn_param tp_conn_param[]; 581 582 IFDEBUG(D_CONN) 583 printf("tp_attach:dom 0x%x so 0x%x ", dom, so); 584 ENDDEBUG 585 IFTRACE(D_CONN) 586 tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0); 587 ENDTRACE 588 if ( ! tp_param.tpp_configed ) { 589 error = ENOPROTOOPT; /* protocol not available */ 590 goto bad2; 591 } 592 593 if (so->so_pcb != NULL) { 594 return EISCONN; /* socket already part of a connection*/ 595 } 596 597 error = soreserve(so, TP_SOCKBUFSIZE, TP_SOCKBUFSIZE); 598 /* later an ioctl will allow reallocation IF still in closed state */ 599 600 if (error) 601 goto bad2; 602 603 MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT); 604 if (tpcb == NULL) { 605 error = ENOBUFS; 606 goto bad2; 607 } 608 bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) ); 609 610 if ( ((tpcb->tp_lref = tp_getref(tpcb)) & TP_ENOREF) != 0 ) { 611 error = ETOOMANYREFS; 612 goto bad3; 613 } 614 tpcb->tp_sock = so; 615 tpcb->tp_domain = dom; 616 if (protocol<ISOPROTO_TP4) { 617 tpcb->tp_netservice = ISO_CONS; 618 tpcb->tp_snduna = (SeqNum) -1;/* kludge so the pseudo-ack from the CR/CC 619 * will generate correct fake-ack values 620 */ 621 } else { 622 tpcb->tp_netservice = (dom== AF_INET)?IN_CLNS:ISO_CLNS; 623 /* the default */ 624 } 625 tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice]; 626 627 tpcb->tp_cong_win = 1; 628 tpcb->tp_state = TP_CLOSED; 629 tpcb->tp_vers = TP_VERSION; 630 631 /* Spec says default is 128 octets, 632 * that is, if the tpdusize argument never appears, use 128. 633 * As the initiator, we will always "propose" the 2048 634 * size, that is, we will put this argument in the CR 635 * always, but accept what the other side sends on the CC. 636 * If the initiator sends us something larger on a CR, 637 * we'll respond w/ this. 638 * Our maximum is 4096. See tp_chksum.c comments. 639 */ 640 tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize; 641 642 tpcb->tp_seqmask = TP_NML_FMT_MASK; 643 tpcb->tp_seqbit = TP_NML_FMT_BIT; 644 tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; 645 tpcb->tp_sndhiwat = (SeqNum) - 1; /* a kludge but it works */ 646 tpcb->tp_s_subseq = 0; 647 648 /* attach to a network-layer protoswitch */ 649 /* new way */ 650 tpcb->tp_nlproto = & nl_protosw[tpcb->tp_netservice]; 651 ASSERT( tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain); 652 #ifdef notdef 653 /* OLD WAY */ 654 /* TODO: properly, this search would be on the basis of 655 * domain,netservice or just netservice only (if you have 656 * IN_CLNS, ISO_CLNS, and ISO_CONS) 657 */ 658 tpcb->tp_nlproto = nl_protosw; 659 while(tpcb->tp_nlproto->nlp_afamily != tpcb->tp_domain ) { 660 if( tpcb->tp_nlproto->nlp_afamily == 0 ) { 661 error = EAFNOSUPPORT; 662 goto bad4; 663 } 664 tpcb->tp_nlproto ++; 665 } 666 #endif notdef 667 668 /* xx_pcballoc sets so_pcb */ 669 if ( error = (tpcb->tp_nlproto->nlp_pcballoc) ( 670 so, tpcb->tp_nlproto->nlp_pcblist ) ) { 671 goto bad4; 672 } 673 674 if( dom == AF_INET ) 675 sotoinpcb(so)->inp_ppcb = (caddr_t) tpcb; 676 /* nothing to do for iso case */ 677 678 tpcb->tp_npcb = (caddr_t) so->so_pcb; 679 so->so_tpcb = (caddr_t) tpcb; 680 681 return 0; 682 683 bad4: 684 IFDEBUG(D_CONN) 685 printf("BAD4 in tp_attach, so 0x%x\n", so); 686 ENDDEBUG 687 tp_freeref(tpcb->tp_refp); 688 689 bad3: 690 IFDEBUG(D_CONN) 691 printf("BAD3 in tp_attach, so 0x%x\n", so); 692 ENDDEBUG 693 694 free((caddr_t)tpcb, M_PCB); /* never a cluster */ 695 696 bad2: 697 IFDEBUG(D_CONN) 698 printf("BAD2 in tp_attach, so 0x%x\n", so); 699 ENDDEBUG 700 so->so_pcb = 0; 701 so->so_tpcb = 0; 702 sofree(so); 703 704 /*bad:*/ 705 IFDEBUG(D_CONN) 706 printf("BAD in tp_attach, so 0x%x\n", so); 707 ENDDEBUG 708 return error; 709 } 710 711 /* 712 * NAME: tp_detach() 713 * 714 * CALLED FROM: 715 * tp.trans, on behalf of a user close request 716 * and when the reference timer goes off 717 * (if the disconnect was initiated by the protocol entity 718 * rather than by the user) 719 * 720 * FUNCTION and ARGUMENTS: 721 * remove the tpcb structure from the list of active or 722 * partially active connections, recycle all the mbufs 723 * associated with the pcb, ref structure, sockbufs, etc. 724 * Only free the ref structure if you know that a ref timer 725 * wasn't set for this tpcb. 726 * 727 * RETURNS: Nada 728 * 729 * SIDE EFFECTS: 730 * 731 * NOTES: 732 * tp_soisdisconnected() was already when this is called 733 */ 734 void 735 tp_detach(tpcb) 736 register struct tp_pcb *tpcb; 737 { 738 void tp_freeref(); 739 register struct socket *so = tpcb->tp_sock; 740 741 IFDEBUG(D_CONN) 742 printf("tp_detach(tpcb 0x%x, so 0x%x)\n", 743 tpcb,so); 744 ENDDEBUG 745 IFTRACE(D_CONN) 746 tptraceTPCB(TPPTmisc, "tp_detach tpcb so lsufx", 747 tpcb, so, *(u_short *)(tpcb->tp_lsuffix), 0); 748 ENDTRACE 749 750 if (so->so_head) { 751 if (!soqremque(so, 0) && !soqremque(so, 1)) 752 panic("sofree dq"); 753 so->so_head = 0; 754 } 755 756 IFDEBUG(D_CONN) 757 printf("tp_detach(freeing RTC list snduna 0x%x rcvnxt 0x%x)\n", 758 tpcb->tp_snduna_rtc, 759 tpcb->tp_rcvnxt_rtc); 760 ENDDEBUG 761 762 #define FREE_RTC_LIST(XXX)\ 763 { register struct tp_rtc *xxr = XXX, *xxs; while (xxr) {\ 764 xxs = xxr->tprt_next;\ 765 m_freem( xxr->tprt_data );\ 766 m_free( dtom(xxr) ); xxr = xxs; }\ 767 XXX = (struct tp_rtc *)0;\ 768 } 769 770 FREE_RTC_LIST( tpcb->tp_snduna_rtc ); 771 tpcb->tp_sndhiwat_rtc = (struct tp_rtc *)0; 772 773 FREE_RTC_LIST( tpcb->tp_rcvnxt_rtc ); 774 775 #undef FREE_RTC_LIST 776 777 IFDEBUG(D_CONN) 778 printf("calling (...nlproto->...)(0x%x, so 0x%x)\n", 779 so->so_pcb, so); 780 printf("so 0x%x so_head 0x%x, qlen %d q0len %d qlimit %d\n", 781 so, so->so_head, 782 so->so_q0len, so->so_qlen, so->so_qlimit); 783 ENDDEBUG 784 785 if ( tpcb->tp_flags & (TPF_DISC_DATA_OUT | TPF_CONN_DATA_OUT ) ) { 786 ASSERT( so->so_snd.sb_cc != 0 ); 787 IFDEBUG(D_CONN) 788 printf( 789 "detach, flags 0x%x doing sbdrop on so_snd, mb 0x%x cc 0x%x\n", 790 tpcb->tp_flags, so->so_snd.sb_mb, so->so_snd.sb_cc); 791 dump_mbuf( so->so_snd.sb_mb, "detach so snd: \n"); 792 ENDDEBUG 793 if ( so->so_snd.sb_cc != 0 ) 794 sbflush(&so->so_snd); 795 tpcb->tp_flags &= ~(TPF_CONN_DATA_OUT | TPF_DISC_DATA_OUT); 796 } 797 if ( tpcb->tp_flags & (TPF_DISC_DATA_IN | TPF_CONN_DATA_IN ) ) { 798 ASSERT( tpcb->tp_Xrcv.sb_cc != 0 ); 799 IFDEBUG(D_CONN) 800 printf( 801 "detach, flags 0x%x doing sbdrop on tp_Xrcv, mb 0x%x cc 0x%x\n", 802 tpcb->tp_flags, tpcb->tp_Xrcv.sb_mb, tpcb->tp_Xrcv.sb_cc); 803 dump_mbuf( tpcb->tp_Xrcv.sb_mb, "detach Xrcv: \n"); 804 ENDDEBUG 805 if( tpcb->tp_Xrcv.sb_cc != 0 ) 806 sbdrop(&tpcb->tp_Xrcv, (int)tpcb->tp_Xrcv.sb_cc); 807 tpcb->tp_flags &= ~(TPF_CONN_DATA_IN | TPF_DISC_DATA_IN); 808 } 809 810 IFDEBUG(D_CONN) 811 printf("so_snd at 0x%x so_rcv at 0x%x\n", &so->so_snd, &so->so_rcv); 812 dump_mbuf(so->so_snd.sb_mb, "so_snd at detach "); 813 printf("about to call LL detach, nlproto 0x%x, nl_detach 0x%x\n", 814 tpcb->tp_nlproto, tpcb->tp_nlproto->nlp_pcbdetach); 815 ENDDEBUG 816 817 818 819 (tpcb->tp_nlproto->nlp_pcbdetach)((struct inpcb *)so->so_pcb); 820 /* does an sofree(so) */ 821 822 IFDEBUG(D_CONN) 823 printf("after xxx_pcbdetach\n"); 824 ENDDEBUG 825 826 if( tpcb->tp_refp->tpr_state == REF_OPENING ) { 827 /* no connection existed here so no reference timer will be called */ 828 IFDEBUG(D_CONN) 829 printf("SETTING ref %d, 0x%x to REF_FREE\n", tpcb->tp_lref, 830 tpcb->tp_refp - &tp_ref[0]); 831 ENDDEBUG 832 833 tp_freeref(tpcb->tp_refp); 834 } 835 836 if (tpcb->tp_Xsnd.sb_mb) { 837 printf("Unsent Xdata on detach; would panic"); 838 sbflush(&tpcb->tp_Xsnd); 839 } 840 so->so_tpcb = (caddr_t)0; 841 842 /* 843 * Get rid of the cluster mbuf allocated for performance measurements, if 844 * there is one. Note that tpcb->tp_perf_on says nothing about whether or 845 * not a cluster mbuf was allocated, so you have to check for a pointer 846 * to one (that is, we need the TP_PERF_MEASs around the following section 847 * of code, not the IFPERFs) 848 */ 849 #ifdef TP_PERF_MEAS 850 if(tpcb->tp_p_mbuf) { 851 register struct mbuf *m = tpcb->tp_p_mbuf; 852 struct mbuf *n; 853 IFDEBUG(D_PERF_MEAS) 854 printf("freeing tp_p_meas 0x%x ", tpcb->tp_p_meas); 855 ENDDEBUG 856 do { 857 MFREE(m, n); 858 m = n; 859 } while (n); 860 tpcb->tp_p_meas = 0; 861 tpcb->tp_p_mbuf = 0; 862 } 863 #endif TP_PERF_MEAS 864 865 IFDEBUG(D_CONN) 866 printf( "end of detach, NOT single, tpcb 0x%x\n", tpcb); 867 ENDDEBUG 868 /* free((caddr_t)tpcb, M_PCB); WHere to put this ? */ 869 } 870