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.4 (Berkeley) 09/22/89 * 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_timerinit(); 359 bzero((caddr_t)&tp_stat, sizeof(struct tp_stat)); 360 return 0; 361 } 362 363 /* 364 * NAME: tp_soisdisconnecting() 365 * 366 * CALLED FROM: 367 * tp.trans 368 * 369 * FUNCTION and ARGUMENTS: 370 * Set state of the socket (so) to reflect that fact that we're disconnectING 371 * 372 * RETURNS: Nada 373 * 374 * SIDE EFFECTS: 375 * 376 * NOTES: 377 * This differs from the regular soisdisconnecting() in that the latter 378 * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags. 379 * We don't want to set those flags because those flags will cause 380 * a SIGPIPE to be delivered in sosend() and we don't like that. 381 * If anyone else is sleeping on this socket, wake 'em up. 382 */ 383 void 384 tp_soisdisconnecting(so) 385 register struct socket *so; 386 { 387 soisdisconnecting(so); 388 so->so_state &= ~SS_CANTSENDMORE; 389 IFPERF(sototpcb(so)) 390 register struct tp_pcb *tpcb = sototpcb(so); 391 u_int fsufx, lsufx; 392 393 bcopy ((caddr_t)tpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) ); 394 bcopy ((caddr_t)tpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) ); 395 396 tpmeas(tpcb->tp_lref, TPtime_close, &time, fsufx, lsufx, tpcb->tp_fref); 397 tpcb->tp_perf_on = 0; /* turn perf off */ 398 ENDPERF 399 } 400 401 402 /* 403 * NAME: tp_soisdisconnected() 404 * 405 * CALLED FROM: 406 * tp.trans 407 * 408 * FUNCTION and ARGUMENTS: 409 * Set state of the socket (so) to reflect that fact that we're disconnectED 410 * Set the state of the reference structure to closed, and 411 * recycle the suffix. 412 * Start a reference timer. 413 * 414 * RETURNS: Nada 415 * 416 * SIDE EFFECTS: 417 * 418 * NOTES: 419 * This differs from the regular soisdisconnected() in that the latter 420 * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags. 421 * We don't want to set those flags because those flags will cause 422 * a SIGPIPE to be delivered in sosend() and we don't like that. 423 * If anyone else is sleeping on this socket, wake 'em up. 424 */ 425 void 426 tp_soisdisconnected(tpcb) 427 register struct tp_pcb *tpcb; 428 { 429 register struct socket *so = tpcb->tp_sock; 430 431 soisdisconnecting(so); 432 so->so_state &= ~SS_CANTSENDMORE; 433 IFPERF(sototpcb(so)) 434 register struct tp_pcb *ttpcb = sototpcb(so); 435 u_int fsufx, lsufx; 436 437 /* CHOKE */ 438 bcopy ((caddr_t)ttpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) ); 439 bcopy ((caddr_t)ttpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) ); 440 441 tpmeas(ttpcb->tp_lref, TPtime_close, 442 &time, &lsufx, &fsufx, ttpcb->tp_fref); 443 tpcb->tp_perf_on = 0; /* turn perf off */ 444 ENDPERF 445 446 tpcb->tp_refp->tpr_state = REF_FROZEN; 447 tp_recycle_tsuffix( tpcb ); 448 tp_etimeout(tpcb->tp_refp, TM_reference, 0,0,0, (int)tpcb->tp_refer_ticks); 449 } 450 451 int tp_maxrefopen; /* highest reference # of the set of open tp connections */ 452 453 /* 454 * NAME: tp_freeref() 455 * 456 * CALLED FROM: 457 * tp.trans when the reference timer goes off, and 458 * from tp_attach() and tp_detach() when a tpcb is partially set up but not 459 * set up enough to have a ref timer set for it, and it's discarded 460 * due to some sort of error or an early close() 461 * 462 * FUNCTION and ARGUMENTS: 463 * Frees the reference represented by (r) for re-use. 464 * 465 * RETURNS: Nothing 466 * 467 * SIDE EFFECTS: 468 * 469 * NOTES: better be called at clock priority !!!!! 470 */ 471 void 472 tp_freeref(r) 473 register struct tp_ref *r; 474 { 475 IFDEBUG(D_TIMER) 476 printf("tp_freeref called for ref %d maxrefopen %d\n", 477 r - tp_ref, tp_maxrefopen); 478 ENDDEBUG 479 IFTRACE(D_TIMER) 480 tptrace(TPPTmisc, "tp_freeref ref tp_maxrefopen", 481 r - tp_ref, tp_maxrefopen, 0, 0); 482 ENDTRACE 483 r->tpr_state = REF_FREE; 484 IFDEBUG(D_CONN) 485 printf("tp_freeref: CLEARING tpr_pcb 0x%x\n", r->tpr_pcb); 486 ENDDEBUG 487 r->tpr_pcb = (struct tp_pcb *)0; 488 489 r = &tp_ref[tp_maxrefopen]; 490 491 while( tp_maxrefopen > 0 ) { 492 if(r->tpr_state ) 493 break; 494 tp_maxrefopen--; 495 r--; 496 } 497 IFDEBUG(D_TIMER) 498 printf("tp_freeref ends w/ maxrefopen %d\n", tp_maxrefopen); 499 ENDDEBUG 500 } 501 502 /* 503 * NAME: tp_getref() 504 * 505 * CALLED FROM: 506 * tp_attach() 507 * 508 * FUNCTION and ARGUMENTS: 509 * obtains the next free reference and allocates the appropriate 510 * ref structure, links that structure to (tpcb) 511 * 512 * RETURN VALUE: 513 * a reference number 514 * or TP_ENOREF 515 * 516 * SIDE EFFECTS: 517 * 518 * NOTES: 519 */ 520 static RefNum 521 tp_getref(tpcb) 522 register struct tp_pcb *tpcb; 523 { 524 register struct tp_ref *r = tp_ref; 525 register int i=1; 526 527 r++; /* tp_ref[0] is never used */ 528 529 /* REF_FREE is zero */ 530 while( r->tpr_state ) { 531 r++; 532 if ( i == N_TPREF ) { 533 return TP_ENOREF; 534 } 535 i++; 536 } 537 r->tpr_state = REF_OPENING; 538 if (tp_maxrefopen < i) 539 tp_maxrefopen = i; 540 r->tpr_pcb = tpcb; 541 tpcb->tp_refp = r; 542 543 return i; 544 } 545 546 /* 547 * NAME: tp_attach() 548 * 549 * CALLED FROM: 550 * tp_usrreq, PRU_ATTACH 551 * 552 * FUNCTION and ARGUMENTS: 553 * given a socket (so) and a protocol family (dom), allocate a tpcb 554 * and ref structure, initialize everything in the structures that 555 * needs to be initialized. 556 * 557 * RETURN VALUE: 558 * 0 ok 559 * EINVAL if DEBUG(X) in is on and a disaster has occurred 560 * ENOPROTOOPT if TP hasn't been configured or if the 561 * socket wasn't created with tp as its protocol 562 * EISCONN if this socket is already part of a connection 563 * ETOOMANYREFS if ran out of tp reference numbers. 564 * E* whatever error is returned from soreserve() 565 * for from the network-layer pcb allocation routine 566 * 567 * SIDE EFFECTS: 568 * 569 * NOTES: 570 */ 571 tp_attach(so, dom) 572 struct socket *so; 573 int dom; 574 { 575 register struct tp_pcb *tpcb; 576 int error; 577 int protocol = so->so_proto->pr_protocol; 578 extern struct tp_conn_param tp_conn_param[]; 579 580 IFDEBUG(D_CONN) 581 printf("tp_attach:dom 0x%x so 0x%x ", dom, so); 582 ENDDEBUG 583 IFTRACE(D_CONN) 584 tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0); 585 ENDTRACE 586 if ( ! tp_param.tpp_configed ) { 587 error = ENOPROTOOPT; /* protocol not available */ 588 goto bad2; 589 } 590 591 if (so->so_pcb != NULL) { 592 return EISCONN; /* socket already part of a connection*/ 593 } 594 595 error = soreserve(so, TP_SOCKBUFSIZE, TP_SOCKBUFSIZE); 596 /* later an ioctl will allow reallocation IF still in closed state */ 597 598 if (error) 599 goto bad2; 600 601 MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT); 602 if (tpcb == NULL) { 603 error = ENOBUFS; 604 goto bad2; 605 } 606 bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) ); 607 608 if ( ((tpcb->tp_lref = tp_getref(tpcb)) & TP_ENOREF) != 0 ) { 609 error = ETOOMANYREFS; 610 goto bad3; 611 } 612 tpcb->tp_sock = so; 613 tpcb->tp_domain = dom; 614 if (protocol<ISOPROTO_TP4) { 615 tpcb->tp_netservice = ISO_CONS; 616 tpcb->tp_snduna = (SeqNum) -1;/* kludge so the pseudo-ack from the CR/CC 617 * will generate correct fake-ack values 618 */ 619 } else { 620 tpcb->tp_netservice = (dom== AF_INET)?IN_CLNS:ISO_CLNS; 621 /* the default */ 622 } 623 tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice]; 624 625 tpcb->tp_cong_win = 1; 626 tpcb->tp_state = TP_CLOSED; 627 tpcb->tp_vers = TP_VERSION; 628 629 /* Spec says default is 128 octets, 630 * that is, if the tpdusize argument never appears, use 128. 631 * As the initiator, we will always "propose" the 2048 632 * size, that is, we will put this argument in the CR 633 * always, but accept what the other side sends on the CC. 634 * If the initiator sends us something larger on a CR, 635 * we'll respond w/ this. 636 * Our maximum is 4096. See tp_chksum.c comments. 637 */ 638 tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize; 639 640 tpcb->tp_seqmask = TP_NML_FMT_MASK; 641 tpcb->tp_seqbit = TP_NML_FMT_BIT; 642 tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; 643 tpcb->tp_sndhiwat = (SeqNum) - 1; /* a kludge but it works */ 644 tpcb->tp_s_subseq = 0; 645 646 /* attach to a network-layer protoswitch */ 647 /* new way */ 648 tpcb->tp_nlproto = & nl_protosw[tpcb->tp_netservice]; 649 ASSERT( tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain); 650 #ifdef notdef 651 /* OLD WAY */ 652 /* TODO: properly, this search would be on the basis of 653 * domain,netservice or just netservice only (if you have 654 * IN_CLNS, ISO_CLNS, and ISO_CONS) 655 */ 656 tpcb->tp_nlproto = nl_protosw; 657 while(tpcb->tp_nlproto->nlp_afamily != tpcb->tp_domain ) { 658 if( tpcb->tp_nlproto->nlp_afamily == 0 ) { 659 error = EAFNOSUPPORT; 660 goto bad4; 661 } 662 tpcb->tp_nlproto ++; 663 } 664 #endif notdef 665 666 /* xx_pcballoc sets so_pcb */ 667 if ( error = (tpcb->tp_nlproto->nlp_pcballoc) ( 668 so, tpcb->tp_nlproto->nlp_pcblist ) ) { 669 goto bad4; 670 } 671 672 if( dom == AF_INET ) 673 sotoinpcb(so)->inp_ppcb = (caddr_t) tpcb; 674 /* nothing to do for iso case */ 675 676 tpcb->tp_npcb = (caddr_t) so->so_pcb; 677 so->so_tpcb = (caddr_t) tpcb; 678 679 return 0; 680 681 bad4: 682 IFDEBUG(D_CONN) 683 printf("BAD4 in tp_attach, so 0x%x\n", so); 684 ENDDEBUG 685 tp_freeref(tpcb->tp_refp); 686 687 bad3: 688 IFDEBUG(D_CONN) 689 printf("BAD3 in tp_attach, so 0x%x\n", so); 690 ENDDEBUG 691 692 free((caddr_t)tpcb, M_PCB); /* never a cluster */ 693 694 bad2: 695 IFDEBUG(D_CONN) 696 printf("BAD2 in tp_attach, so 0x%x\n", so); 697 ENDDEBUG 698 so->so_pcb = 0; 699 so->so_tpcb = 0; 700 sofree(so); 701 702 /*bad:*/ 703 IFDEBUG(D_CONN) 704 printf("BAD in tp_attach, so 0x%x\n", so); 705 ENDDEBUG 706 return error; 707 } 708 709 /* 710 * NAME: tp_detach() 711 * 712 * CALLED FROM: 713 * tp.trans, on behalf of a user close request 714 * and when the reference timer goes off 715 * (if the disconnect was initiated by the protocol entity 716 * rather than by the user) 717 * 718 * FUNCTION and ARGUMENTS: 719 * remove the tpcb structure from the list of active or 720 * partially active connections, recycle all the mbufs 721 * associated with the pcb, ref structure, sockbufs, etc. 722 * Only free the ref structure if you know that a ref timer 723 * wasn't set for this tpcb. 724 * 725 * RETURNS: Nada 726 * 727 * SIDE EFFECTS: 728 * 729 * NOTES: 730 * tp_soisdisconnected() was already when this is called 731 */ 732 void 733 tp_detach(tpcb) 734 register struct tp_pcb *tpcb; 735 { 736 void tp_freeref(); 737 register struct socket *so = tpcb->tp_sock; 738 739 IFDEBUG(D_CONN) 740 printf("tp_detach(tpcb 0x%x, so 0x%x)\n", 741 tpcb,so); 742 ENDDEBUG 743 IFTRACE(D_CONN) 744 tptraceTPCB(TPPTmisc, "tp_detach tpcb so lsufx", 745 tpcb, so, *(u_short *)(tpcb->tp_lsuffix), 0); 746 ENDTRACE 747 748 if (so->so_head) { 749 if (!soqremque(so, 0) && !soqremque(so, 1)) 750 panic("sofree dq"); 751 so->so_head = 0; 752 } 753 754 IFDEBUG(D_CONN) 755 printf("tp_detach(freeing RTC list snduna 0x%x rcvnxt 0x%x)\n", 756 tpcb->tp_snduna_rtc, 757 tpcb->tp_rcvnxt_rtc); 758 ENDDEBUG 759 760 #define FREE_RTC_LIST(XXX)\ 761 { register struct tp_rtc *xxr = XXX, *xxs; while (xxr) {\ 762 xxs = xxr->tprt_next;\ 763 m_freem( xxr->tprt_data );\ 764 m_free( dtom(xxr) ); xxr = xxs; }\ 765 XXX = (struct tp_rtc *)0;\ 766 } 767 768 FREE_RTC_LIST( tpcb->tp_snduna_rtc ); 769 tpcb->tp_sndhiwat_rtc = (struct tp_rtc *)0; 770 771 FREE_RTC_LIST( tpcb->tp_rcvnxt_rtc ); 772 773 #undef FREE_RTC_LIST 774 775 IFDEBUG(D_CONN) 776 printf("calling (...nlproto->...)(0x%x, so 0x%x)\n", 777 so->so_pcb, so); 778 printf("so 0x%x so_head 0x%x, qlen %d q0len %d qlimit %d\n", 779 so, so->so_head, 780 so->so_q0len, so->so_qlen, so->so_qlimit); 781 ENDDEBUG 782 783 if ( tpcb->tp_flags & (TPF_DISC_DATA_OUT | TPF_CONN_DATA_OUT ) ) { 784 ASSERT( so->so_snd.sb_cc != 0 ); 785 IFDEBUG(D_CONN) 786 printf( 787 "detach, flags 0x%x doing sbdrop on so_snd, mb 0x%x cc 0x%x\n", 788 tpcb->tp_flags, so->so_snd.sb_mb, so->so_snd.sb_cc); 789 dump_mbuf( so->so_snd.sb_mb, "detach so snd: \n"); 790 ENDDEBUG 791 if ( so->so_snd.sb_cc != 0 ) 792 sbflush(&so->so_snd); 793 tpcb->tp_flags &= ~(TPF_CONN_DATA_OUT | TPF_DISC_DATA_OUT); 794 } 795 if ( tpcb->tp_flags & (TPF_DISC_DATA_IN | TPF_CONN_DATA_IN ) ) { 796 ASSERT( tpcb->tp_Xrcv.sb_cc != 0 ); 797 IFDEBUG(D_CONN) 798 printf( 799 "detach, flags 0x%x doing sbdrop on tp_Xrcv, mb 0x%x cc 0x%x\n", 800 tpcb->tp_flags, tpcb->tp_Xrcv.sb_mb, tpcb->tp_Xrcv.sb_cc); 801 dump_mbuf( tpcb->tp_Xrcv.sb_mb, "detach Xrcv: \n"); 802 ENDDEBUG 803 if( tpcb->tp_Xrcv.sb_cc != 0 ) 804 sbdrop(&tpcb->tp_Xrcv, (int)tpcb->tp_Xrcv.sb_cc); 805 tpcb->tp_flags &= ~(TPF_CONN_DATA_IN | TPF_DISC_DATA_IN); 806 } 807 808 IFDEBUG(D_CONN) 809 printf("so_snd at 0x%x so_rcv at 0x%x\n", &so->so_snd, &so->so_rcv); 810 dump_mbuf(so->so_snd.sb_mb, "so_snd at detach "); 811 printf("about to call LL detach, nlproto 0x%x, nl_detach 0x%x\n", 812 tpcb->tp_nlproto, tpcb->tp_nlproto->nlp_pcbdetach); 813 ENDDEBUG 814 815 816 817 (tpcb->tp_nlproto->nlp_pcbdetach)((struct inpcb *)so->so_pcb); 818 /* does an sofree(so) */ 819 820 IFDEBUG(D_CONN) 821 printf("after xxx_pcbdetach\n"); 822 ENDDEBUG 823 824 if( tpcb->tp_refp->tpr_state == REF_OPENING ) { 825 /* no connection existed here so no reference timer will be called */ 826 IFDEBUG(D_CONN) 827 printf("SETTING ref %d, 0x%x to REF_FREE\n", tpcb->tp_lref, 828 tpcb->tp_refp - &tp_ref[0]); 829 ENDDEBUG 830 831 tp_freeref(tpcb->tp_refp); 832 } 833 834 if (tpcb->tp_Xsnd.sb_mb) { 835 printf("Unsent Xdata on detach; would panic"); 836 sbflush(&tpcb->tp_Xsnd); 837 } 838 so->so_tpcb = (caddr_t)0; 839 840 /* 841 * Get rid of the cluster mbuf allocated for performance measurements, if 842 * there is one. Note that tpcb->tp_perf_on says nothing about whether or 843 * not a cluster mbuf was allocated, so you have to check for a pointer 844 * to one (that is, we need the TP_PERF_MEASs around the following section 845 * of code, not the IFPERFs) 846 */ 847 #ifdef TP_PERF_MEAS 848 if(tpcb->tp_p_mbuf) { 849 register struct mbuf *m = tpcb->tp_p_mbuf; 850 struct mbuf *n; 851 IFDEBUG(D_PERF_MEAS) 852 printf("freeing tp_p_meas 0x%x ", tpcb->tp_p_meas); 853 ENDDEBUG 854 do { 855 MFREE(m, n); 856 m = n; 857 } while (n); 858 tpcb->tp_p_meas = 0; 859 tpcb->tp_p_mbuf = 0; 860 } 861 #endif TP_PERF_MEAS 862 863 IFDEBUG(D_CONN) 864 printf( "end of detach, NOT single, tpcb 0x%x\n", tpcb); 865 ENDDEBUG 866 /* free((caddr_t)tpcb, M_PCB); WHere to put this ? */ 867 } 868