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