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