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