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