|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /*- ! 26: * Copyright (c) 1991, 1993 ! 27: * The Regents of the University of California. All rights reserved. ! 28: * ! 29: * Redistribution and use in source and binary forms, with or without ! 30: * modification, are permitted provided that the following conditions ! 31: * are met: ! 32: * 1. Redistributions of source code must retain the above copyright ! 33: * notice, this list of conditions and the following disclaimer. ! 34: * 2. Redistributions in binary form must reproduce the above copyright ! 35: * notice, this list of conditions and the following disclaimer in the ! 36: * documentation and/or other materials provided with the distribution. ! 37: * 3. All advertising materials mentioning features or use of this software ! 38: * must display the following acknowledgement: ! 39: * This product includes software developed by the University of ! 40: * California, Berkeley and its contributors. ! 41: * 4. Neither the name of the University nor the names of its contributors ! 42: * may be used to endorse or promote products derived from this software ! 43: * without specific prior written permission. ! 44: * ! 45: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 46: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 47: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 48: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 49: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 50: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 51: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 52: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 53: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 54: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 55: * SUCH DAMAGE. ! 56: * ! 57: * @(#)tp_pcb.c 8.1 (Berkeley) 6/10/93 ! 58: */ ! 59: ! 60: /*********************************************************** ! 61: Copyright IBM Corporation 1987 ! 62: ! 63: All Rights Reserved ! 64: ! 65: Permission to use, copy, modify, and distribute this software and its ! 66: documentation for any purpose and without fee is hereby granted, ! 67: provided that the above copyright notice appear in all copies and that ! 68: both that copyright notice and this permission notice appear in ! 69: supporting documentation, and that the name of IBM not be ! 70: used in advertising or publicity pertaining to distribution of the ! 71: software without specific, written prior permission. ! 72: ! 73: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 74: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 75: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 76: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 77: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 78: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 79: SOFTWARE. ! 80: ! 81: ******************************************************************/ ! 82: ! 83: /* ! 84: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison ! 85: */ ! 86: /* ! 87: * ARGO TP ! 88: * ! 89: * This is the initialization and cleanup stuff - ! 90: * for the tp machine in general as well as for the individual pcbs. ! 91: * tp_init() is called at system startup. tp_attach() and tp_getref() are ! 92: * called when a socket is created. tp_detach() and tp_freeref() ! 93: * are called during the closing stage and/or when the reference timer ! 94: * goes off. ! 95: * tp_soisdisconnecting() and tp_soisdisconnected() are tp-specific ! 96: * versions of soisconnect* ! 97: * and are called (obviously) during the closing phase. ! 98: * ! 99: */ ! 100: ! 101: #include <sys/param.h> ! 102: #include <sys/systm.h> ! 103: #include <sys/mbuf.h> ! 104: #include <sys/socket.h> ! 105: #include <sys/socketvar.h> ! 106: #include <sys/domain.h> ! 107: #include <sys/protosw.h> ! 108: #include <sys/errno.h> ! 109: #include <sys/time.h> ! 110: ! 111: #include <netiso/argo_debug.h> ! 112: #include <netiso/tp_param.h> ! 113: #include <netiso/tp_timer.h> ! 114: #include <netiso/tp_ip.h> ! 115: #include <netiso/tp_stat.h> ! 116: #include <netiso/tp_pcb.h> ! 117: #include <netiso/tp_tpdu.h> ! 118: #include <netiso/tp_trace.h> ! 119: #include <netiso/tp_meas.h> ! 120: #include <netiso/tp_seq.h> ! 121: #include <netiso/tp_clnp.h> ! 122: ! 123: /* ticks are in units of: ! 124: * 500 nano-fortnights ;-) or ! 125: * 500 ms or ! 126: * 1/2 second ! 127: */ ! 128: ! 129: struct tp_conn_param tp_conn_param[] = { ! 130: /* ISO_CLNS: TP4 CONNECTION LESS */ ! 131: { ! 132: TP_NRETRANS, /* short p_Nretrans; */ ! 133: 20, /* 10 sec */ /* short p_dr_ticks; */ ! 134: ! 135: 20, /* 10 sec */ /* short p_cc_ticks; */ ! 136: 20, /* 10 sec */ /* short p_dt_ticks; */ ! 137: ! 138: 40, /* 20 sec */ /* short p_x_ticks; */ ! 139: 80, /* 40 sec */ /* short p_cr_ticks;*/ ! 140: ! 141: 240, /* 2 min */ /* short p_keepalive_ticks;*/ ! 142: 10, /* 5 sec */ /* short p_sendack_ticks; */ ! 143: ! 144: 600, /* 5 min */ /* short p_ref_ticks; */ ! 145: 360, /* 3 min */ /* short p_inact_ticks; */ ! 146: ! 147: (short) 100, /* short p_lcdtfract */ ! 148: (short) TP_SOCKBUFSIZE, /* short p_winsize */ ! 149: TP_TPDUSIZE, /* u_char p_tpdusize */ ! 150: ! 151: TPACK_WINDOW, /* 4 bits p_ack_strat */ ! 152: TPRX_USE_CW | TPRX_FASTSTART, ! 153: /* 4 bits p_rx_strat*/ ! 154: TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */ ! 155: 1, /* 1 bit xtd format */ ! 156: 1, /* 1 bit xpd service */ ! 157: 1, /* 1 bit use_checksum */ ! 158: 0, /* 1 bit use net xpd */ ! 159: 0, /* 1 bit use rcc */ ! 160: 0, /* 1 bit use efc */ ! 161: 1, /* no disc indications */ ! 162: 0, /* don't change params */ ! 163: ISO_CLNS, /* p_netservice */ ! 164: }, ! 165: /* IN_CLNS: TP4 CONNECTION LESS */ ! 166: { ! 167: TP_NRETRANS, /* short p_Nretrans; */ ! 168: 20, /* 10 sec */ /* short p_dr_ticks; */ ! 169: ! 170: 20, /* 10 sec */ /* short p_cc_ticks; */ ! 171: 20, /* 10 sec */ /* short p_dt_ticks; */ ! 172: ! 173: 40, /* 20 sec */ /* short p_x_ticks; */ ! 174: 80, /* 40 sec */ /* short p_cr_ticks;*/ ! 175: ! 176: 240, /* 2 min */ /* short p_keepalive_ticks;*/ ! 177: 10, /* 5 sec */ /* short p_sendack_ticks; */ ! 178: ! 179: 600, /* 5 min */ /* short p_ref_ticks; */ ! 180: 360, /* 3 min */ /* short p_inact_ticks; */ ! 181: ! 182: (short) 100, /* short p_lcdtfract */ ! 183: (short) TP_SOCKBUFSIZE, /* short p_winsize */ ! 184: TP_TPDUSIZE, /* u_char p_tpdusize */ ! 185: ! 186: TPACK_WINDOW, /* 4 bits p_ack_strat */ ! 187: TPRX_USE_CW | TPRX_FASTSTART, ! 188: /* 4 bits p_rx_strat*/ ! 189: TP_CLASS_4, /* 5 bits p_class */ ! 190: 1, /* 1 bit xtd format */ ! 191: 1, /* 1 bit xpd service */ ! 192: 1, /* 1 bit use_checksum */ ! 193: 0, /* 1 bit use net xpd */ ! 194: 0, /* 1 bit use rcc */ ! 195: 0, /* 1 bit use efc */ ! 196: 1, /* no disc indications */ ! 197: 0, /* don't change params */ ! 198: IN_CLNS, /* p_netservice */ ! 199: }, ! 200: /* ISO_CONS: TP0 CONNECTION MODE */ ! 201: { ! 202: TP_NRETRANS, /* short p_Nretrans; */ ! 203: 0, /* n/a */ /* short p_dr_ticks; */ ! 204: ! 205: 40, /* 20 sec */ /* short p_cc_ticks; */ ! 206: 0, /* n/a */ /* short p_dt_ticks; */ ! 207: ! 208: 0, /* n/a */ /* short p_x_ticks; */ ! 209: 360, /* 3 min */ /* short p_cr_ticks;*/ ! 210: ! 211: 0, /* n/a */ /* short p_keepalive_ticks;*/ ! 212: 0, /* n/a */ /* short p_sendack_ticks; */ ! 213: ! 214: 600, /* for cr/cc to clear *//* short p_ref_ticks; */ ! 215: 0, /* n/a */ /* short p_inact_ticks; */ ! 216: ! 217: /* Use tp4 defaults just in case the user changes ONLY ! 218: * the class ! 219: */ ! 220: (short) 100, /* short p_lcdtfract */ ! 221: (short) TP0_SOCKBUFSIZE, /* short p_winsize */ ! 222: TP0_TPDUSIZE, /* 8 bits p_tpdusize */ ! 223: ! 224: 0, /* 4 bits p_ack_strat */ ! 225: 0, /* 4 bits p_rx_strat*/ ! 226: TP_CLASS_0, /* 5 bits p_class */ ! 227: 0, /* 1 bit xtd format */ ! 228: 0, /* 1 bit xpd service */ ! 229: 0, /* 1 bit use_checksum */ ! 230: 0, /* 1 bit use net xpd */ ! 231: 0, /* 1 bit use rcc */ ! 232: 0, /* 1 bit use efc */ ! 233: 0, /* no disc indications */ ! 234: 0, /* don't change params */ ! 235: ISO_CONS, /* p_netservice */ ! 236: }, ! 237: /* ISO_COSNS: TP4 CONNECTION LESS SERVICE over CONSNS */ ! 238: { ! 239: TP_NRETRANS, /* short p_Nretrans; */ ! 240: 40, /* 20 sec */ /* short p_dr_ticks; */ ! 241: ! 242: 40, /* 20 sec */ /* short p_cc_ticks; */ ! 243: 80, /* 40 sec */ /* short p_dt_ticks; */ ! 244: ! 245: 120, /* 1 min */ /* short p_x_ticks; */ ! 246: 360, /* 3 min */ /* short p_cr_ticks;*/ ! 247: ! 248: 360, /* 3 min */ /* short p_keepalive_ticks;*/ ! 249: 20, /* 10 sec */ /* short p_sendack_ticks; */ ! 250: ! 251: 600, /* 5 min */ /* short p_ref_ticks; */ ! 252: 480, /* 4 min */ /* short p_inact_ticks; */ ! 253: ! 254: (short) 100, /* short p_lcdtfract */ ! 255: (short) TP0_SOCKBUFSIZE, /* short p_winsize */ ! 256: TP0_TPDUSIZE, /* u_char p_tpdusize */ ! 257: ! 258: TPACK_WINDOW, /* 4 bits p_ack_strat */ ! 259: TPRX_USE_CW , /* No fast start */ ! 260: /* 4 bits p_rx_strat*/ ! 261: TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */ ! 262: 0, /* 1 bit xtd format */ ! 263: 1, /* 1 bit xpd service */ ! 264: 1, /* 1 bit use_checksum */ ! 265: 0, /* 1 bit use net xpd */ ! 266: 0, /* 1 bit use rcc */ ! 267: 0, /* 1 bit use efc */ ! 268: 0, /* no disc indications */ ! 269: 0, /* don't change params */ ! 270: ISO_COSNS, /* p_netservice */ ! 271: }, ! 272: }; ! 273: ! 274: #if INET ! 275: int in_putnetaddr(); ! 276: int in_getnetaddr(); ! 277: int in_cmpnetaddr(); ! 278: int in_putsufx(); ! 279: int in_getsufx(); ! 280: int in_recycle_tsuffix(); ! 281: int tpip_mtu(); ! 282: int in_pcbbind(); ! 283: int in_pcbconnect(); ! 284: int in_pcbdisconnect(); ! 285: int in_pcbdetach(); ! 286: int in_pcballoc(); ! 287: int tpip_output(); ! 288: int tpip_output_dg(); ! 289: struct inpcb tp_inpcb; ! 290: #endif /* INET */ ! 291: #if ISO ! 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 tpclnp_mtu(); ! 299: int iso_pcbbind(); ! 300: int iso_pcbconnect(); ! 301: int iso_pcbdisconnect(); ! 302: int iso_pcbdetach(); ! 303: int iso_pcballoc(); ! 304: int tpclnp_output(); ! 305: int tpclnp_output_dg(); ! 306: int iso_nlctloutput(); ! 307: struct isopcb tp_isopcb; ! 308: #endif /* ISO */ ! 309: #if TPCONS ! 310: int iso_putnetaddr(); ! 311: int iso_getnetaddr(); ! 312: int iso_cmpnetaddr(); ! 313: int iso_putsufx(); ! 314: int iso_getsufx(); ! 315: int iso_recycle_tsuffix(); ! 316: int iso_pcbbind(); ! 317: int tpcons_pcbconnect(); ! 318: int tpclnp_mtu(); ! 319: int iso_pcbdisconnect(); ! 320: int iso_pcbdetach(); ! 321: int iso_pcballoc(); ! 322: int tpcons_output(); ! 323: struct isopcb tp_isopcb; ! 324: #endif /* TPCONS */ ! 325: ! 326: ! 327: struct nl_protosw nl_protosw[] = { ! 328: /* ISO_CLNS */ ! 329: #if ISO ! 330: { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr, ! 331: iso_putsufx, iso_getsufx, ! 332: iso_recycle_tsuffix, ! 333: tpclnp_mtu, iso_pcbbind, iso_pcbconnect, ! 334: iso_pcbdisconnect, iso_pcbdetach, ! 335: iso_pcballoc, ! 336: tpclnp_output, tpclnp_output_dg, iso_nlctloutput, ! 337: (caddr_t) &tp_isopcb, ! 338: }, ! 339: #else ! 340: { 0 }, ! 341: #endif /* ISO */ ! 342: /* IN_CLNS */ ! 343: #if INET ! 344: { AF_INET, in_putnetaddr, in_getnetaddr, in_cmpnetaddr, ! 345: in_putsufx, in_getsufx, ! 346: in_recycle_tsuffix, ! 347: tpip_mtu, in_pcbbind, in_pcbconnect, ! 348: in_pcbdisconnect, in_pcbdetach, ! 349: in_pcballoc, ! 350: tpip_output, tpip_output_dg, /* nl_ctloutput */ NULL, ! 351: (caddr_t) &tp_inpcb, ! 352: }, ! 353: #else ! 354: { 0 }, ! 355: #endif /* INET */ ! 356: /* ISO_CONS */ ! 357: #if defined(ISO) && defined(TPCONS) ! 358: { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr, ! 359: iso_putsufx, iso_getsufx, ! 360: iso_recycle_tsuffix, ! 361: tpclnp_mtu, iso_pcbbind, tpcons_pcbconnect, ! 362: iso_pcbdisconnect, iso_pcbdetach, ! 363: iso_pcballoc, ! 364: tpcons_output, tpcons_output, iso_nlctloutput, ! 365: (caddr_t) &tp_isopcb, ! 366: }, ! 367: #else ! 368: { 0 }, ! 369: #endif /* ISO_CONS */ ! 370: /* End of protosw marker */ ! 371: { 0 } ! 372: }; ! 373: ! 374: u_long tp_sendspace = 1024 * 4; ! 375: u_long tp_recvspace = 1024 * 4; ! 376: ! 377: /* ! 378: * NAME: tp_init() ! 379: * ! 380: * CALLED FROM: ! 381: * autoconf through the protosw structure ! 382: * ! 383: * FUNCTION: ! 384: * initialize tp machine ! 385: * ! 386: * RETURNS: Nada ! 387: * ! 388: * SIDE EFFECTS: ! 389: * ! 390: * NOTES: ! 391: */ ! 392: int ! 393: tp_init() ! 394: { ! 395: static int init_done=0; ! 396: void tp_timerinit(); ! 397: ! 398: if (init_done++) ! 399: return 0; ! 400: ! 401: ! 402: /* FOR INET */ ! 403: tp_inpcb.inp_next = tp_inpcb.inp_prev = &tp_inpcb; ! 404: /* FOR ISO */ ! 405: tp_isopcb.isop_next = tp_isopcb.isop_prev = &tp_isopcb; ! 406: ! 407: tp_start_win = 2; ! 408: ! 409: tp_timerinit(); ! 410: bzero((caddr_t)&tp_stat, sizeof(struct tp_stat)); ! 411: return 0; ! 412: } ! 413: ! 414: /* ! 415: * NAME: tp_soisdisconnecting() ! 416: * ! 417: * CALLED FROM: ! 418: * tp.trans ! 419: * ! 420: * FUNCTION and ARGUMENTS: ! 421: * Set state of the socket (so) to reflect that fact that we're disconnectING ! 422: * ! 423: * RETURNS: Nada ! 424: * ! 425: * SIDE EFFECTS: ! 426: * ! 427: * NOTES: ! 428: * This differs from the regular soisdisconnecting() in that the latter ! 429: * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags. ! 430: * We don't want to set those flags because those flags will cause ! 431: * a SIGPIPE to be delivered in sosend() and we don't like that. ! 432: * If anyone else is sleeping on this socket, wake 'em up. ! 433: */ ! 434: void ! 435: tp_soisdisconnecting(so) ! 436: register struct socket *so; ! 437: { ! 438: soisdisconnecting(so); ! 439: so->so_state &= ~SS_CANTSENDMORE; ! 440: IFPERF(sototpcb(so)) ! 441: register struct tp_pcb *tpcb = sototpcb(so); ! 442: u_int fsufx, lsufx; ! 443: ! 444: bcopy ((caddr_t)tpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) ); ! 445: bcopy ((caddr_t)tpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) ); ! 446: ! 447: tpmeas(tpcb->tp_lref, TPtime_close, &time, fsufx, lsufx, tpcb->tp_fref); ! 448: tpcb->tp_perf_on = 0; /* turn perf off */ ! 449: ENDPERF ! 450: } ! 451: ! 452: ! 453: /* ! 454: * NAME: tp_soisdisconnected() ! 455: * ! 456: * CALLED FROM: ! 457: * tp.trans ! 458: * ! 459: * FUNCTION and ARGUMENTS: ! 460: * Set state of the socket (so) to reflect that fact that we're disconnectED ! 461: * Set the state of the reference structure to closed, and ! 462: * recycle the suffix. ! 463: * Start a reference timer. ! 464: * ! 465: * RETURNS: Nada ! 466: * ! 467: * SIDE EFFECTS: ! 468: * ! 469: * NOTES: ! 470: * This differs from the regular soisdisconnected() in that the latter ! 471: * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags. ! 472: * We don't want to set those flags because those flags will cause ! 473: * a SIGPIPE to be delivered in sosend() and we don't like that. ! 474: * If anyone else is sleeping on this socket, wake 'em up. ! 475: */ ! 476: void ! 477: tp_soisdisconnected(tpcb) ! 478: register struct tp_pcb *tpcb; ! 479: { ! 480: register struct socket *so = tpcb->tp_sock; ! 481: ! 482: soisdisconnecting(so); ! 483: so->so_state &= ~SS_CANTSENDMORE; ! 484: IFPERF(tpcb) ! 485: register struct tp_pcb *ttpcb = sototpcb(so); ! 486: u_int fsufx, lsufx; ! 487: ! 488: /* CHOKE */ ! 489: bcopy ((caddr_t)ttpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) ); ! 490: bcopy ((caddr_t)ttpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) ); ! 491: ! 492: tpmeas(ttpcb->tp_lref, TPtime_close, ! 493: &time, &lsufx, &fsufx, ttpcb->tp_fref); ! 494: tpcb->tp_perf_on = 0; /* turn perf off */ ! 495: ENDPERF ! 496: ! 497: tpcb->tp_refstate = REF_FROZEN; ! 498: tp_recycle_tsuffix(tpcb); ! 499: tp_etimeout(tpcb, TM_reference, (int)tpcb->tp_refer_ticks); ! 500: } ! 501: ! 502: /* ! 503: * NAME: tp_freeref() ! 504: * ! 505: * CALLED FROM: ! 506: * tp.trans when the reference timer goes off, and ! 507: * from tp_attach() and tp_detach() when a tpcb is partially set up but not ! 508: * set up enough to have a ref timer set for it, and it's discarded ! 509: * due to some sort of error or an early close() ! 510: * ! 511: * FUNCTION and ARGUMENTS: ! 512: * Frees the reference represented by (r) for re-use. ! 513: * ! 514: * RETURNS: Nothing ! 515: * ! 516: * SIDE EFFECTS: ! 517: * ! 518: * NOTES: better be called at clock priority !!!!! ! 519: */ ! 520: void ! 521: tp_freeref(n) ! 522: RefNum n; ! 523: { ! 524: register struct tp_ref *r = tp_ref + n; ! 525: register struct tp_pcb *tpcb; ! 526: ! 527: tpcb = r->tpr_pcb; ! 528: IFDEBUG(D_TIMER) ! 529: printf("tp_freeref called for ref %d pcb %x maxrefopen %d\n", ! 530: n, tpcb, tp_refinfo.tpr_maxopen); ! 531: ENDDEBUG ! 532: IFTRACE(D_TIMER) ! 533: tptrace(TPPTmisc, "tp_freeref ref maxrefopen pcb", ! 534: n, tp_refinfo.tpr_maxopen, tpcb, 0); ! 535: ENDTRACE ! 536: if (tpcb == 0) ! 537: return; ! 538: IFDEBUG(D_CONN) ! 539: printf("tp_freeref: CLEARING tpr_pcb 0x%x\n", tpcb); ! 540: ENDDEBUG ! 541: r->tpr_pcb = (struct tp_pcb *)0; ! 542: tpcb->tp_refstate = REF_FREE; ! 543: ! 544: for (r = tp_ref + tp_refinfo.tpr_maxopen; r > tp_ref; r--) ! 545: if (r->tpr_pcb) ! 546: break; ! 547: tp_refinfo.tpr_maxopen = r - tp_ref; ! 548: tp_refinfo.tpr_numopen--; ! 549: ! 550: IFDEBUG(D_TIMER) ! 551: printf("tp_freeref ends w/ maxrefopen %d\n", tp_refinfo.tpr_maxopen); ! 552: ENDDEBUG ! 553: } ! 554: ! 555: /* ! 556: * NAME: tp_getref() ! 557: * ! 558: * CALLED FROM: ! 559: * tp_attach() ! 560: * ! 561: * FUNCTION and ARGUMENTS: ! 562: * obtains the next free reference and allocates the appropriate ! 563: * ref structure, links that structure to (tpcb) ! 564: * ! 565: * RETURN VALUE: ! 566: * a reference number ! 567: * or TP_ENOREF ! 568: * ! 569: * SIDE EFFECTS: ! 570: * ! 571: * NOTES: ! 572: */ ! 573: u_long ! 574: tp_getref(tpcb) ! 575: register struct tp_pcb *tpcb; ! 576: { ! 577: register struct tp_ref *r, *rlim; ! 578: register int i; ! 579: caddr_t obase; ! 580: unsigned size; ! 581: ! 582: if (++tp_refinfo.tpr_numopen < tp_refinfo.tpr_size) ! 583: for (r = tp_refinfo.tpr_base, rlim = r + tp_refinfo.tpr_size; ! 584: ++r < rlim; ) /* tp_ref[0] is never used */ ! 585: if (r->tpr_pcb == 0) ! 586: goto got_one; ! 587: /* else have to allocate more space */ ! 588: ! 589: obase = (caddr_t)tp_refinfo.tpr_base; ! 590: size = tp_refinfo.tpr_size * sizeof(struct tp_ref); ! 591: // r = (struct tp_ref *) malloc(size + size, M_PCB, M_NOWAIT); ! 592: MALLOC(r, struct tp_ref *, size + size, M_PCB, M_NOWAIT); ! 593: if (r == 0) ! 594: return (--tp_refinfo.tpr_numopen, TP_ENOREF); ! 595: tp_refinfo.tpr_base = tp_ref = r; ! 596: tp_refinfo.tpr_size *= 2; ! 597: bcopy(obase, (caddr_t)r, size); ! 598: free(obase, M_PCB); ! 599: r = (struct tp_ref *)(size + (caddr_t)r); ! 600: bzero((caddr_t)r, size); ! 601: ! 602: got_one: ! 603: r->tpr_pcb = tpcb; ! 604: tpcb->tp_refstate = REF_OPENING; ! 605: i = r - tp_refinfo.tpr_base; ! 606: if (tp_refinfo.tpr_maxopen < i) ! 607: tp_refinfo.tpr_maxopen = i; ! 608: return (u_long)i; ! 609: } ! 610: ! 611: /* ! 612: * NAME: tp_set_npcb() ! 613: * ! 614: * CALLED FROM: ! 615: * tp_attach(), tp_route_to() ! 616: * ! 617: * FUNCTION and ARGUMENTS: ! 618: * given a tpcb, allocate an appropriate lower-lever npcb, freeing ! 619: * any old ones that might need re-assigning. ! 620: */ ! 621: tp_set_npcb(tpcb) ! 622: register struct tp_pcb *tpcb; ! 623: { ! 624: register struct socket *so = tpcb->tp_sock; ! 625: int error; ! 626: ! 627: if (tpcb->tp_nlproto && tpcb->tp_npcb) { ! 628: short so_state = so->so_state; ! 629: so->so_state &= ~SS_NOFDREF; ! 630: tpcb->tp_nlproto->nlp_pcbdetach(tpcb->tp_npcb); ! 631: so->so_state = so_state; ! 632: } ! 633: tpcb->tp_nlproto = &nl_protosw[tpcb->tp_netservice]; ! 634: /* xx_pcballoc sets so_pcb */ ! 635: error = tpcb->tp_nlproto->nlp_pcballoc(so, tpcb->tp_nlproto->nlp_pcblist); ! 636: tpcb->tp_npcb = so->so_pcb; ! 637: so->so_pcb = (caddr_t)tpcb; ! 638: return (error); ! 639: } ! 640: /* ! 641: * NAME: tp_attach() ! 642: * ! 643: * CALLED FROM: ! 644: * tp_usrreq, PRU_ATTACH ! 645: * ! 646: * FUNCTION and ARGUMENTS: ! 647: * given a socket (so) and a protocol family (dom), allocate a tpcb ! 648: * and ref structure, initialize everything in the structures that ! 649: * needs to be initialized. ! 650: * ! 651: * RETURN VALUE: ! 652: * 0 ok ! 653: * EINVAL if DEBUG(X) in is on and a disaster has occurred ! 654: * ENOPROTOOPT if TP hasn't been configured or if the ! 655: * socket wasn't created with tp as its protocol ! 656: * EISCONN if this socket is already part of a connection ! 657: * ETOOMANYREFS if ran out of tp reference numbers. ! 658: * E* whatever error is returned from soreserve() ! 659: * for from the network-layer pcb allocation routine ! 660: * ! 661: * SIDE EFFECTS: ! 662: * ! 663: * NOTES: ! 664: */ ! 665: tp_attach(so, protocol) ! 666: struct socket *so; ! 667: int protocol; ! 668: { ! 669: register struct tp_pcb *tpcb; ! 670: int error = 0; ! 671: int dom = so->so_proto->pr_domain->dom_family; ! 672: u_long lref; ! 673: extern struct tp_conn_param tp_conn_param[]; ! 674: ! 675: IFDEBUG(D_CONN) ! 676: printf("tp_attach:dom 0x%x so 0x%x ", dom, so); ! 677: ENDDEBUG ! 678: IFTRACE(D_CONN) ! 679: tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0); ! 680: ENDTRACE ! 681: ! 682: if (so->so_pcb != NULL) { ! 683: return EISCONN; /* socket already part of a connection*/ ! 684: } ! 685: ! 686: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) ! 687: error = soreserve(so, tp_sendspace, tp_recvspace); ! 688: /* later an ioctl will allow reallocation IF still in closed state */ ! 689: ! 690: if (error) ! 691: goto bad2; ! 692: ! 693: MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT); ! 694: if (tpcb == NULL) { ! 695: error = ENOBUFS; ! 696: goto bad2; ! 697: } ! 698: bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) ); ! 699: ! 700: if ( ((lref = tp_getref(tpcb)) & TP_ENOREF) != 0 ) { ! 701: error = ETOOMANYREFS; ! 702: goto bad3; ! 703: } ! 704: tpcb->tp_lref = lref; ! 705: tpcb->tp_sock = so; ! 706: tpcb->tp_domain = dom; ! 707: tpcb->tp_rhiwat = so->so_rcv.sb_hiwat; ! 708: /* tpcb->tp_proto = protocol; someday maybe? */ ! 709: if (protocol && protocol<ISOPROTO_TP4) { ! 710: tpcb->tp_netservice = ISO_CONS; ! 711: tpcb->tp_snduna = (SeqNum) -1;/* kludge so the pseudo-ack from the CR/CC ! 712: * will generate correct fake-ack values ! 713: */ ! 714: } else { ! 715: tpcb->tp_netservice = (dom== AF_INET)?IN_CLNS:ISO_CLNS; ! 716: /* the default */ ! 717: } ! 718: tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice]; ! 719: ! 720: tpcb->tp_state = TP_CLOSED; ! 721: tpcb->tp_vers = TP_VERSION; ! 722: tpcb->tp_notdetached = 1; ! 723: ! 724: /* Spec says default is 128 octets, ! 725: * that is, if the tpdusize argument never appears, use 128. ! 726: * As the initiator, we will always "propose" the 2048 ! 727: * size, that is, we will put this argument in the CR ! 728: * always, but accept what the other side sends on the CC. ! 729: * If the initiator sends us something larger on a CR, ! 730: * we'll respond w/ this. ! 731: * Our maximum is 4096. See tp_chksum.c comments. ! 732: */ ! 733: tpcb->tp_cong_win = ! 734: tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize; ! 735: ! 736: tpcb->tp_seqmask = TP_NML_FMT_MASK; ! 737: tpcb->tp_seqbit = TP_NML_FMT_BIT; ! 738: tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; ! 739: ! 740: /* attach to a network-layer protoswitch */ ! 741: if ( error = tp_set_npcb(tpcb)) ! 742: goto bad4; ! 743: ASSERT( tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain); ! 744: ! 745: /* nothing to do for iso case */ ! 746: if( dom == AF_INET ) ! 747: sotoinpcb(so)->inp_ppcb = (caddr_t) tpcb; ! 748: ! 749: return 0; ! 750: ! 751: bad4: ! 752: IFDEBUG(D_CONN) ! 753: printf("BAD4 in tp_attach, so 0x%x\n", so); ! 754: ENDDEBUG ! 755: tp_freeref(tpcb->tp_lref); ! 756: ! 757: bad3: ! 758: IFDEBUG(D_CONN) ! 759: printf("BAD3 in tp_attach, so 0x%x\n", so); ! 760: ENDDEBUG ! 761: ! 762: free((caddr_t)tpcb, M_PCB); /* never a cluster */ ! 763: ! 764: bad2: ! 765: IFDEBUG(D_CONN) ! 766: printf("BAD2 in tp_attach, so 0x%x\n", so); ! 767: ENDDEBUG ! 768: so->so_pcb = 0; ! 769: ! 770: /*bad:*/ ! 771: IFDEBUG(D_CONN) ! 772: printf("BAD in tp_attach, so 0x%x\n", so); ! 773: ENDDEBUG ! 774: return error; ! 775: } ! 776: ! 777: /* ! 778: * NAME: tp_detach() ! 779: * ! 780: * CALLED FROM: ! 781: * tp.trans, on behalf of a user close request ! 782: * and when the reference timer goes off ! 783: * (if the disconnect was initiated by the protocol entity ! 784: * rather than by the user) ! 785: * ! 786: * FUNCTION and ARGUMENTS: ! 787: * remove the tpcb structure from the list of active or ! 788: * partially active connections, recycle all the mbufs ! 789: * associated with the pcb, ref structure, sockbufs, etc. ! 790: * Only free the ref structure if you know that a ref timer ! 791: * wasn't set for this tpcb. ! 792: * ! 793: * RETURNS: Nada ! 794: * ! 795: * SIDE EFFECTS: ! 796: * ! 797: * NOTES: ! 798: * tp_soisdisconnected() was already when this is called ! 799: */ ! 800: void ! 801: tp_detach(tpcb) ! 802: register struct tp_pcb *tpcb; ! 803: { ! 804: void tp_freeref(), tp_rsyflush(); ! 805: register struct socket *so = tpcb->tp_sock; ! 806: ! 807: IFDEBUG(D_CONN) ! 808: printf("tp_detach(tpcb 0x%x, so 0x%x)\n", ! 809: tpcb,so); ! 810: ENDDEBUG ! 811: IFTRACE(D_CONN) ! 812: tptraceTPCB(TPPTmisc, "tp_detach tpcb so lsufx", ! 813: tpcb, so, *(u_short *)(tpcb->tp_lsuffix), 0); ! 814: ENDTRACE ! 815: ! 816: IFDEBUG(D_CONN) ! 817: printf("so_snd at 0x%x so_rcv at 0x%x\n", &so->so_snd, &so->so_rcv); ! 818: dump_mbuf(so->so_snd.sb_mb, "so_snd at detach "); ! 819: printf("about to call LL detach, nlproto 0x%x, nl_detach 0x%x\n", ! 820: tpcb->tp_nlproto, tpcb->tp_nlproto->nlp_pcbdetach); ! 821: ENDDEBUG ! 822: ! 823: if (tpcb->tp_Xsnd.sb_mb) { ! 824: printf("Unsent Xdata on detach; would panic"); ! 825: sbflush(&tpcb->tp_Xsnd); ! 826: } ! 827: if (tpcb->tp_ucddata) ! 828: m_freem(tpcb->tp_ucddata); ! 829: ! 830: IFDEBUG(D_CONN) ! 831: printf("reassembly info cnt %d rsyq 0x%x\n", ! 832: tpcb->tp_rsycnt, tpcb->tp_rsyq); ! 833: ENDDEBUG ! 834: if (tpcb->tp_rsyq) ! 835: tp_rsyflush(tpcb); ! 836: ! 837: if (tpcb->tp_next) { ! 838: remque(tpcb); ! 839: tpcb->tp_next = tpcb->tp_prev = 0; ! 840: } ! 841: tpcb->tp_notdetached = 0; ! 842: ! 843: IFDEBUG(D_CONN) ! 844: printf("calling (...nlproto->...)(0x%x, so 0x%x)\n", ! 845: tpcb->tp_npcb, so); ! 846: printf("so 0x%x so_head 0x%x, qlen %d q0len %d qlimit %d\n", ! 847: so, so->so_head, ! 848: so->so_q0len, so->so_qlen, so->so_qlimit); ! 849: ENDDEBUG ! 850: ! 851: (tpcb->tp_nlproto->nlp_pcbdetach)(tpcb->tp_npcb); ! 852: /* does an so->so_pcb = 0; sofree(so) */ ! 853: ! 854: IFDEBUG(D_CONN) ! 855: printf("after xxx_pcbdetach\n"); ! 856: ENDDEBUG ! 857: ! 858: if (tpcb->tp_state == TP_LISTENING) { ! 859: register struct tp_pcb **tt; ! 860: for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten)) ! 861: if (*tt == tpcb) ! 862: break; ! 863: if (*tt) ! 864: *tt = tpcb->tp_nextlisten; ! 865: else ! 866: printf("tp_detach from listen: should panic\n"); ! 867: } ! 868: if (tpcb->tp_refstate == REF_OPENING ) { ! 869: /* no connection existed here so no reference timer will be called */ ! 870: IFDEBUG(D_CONN) ! 871: printf("SETTING ref %d to REF_FREE\n", tpcb->tp_lref); ! 872: ENDDEBUG ! 873: ! 874: tp_freeref(tpcb->tp_lref); ! 875: } ! 876: #ifdef TP_PERF_MEAS ! 877: /* ! 878: * Get rid of the cluster mbuf allocated for performance measurements, if ! 879: * there is one. Note that tpcb->tp_perf_on says nothing about whether or ! 880: * not a cluster mbuf was allocated, so you have to check for a pointer ! 881: * to one (that is, we need the TP_PERF_MEASs around the following section ! 882: * of code, not the IFPERFs) ! 883: */ ! 884: if (tpcb->tp_p_mbuf) { ! 885: register struct mbuf *m = tpcb->tp_p_mbuf; ! 886: struct mbuf *n; ! 887: IFDEBUG(D_PERF_MEAS) ! 888: printf("freeing tp_p_meas 0x%x ", tpcb->tp_p_meas); ! 889: ENDDEBUG ! 890: do { ! 891: MFREE(m, n); ! 892: m = n; ! 893: } while (n); ! 894: tpcb->tp_p_meas = 0; ! 895: tpcb->tp_p_mbuf = 0; ! 896: } ! 897: #endif /* TP_PERF_MEAS */ ! 898: ! 899: IFDEBUG(D_CONN) ! 900: printf( "end of detach, NOT single, tpcb 0x%x\n", tpcb); ! 901: ENDDEBUG ! 902: /* free((caddr_t)tpcb, M_PCB); WHere to put this ? */ ! 903: } ! 904: ! 905: struct que { ! 906: struct tp_pcb *next; ! 907: struct tp_pcb *prev; ! 908: } tp_bound_pcbs = ! 909: {(struct tp_pcb *)&tp_bound_pcbs, (struct tp_pcb *)&tp_bound_pcbs}; ! 910: ! 911: u_short tp_unique; ! 912: ! 913: tp_tselinuse(tlen, tsel, siso, reuseaddr) ! 914: caddr_t tsel; ! 915: register struct sockaddr_iso *siso; ! 916: { ! 917: struct tp_pcb *b = tp_bound_pcbs.next, *l = tp_listeners; ! 918: register struct tp_pcb *t; ! 919: ! 920: for (;;) { ! 921: if (b != (struct tp_pcb *)&tp_bound_pcbs) { ! 922: t = b; b = t->tp_next; ! 923: } else if (l) { ! 924: t = l; l = t->tp_nextlisten; ! 925: } else ! 926: break; ! 927: if (tlen == t->tp_lsuffixlen && bcmp(tsel, t->tp_lsuffix, tlen) == 0) { ! 928: if (t->tp_flags & TPF_GENERAL_ADDR) { ! 929: if (siso == 0 || reuseaddr == 0) ! 930: return 1; ! 931: } else if (siso) { ! 932: if (siso->siso_family == t->tp_domain && ! 933: t->tp_nlproto->nlp_cmpnetaddr(t->tp_npcb, siso, TP_LOCAL)) ! 934: return 1; ! 935: } else if (reuseaddr == 0) ! 936: return 1; ! 937: } ! 938: } ! 939: return 0; ! 940: ! 941: } ! 942: ! 943: ! 944: tp_pcbbind(tpcb, nam) ! 945: register struct tp_pcb *tpcb; ! 946: register struct mbuf *nam; ! 947: { ! 948: register struct sockaddr_iso *siso = 0; ! 949: int tlen = 0, wrapped = 0; ! 950: caddr_t tsel; ! 951: u_short tutil; ! 952: ! 953: if (tpcb->tp_state != TP_CLOSED) ! 954: return (EINVAL); ! 955: if (nam) { ! 956: siso = mtod(nam, struct sockaddr_iso *); ! 957: switch (siso->siso_family) { ! 958: default: ! 959: return (EAFNOSUPPORT); ! 960: #if ISO ! 961: case AF_ISO: ! 962: tlen = siso->siso_tlen; ! 963: tsel = TSEL(siso); ! 964: if (siso->siso_nlen == 0) ! 965: siso = 0; ! 966: break; ! 967: #endif ! 968: #if INET ! 969: case AF_INET: ! 970: tsel = (caddr_t)&tutil; ! 971: if (tutil = ((struct sockaddr_in *)siso)->sin_port) { ! 972: tlen = 2; ! 973: } ! 974: if (((struct sockaddr_in *)siso)->sin_addr.s_addr == 0) ! 975: siso = 0; ! 976: } ! 977: #endif ! 978: } ! 979: if (tpcb->tp_lsuffixlen == 0) { ! 980: if (tlen) { ! 981: if (tp_tselinuse(tlen, tsel, siso, ! 982: tpcb->tp_sock->so_options & SO_REUSEADDR)) ! 983: return (EINVAL); ! 984: } else { ! 985: for (tsel = (caddr_t)&tutil, tlen = 2;;){ ! 986: if (tp_unique++ < ISO_PORT_RESERVED || ! 987: tp_unique > ISO_PORT_USERRESERVED) { ! 988: if (wrapped++) ! 989: return ESRCH; ! 990: tp_unique = ISO_PORT_RESERVED; ! 991: } ! 992: tutil = htons(tp_unique); ! 993: if (tp_tselinuse(tlen, tsel, siso, 0) == 0) ! 994: break; ! 995: } ! 996: if (siso) switch (siso->siso_family) { ! 997: #if ISO ! 998: case AF_ISO: ! 999: bcopy(tsel, TSEL(siso), tlen); ! 1000: siso->siso_tlen = tlen; ! 1001: break; ! 1002: #endif ! 1003: #if INET ! 1004: case AF_INET: ! 1005: ((struct sockaddr_in *)siso)->sin_port = tutil; ! 1006: #endif ! 1007: } ! 1008: } ! 1009: bcopy(tsel, tpcb->tp_lsuffix, (tpcb->tp_lsuffixlen = tlen)); ! 1010: insque(tpcb, &tp_bound_pcbs); ! 1011: } else { ! 1012: if (tlen || siso == 0) ! 1013: return (EINVAL); ! 1014: } ! 1015: if (siso == 0) { ! 1016: tpcb->tp_flags |= TPF_GENERAL_ADDR; ! 1017: return (0); ! 1018: } ! 1019: return tpcb->tp_nlproto->nlp_pcbbind(tpcb->tp_npcb, nam); ! 1020: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.