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