136408Ssklower /*********************************************************** 239196Ssklower Copyright IBM Corporation 1987 336408Ssklower 436408Ssklower All Rights Reserved 536408Ssklower 636408Ssklower Permission to use, copy, modify, and distribute this software and its 736408Ssklower documentation for any purpose and without fee is hereby granted, 836408Ssklower provided that the above copyright notice appear in all copies and that 936408Ssklower both that copyright notice and this permission notice appear in 1036408Ssklower supporting documentation, and that the name of IBM not be 1136408Ssklower used in advertising or publicity pertaining to distribution of the 1236408Ssklower software without specific, written prior permission. 1336408Ssklower 1436408Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536408Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636408Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736408Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836408Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936408Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036408Ssklower SOFTWARE. 2136408Ssklower 2236408Ssklower ******************************************************************/ 2336408Ssklower 2436408Ssklower /* 2536408Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636408Ssklower */ 2736408Ssklower /* 2836408Ssklower * ARGO TP 2936408Ssklower * 3036408Ssklower * $Header: tp_pcb.c,v 5.4 88/11/18 17:28:24 nhall Exp $ 3136408Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_pcb.c,v $ 32*45900Ssklower * @(#)tp_pcb.c 7.7 (Berkeley) 01/09/91 * 3336408Ssklower * 3436408Ssklower * 3536408Ssklower * This is the initialization and cleanup stuff - 3636408Ssklower * for the tp machine in general as well as for the individual pcbs. 3736408Ssklower * tp_init() is called at system startup. tp_attach() and tp_getref() are 3836408Ssklower * called when a socket is created. tp_detach() and tp_freeref() 3936408Ssklower * are called during the closing stage and/or when the reference timer 4036408Ssklower * goes off. 4136408Ssklower * tp_soisdisconnecting() and tp_soisdisconnected() are tp-specific 4236408Ssklower * versions of soisconnect* 4336408Ssklower * and are called (obviously) during the closing phase. 4436408Ssklower * 4536408Ssklower */ 4636408Ssklower 4736408Ssklower #ifndef lint 4836408Ssklower static char *rcsid = "$Header: tp_pcb.c,v 5.4 88/11/18 17:28:24 nhall Exp $"; 4936408Ssklower #endif lint 5036408Ssklower 5136408Ssklower #include "types.h" 5236408Ssklower #include "param.h" 5336408Ssklower #include "mbuf.h" 5436408Ssklower #include "socket.h" 5536408Ssklower #include "socketvar.h" 5636408Ssklower #include "protosw.h" 5736408Ssklower #include "errno.h" 5836408Ssklower #include "time.h" 5937469Ssklower #include "argo_debug.h" 6037469Ssklower #include "tp_param.h" 6137469Ssklower #include "tp_timer.h" 6237469Ssklower #include "tp_ip.h" 6337469Ssklower #include "tp_stat.h" 6437469Ssklower #include "tp_pcb.h" 6537469Ssklower #include "tp_tpdu.h" 6637469Ssklower #include "tp_trace.h" 6737469Ssklower #include "tp_meas.h" 6837469Ssklower #include "tp_seq.h" 6937469Ssklower #include "tp_clnp.h" 7036408Ssklower 7136408Ssklower /* list of reference structures */ 7236408Ssklower struct tp_ref tp_ref[N_TPREF]; 7336408Ssklower 7436408Ssklower struct tp_param tp_param = { 7536408Ssklower 1, /* configured */ 7636408Ssklower }; 7736408Ssklower 7836408Ssklower /* ticks are in units of: 7936408Ssklower * 500 nano-fortnights ;-) or 8036408Ssklower * 500 ms or 8136408Ssklower * 1/2 second 8236408Ssklower */ 8336408Ssklower 8436408Ssklower struct tp_conn_param tp_conn_param[] = { 8536408Ssklower /* ISO_CLNS: TP4 CONNECTION LESS */ 8636408Ssklower { 8736408Ssklower TP_NRETRANS, /* short p_Nretrans; */ 8836408Ssklower 20, /* 10 sec */ /* short p_dr_ticks; */ 8936408Ssklower 9036408Ssklower 20, /* 10 sec */ /* short p_cc_ticks; */ 9136408Ssklower 20, /* 10 sec */ /* short p_dt_ticks; */ 9236408Ssklower 9336408Ssklower 40, /* 20 sec */ /* short p_x_ticks; */ 9436408Ssklower 80, /* 40 sec */ /* short p_cr_ticks;*/ 9536408Ssklower 9636408Ssklower 240, /* 2 min */ /* short p_keepalive_ticks;*/ 9736408Ssklower 10, /* 5 sec */ /* short p_sendack_ticks; */ 9836408Ssklower 9936408Ssklower 600, /* 5 min */ /* short p_ref_ticks; */ 10036408Ssklower 360, /* 3 min */ /* short p_inact_ticks; */ 10136408Ssklower 10236408Ssklower (short) 100, /* short p_lcdtfract */ 10336408Ssklower (short) TP_SOCKBUFSIZE, /* short p_winsize */ 10436408Ssklower TP_TPDUSIZE, /* u_char p_tpdusize */ 10536408Ssklower 10636408Ssklower TPACK_WINDOW, /* 4 bits p_ack_strat */ 10736408Ssklower TPRX_USE_CW | TPRX_FASTSTART, 10836408Ssklower /* 4 bits p_rx_strat*/ 10936408Ssklower TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */ 11036408Ssklower 1, /* 1 bit xtd format */ 11136408Ssklower 1, /* 1 bit xpd service */ 11236408Ssklower 1, /* 1 bit use_checksum */ 11336408Ssklower 0, /* 1 bit use net xpd */ 11436408Ssklower 0, /* 1 bit use rcc */ 11536408Ssklower 0, /* 1 bit use efc */ 11638841Ssklower 1, /* no disc indications */ 11736408Ssklower 0, /* don't change params */ 11836408Ssklower ISO_CLNS, /* p_netservice */ 11936408Ssklower }, 12036408Ssklower /* IN_CLNS: TP4 CONNECTION LESS */ 12136408Ssklower { 12236408Ssklower TP_NRETRANS, /* short p_Nretrans; */ 12336408Ssklower 20, /* 10 sec */ /* short p_dr_ticks; */ 12436408Ssklower 12536408Ssklower 20, /* 10 sec */ /* short p_cc_ticks; */ 12636408Ssklower 20, /* 10 sec */ /* short p_dt_ticks; */ 12736408Ssklower 12836408Ssklower 40, /* 20 sec */ /* short p_x_ticks; */ 12936408Ssklower 80, /* 40 sec */ /* short p_cr_ticks;*/ 13036408Ssklower 13136408Ssklower 240, /* 2 min */ /* short p_keepalive_ticks;*/ 13236408Ssklower 10, /* 5 sec */ /* short p_sendack_ticks; */ 13336408Ssklower 13436408Ssklower 600, /* 5 min */ /* short p_ref_ticks; */ 13536408Ssklower 360, /* 3 min */ /* short p_inact_ticks; */ 13636408Ssklower 13736408Ssklower (short) 100, /* short p_lcdtfract */ 13836408Ssklower (short) TP_SOCKBUFSIZE, /* short p_winsize */ 13936408Ssklower TP_TPDUSIZE, /* u_char p_tpdusize */ 14036408Ssklower 14136408Ssklower TPACK_WINDOW, /* 4 bits p_ack_strat */ 14236408Ssklower TPRX_USE_CW | TPRX_FASTSTART, 14336408Ssklower /* 4 bits p_rx_strat*/ 14436408Ssklower TP_CLASS_4, /* 5 bits p_class */ 14536408Ssklower 1, /* 1 bit xtd format */ 14636408Ssklower 1, /* 1 bit xpd service */ 14736408Ssklower 1, /* 1 bit use_checksum */ 14836408Ssklower 0, /* 1 bit use net xpd */ 14936408Ssklower 0, /* 1 bit use rcc */ 15036408Ssklower 0, /* 1 bit use efc */ 15138841Ssklower 1, /* no disc indications */ 15236408Ssklower 0, /* don't change params */ 15336408Ssklower IN_CLNS, /* p_netservice */ 15436408Ssklower }, 15536408Ssklower /* ISO_CONS: TP0 CONNECTION MODE */ 15636408Ssklower { 15736408Ssklower TP_NRETRANS, /* short p_Nretrans; */ 15836408Ssklower 0, /* n/a */ /* short p_dr_ticks; */ 15936408Ssklower 16036408Ssklower 40, /* 20 sec */ /* short p_cc_ticks; */ 16136408Ssklower 0, /* n/a */ /* short p_dt_ticks; */ 16236408Ssklower 16336408Ssklower 0, /* n/a */ /* short p_x_ticks; */ 16436408Ssklower 360, /* 3 min */ /* short p_cr_ticks;*/ 16536408Ssklower 16636408Ssklower 0, /* n/a */ /* short p_keepalive_ticks;*/ 16736408Ssklower 0, /* n/a */ /* short p_sendack_ticks; */ 16836408Ssklower 16936408Ssklower 600, /* for cr/cc to clear *//* short p_ref_ticks; */ 17036408Ssklower 0, /* n/a */ /* short p_inact_ticks; */ 17136408Ssklower 17236408Ssklower /* Use tp4 defaults just in case the user changes ONLY 17336408Ssklower * the class 17436408Ssklower */ 17536408Ssklower (short) 100, /* short p_lcdtfract */ 17636408Ssklower (short) TP0_SOCKBUFSIZE, /* short p_winsize */ 17736408Ssklower TP0_TPDUSIZE, /* 8 bits p_tpdusize */ 17836408Ssklower 17936408Ssklower 0, /* 4 bits p_ack_strat */ 18036408Ssklower 0, /* 4 bits p_rx_strat*/ 18136408Ssklower TP_CLASS_0, /* 5 bits p_class */ 18236408Ssklower 0, /* 1 bit xtd format */ 18336408Ssklower 0, /* 1 bit xpd service */ 18436408Ssklower 0, /* 1 bit use_checksum */ 18536408Ssklower 0, /* 1 bit use net xpd */ 18636408Ssklower 0, /* 1 bit use rcc */ 18736408Ssklower 0, /* 1 bit use efc */ 18836408Ssklower 0, /* no disc indications */ 18936408Ssklower 0, /* don't change params */ 19036408Ssklower ISO_CONS, /* p_netservice */ 19136408Ssklower }, 19236408Ssklower /* ISO_COSNS: TP4 CONNECTION LESS SERVICE over CONSNS */ 19336408Ssklower { 19436408Ssklower TP_NRETRANS, /* short p_Nretrans; */ 19536408Ssklower 40, /* 20 sec */ /* short p_dr_ticks; */ 19636408Ssklower 19736408Ssklower 40, /* 20 sec */ /* short p_cc_ticks; */ 19836408Ssklower 80, /* 40 sec */ /* short p_dt_ticks; */ 19936408Ssklower 20036408Ssklower 120, /* 1 min */ /* short p_x_ticks; */ 20136408Ssklower 360, /* 3 min */ /* short p_cr_ticks;*/ 20236408Ssklower 20336408Ssklower 360, /* 3 min */ /* short p_keepalive_ticks;*/ 20436408Ssklower 20, /* 10 sec */ /* short p_sendack_ticks; */ 20536408Ssklower 20636408Ssklower 600, /* 5 min */ /* short p_ref_ticks; */ 20736408Ssklower 480, /* 4 min */ /* short p_inact_ticks; */ 20836408Ssklower 20936408Ssklower (short) 100, /* short p_lcdtfract */ 21036408Ssklower (short) TP0_SOCKBUFSIZE, /* short p_winsize */ 21136408Ssklower TP0_TPDUSIZE, /* u_char p_tpdusize */ 21236408Ssklower 21336408Ssklower TPACK_WINDOW, /* 4 bits p_ack_strat */ 21436408Ssklower TPRX_USE_CW , /* No fast start */ 21536408Ssklower /* 4 bits p_rx_strat*/ 21636408Ssklower TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */ 21736408Ssklower 0, /* 1 bit xtd format */ 21836408Ssklower 1, /* 1 bit xpd service */ 21936408Ssklower 1, /* 1 bit use_checksum */ 22036408Ssklower 0, /* 1 bit use net xpd */ 22136408Ssklower 0, /* 1 bit use rcc */ 22236408Ssklower 0, /* 1 bit use efc */ 22336408Ssklower 0, /* no disc indications */ 22436408Ssklower 0, /* don't change params */ 22536408Ssklower ISO_COSNS, /* p_netservice */ 22636408Ssklower }, 22736408Ssklower }; 22836408Ssklower 22936408Ssklower #ifdef INET 23036408Ssklower int in_putnetaddr(); 23136408Ssklower int in_getnetaddr(); 23244423Ssklower int in_cmpnetaddr(); 23336408Ssklower int in_putsufx(); 23436408Ssklower int in_getsufx(); 23536408Ssklower int in_recycle_tsuffix(); 23636408Ssklower int tpip_mtu(); 23736408Ssklower int in_pcbbind(); 23836408Ssklower int in_pcbconnect(); 23936408Ssklower int in_pcbdisconnect(); 24036408Ssklower int in_pcbdetach(); 24136408Ssklower int in_pcballoc(); 24236408Ssklower int tpip_output(); 24336408Ssklower int tpip_output_dg(); 24436408Ssklower struct inpcb tp_inpcb; 24536408Ssklower #endif INET 24636408Ssklower #ifdef ISO 24736408Ssklower int iso_putnetaddr(); 24836408Ssklower int iso_getnetaddr(); 24944423Ssklower int iso_cmpnetaddr(); 25036408Ssklower int iso_putsufx(); 25136408Ssklower int iso_getsufx(); 25236408Ssklower int iso_recycle_tsuffix(); 25336408Ssklower int tpclnp_mtu(); 25436408Ssklower int iso_pcbbind(); 25536408Ssklower int iso_pcbconnect(); 25636408Ssklower int iso_pcbdisconnect(); 25736408Ssklower int iso_pcbdetach(); 25836408Ssklower int iso_pcballoc(); 25936408Ssklower int tpclnp_output(); 26036408Ssklower int tpclnp_output_dg(); 26136408Ssklower int iso_nlctloutput(); 26236408Ssklower struct isopcb tp_isopcb; 26336408Ssklower #endif ISO 264*45900Ssklower #ifdef TPCONS 26536408Ssklower int iso_putnetaddr(); 26636408Ssklower int iso_getnetaddr(); 26744423Ssklower int iso_cmpnetaddr(); 26836408Ssklower int iso_putsufx(); 26936408Ssklower int iso_getsufx(); 27036408Ssklower int iso_recycle_tsuffix(); 27136408Ssklower int tpcons_mtu(); 27236408Ssklower int iso_pcbbind(); 273*45900Ssklower int tpcons_pcbconnect(); 27436408Ssklower int iso_pcbdisconnect(); 27536408Ssklower int iso_pcbdetach(); 27636408Ssklower int iso_pcballoc(); 27736408Ssklower int tpcons_output(); 27836408Ssklower struct isopcb tp_isopcb; 279*45900Ssklower #endif TPCONS 28036408Ssklower 28137469Ssklower 28236408Ssklower struct nl_protosw nl_protosw[] = { 28336408Ssklower /* ISO_CLNS */ 28436408Ssklower #ifdef ISO 28544423Ssklower { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr, 28636408Ssklower iso_putsufx, iso_getsufx, 28736408Ssklower iso_recycle_tsuffix, 28836408Ssklower tpclnp_mtu, iso_pcbbind, iso_pcbconnect, 28936408Ssklower iso_pcbdisconnect, iso_pcbdetach, 29036408Ssklower iso_pcballoc, 29136408Ssklower tpclnp_output, tpclnp_output_dg, iso_nlctloutput, 29236408Ssklower (caddr_t) &tp_isopcb, 29336408Ssklower }, 29437469Ssklower #else 29537469Ssklower { 0 }, 29636408Ssklower #endif ISO 29736408Ssklower /* IN_CLNS */ 29836408Ssklower #ifdef INET 29944423Ssklower { AF_INET, in_putnetaddr, in_getnetaddr, in_cmpnetaddr, 30036408Ssklower in_putsufx, in_getsufx, 30136408Ssklower in_recycle_tsuffix, 30236408Ssklower tpip_mtu, in_pcbbind, in_pcbconnect, 30336408Ssklower in_pcbdisconnect, in_pcbdetach, 30436408Ssklower in_pcballoc, 30536408Ssklower tpip_output, tpip_output_dg, /* nl_ctloutput */ NULL, 30636408Ssklower (caddr_t) &tp_inpcb, 30736408Ssklower }, 30837469Ssklower #else 30937469Ssklower { 0 }, 31036408Ssklower #endif INET 31136408Ssklower /* ISO_CONS */ 312*45900Ssklower #if defined(ISO) && defined(TPCONS) 31344423Ssklower { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr, 31436408Ssklower iso_putsufx, iso_getsufx, 31536408Ssklower iso_recycle_tsuffix, 316*45900Ssklower tpcons_mtu, iso_pcbbind, tpcons_pcbconnect, 31736408Ssklower iso_pcbdisconnect, iso_pcbdetach, 31836408Ssklower iso_pcballoc, 319*45900Ssklower tpcons_output, tpcons_output, iso_nlctloutput, 32036408Ssklower (caddr_t) &tp_isopcb, 32136408Ssklower }, 32237469Ssklower #else 32337469Ssklower { 0 }, 32437469Ssklower #endif ISO_CONS 32537469Ssklower /* End of protosw marker */ 32637469Ssklower { 0 } 32736408Ssklower }; 32836408Ssklower 32936408Ssklower /* 33036408Ssklower * NAME: tp_init() 33136408Ssklower * 33236408Ssklower * CALLED FROM: 33336408Ssklower * autoconf through the protosw structure 33436408Ssklower * 33536408Ssklower * FUNCTION: 33636408Ssklower * initialize tp machine 33736408Ssklower * 33836408Ssklower * RETURNS: Nada 33936408Ssklower * 34036408Ssklower * SIDE EFFECTS: 34136408Ssklower * 34236408Ssklower * NOTES: 34336408Ssklower */ 34437469Ssklower int 34536408Ssklower tp_init() 34636408Ssklower { 34736408Ssklower static int init_done=0; 34836408Ssklower void tp_timerinit(); 34936408Ssklower 35036408Ssklower if (init_done++) 35137469Ssklower return 0; 35236408Ssklower 35336408Ssklower 35436408Ssklower /* FOR INET */ 35536408Ssklower tp_inpcb.inp_next = tp_inpcb.inp_prev = &tp_inpcb; 35636408Ssklower /* FOR ISO */ 35736408Ssklower tp_isopcb.isop_next = tp_isopcb.isop_prev = &tp_isopcb; 35836408Ssklower 35939923Ssklower tp_start_win = 2; 36039923Ssklower 36136408Ssklower tp_timerinit(); 36236408Ssklower bzero((caddr_t)&tp_stat, sizeof(struct tp_stat)); 36337469Ssklower return 0; 36436408Ssklower } 36536408Ssklower 36636408Ssklower /* 36736408Ssklower * NAME: tp_soisdisconnecting() 36836408Ssklower * 36936408Ssklower * CALLED FROM: 37036408Ssklower * tp.trans 37136408Ssklower * 37236408Ssklower * FUNCTION and ARGUMENTS: 37336408Ssklower * Set state of the socket (so) to reflect that fact that we're disconnectING 37436408Ssklower * 37536408Ssklower * RETURNS: Nada 37636408Ssklower * 37736408Ssklower * SIDE EFFECTS: 37836408Ssklower * 37936408Ssklower * NOTES: 38036408Ssklower * This differs from the regular soisdisconnecting() in that the latter 38136408Ssklower * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags. 38236408Ssklower * We don't want to set those flags because those flags will cause 38336408Ssklower * a SIGPIPE to be delivered in sosend() and we don't like that. 38436408Ssklower * If anyone else is sleeping on this socket, wake 'em up. 38536408Ssklower */ 38636408Ssklower void 38736408Ssklower tp_soisdisconnecting(so) 38836408Ssklower register struct socket *so; 38936408Ssklower { 39038841Ssklower soisdisconnecting(so); 39138841Ssklower so->so_state &= ~SS_CANTSENDMORE; 39236408Ssklower IFPERF(sototpcb(so)) 39336408Ssklower register struct tp_pcb *tpcb = sototpcb(so); 39436408Ssklower u_int fsufx, lsufx; 39536408Ssklower 39637469Ssklower bcopy ((caddr_t)tpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) ); 39737469Ssklower bcopy ((caddr_t)tpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) ); 39836408Ssklower 39937469Ssklower tpmeas(tpcb->tp_lref, TPtime_close, &time, fsufx, lsufx, tpcb->tp_fref); 40036408Ssklower tpcb->tp_perf_on = 0; /* turn perf off */ 40136408Ssklower ENDPERF 40236408Ssklower } 40336408Ssklower 40436408Ssklower 40536408Ssklower /* 40636408Ssklower * NAME: tp_soisdisconnected() 40736408Ssklower * 40836408Ssklower * CALLED FROM: 40936408Ssklower * tp.trans 41036408Ssklower * 41136408Ssklower * FUNCTION and ARGUMENTS: 41236408Ssklower * Set state of the socket (so) to reflect that fact that we're disconnectED 41336408Ssklower * Set the state of the reference structure to closed, and 41436408Ssklower * recycle the suffix. 41536408Ssklower * Start a reference timer. 41636408Ssklower * 41736408Ssklower * RETURNS: Nada 41836408Ssklower * 41936408Ssklower * SIDE EFFECTS: 42036408Ssklower * 42136408Ssklower * NOTES: 42236408Ssklower * This differs from the regular soisdisconnected() in that the latter 42336408Ssklower * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags. 42436408Ssklower * We don't want to set those flags because those flags will cause 42536408Ssklower * a SIGPIPE to be delivered in sosend() and we don't like that. 42636408Ssklower * If anyone else is sleeping on this socket, wake 'em up. 42736408Ssklower */ 42836408Ssklower void 42936408Ssklower tp_soisdisconnected(tpcb) 43036408Ssklower register struct tp_pcb *tpcb; 43136408Ssklower { 43236408Ssklower register struct socket *so = tpcb->tp_sock; 43336408Ssklower 43438841Ssklower soisdisconnecting(so); 43538841Ssklower so->so_state &= ~SS_CANTSENDMORE; 43636408Ssklower IFPERF(sototpcb(so)) 43737469Ssklower register struct tp_pcb *ttpcb = sototpcb(so); 43836408Ssklower u_int fsufx, lsufx; 43936408Ssklower 44036408Ssklower /* CHOKE */ 44137469Ssklower bcopy ((caddr_t)ttpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) ); 44237469Ssklower bcopy ((caddr_t)ttpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) ); 44336408Ssklower 44437469Ssklower tpmeas(ttpcb->tp_lref, TPtime_close, 44537469Ssklower &time, &lsufx, &fsufx, ttpcb->tp_fref); 44636408Ssklower tpcb->tp_perf_on = 0; /* turn perf off */ 44736408Ssklower ENDPERF 44836408Ssklower 44936408Ssklower tpcb->tp_refp->tpr_state = REF_FROZEN; 45036408Ssklower tp_recycle_tsuffix( tpcb ); 45136408Ssklower tp_etimeout(tpcb->tp_refp, TM_reference, 0,0,0, (int)tpcb->tp_refer_ticks); 45236408Ssklower } 45336408Ssklower 45436408Ssklower int tp_maxrefopen; /* highest reference # of the set of open tp connections */ 45536408Ssklower 45636408Ssklower /* 45736408Ssklower * NAME: tp_freeref() 45836408Ssklower * 45936408Ssklower * CALLED FROM: 46036408Ssklower * tp.trans when the reference timer goes off, and 46136408Ssklower * from tp_attach() and tp_detach() when a tpcb is partially set up but not 46236408Ssklower * set up enough to have a ref timer set for it, and it's discarded 46336408Ssklower * due to some sort of error or an early close() 46436408Ssklower * 46536408Ssklower * FUNCTION and ARGUMENTS: 46636408Ssklower * Frees the reference represented by (r) for re-use. 46736408Ssklower * 46836408Ssklower * RETURNS: Nothing 46936408Ssklower * 47036408Ssklower * SIDE EFFECTS: 47136408Ssklower * 47236408Ssklower * NOTES: better be called at clock priority !!!!! 47336408Ssklower */ 47436408Ssklower void 47536408Ssklower tp_freeref(r) 47636408Ssklower register struct tp_ref *r; 47736408Ssklower { 47836408Ssklower IFDEBUG(D_TIMER) 47936408Ssklower printf("tp_freeref called for ref %d maxrefopen %d\n", 48036408Ssklower r - tp_ref, tp_maxrefopen); 48136408Ssklower ENDDEBUG 48236408Ssklower IFTRACE(D_TIMER) 48336408Ssklower tptrace(TPPTmisc, "tp_freeref ref tp_maxrefopen", 48436408Ssklower r - tp_ref, tp_maxrefopen, 0, 0); 48536408Ssklower ENDTRACE 48636408Ssklower r->tpr_state = REF_FREE; 48736408Ssklower IFDEBUG(D_CONN) 48836408Ssklower printf("tp_freeref: CLEARING tpr_pcb 0x%x\n", r->tpr_pcb); 48936408Ssklower ENDDEBUG 49036408Ssklower r->tpr_pcb = (struct tp_pcb *)0; 49136408Ssklower 49236408Ssklower r = &tp_ref[tp_maxrefopen]; 49336408Ssklower 49436408Ssklower while( tp_maxrefopen > 0 ) { 49536408Ssklower if(r->tpr_state ) 49636408Ssklower break; 49736408Ssklower tp_maxrefopen--; 49836408Ssklower r--; 49936408Ssklower } 50036408Ssklower IFDEBUG(D_TIMER) 50136408Ssklower printf("tp_freeref ends w/ maxrefopen %d\n", tp_maxrefopen); 50236408Ssklower ENDDEBUG 50336408Ssklower } 50436408Ssklower 50536408Ssklower /* 50636408Ssklower * NAME: tp_getref() 50736408Ssklower * 50836408Ssklower * CALLED FROM: 50936408Ssklower * tp_attach() 51036408Ssklower * 51136408Ssklower * FUNCTION and ARGUMENTS: 51236408Ssklower * obtains the next free reference and allocates the appropriate 51336408Ssklower * ref structure, links that structure to (tpcb) 51436408Ssklower * 51536408Ssklower * RETURN VALUE: 51636408Ssklower * a reference number 51736408Ssklower * or TP_ENOREF 51836408Ssklower * 51936408Ssklower * SIDE EFFECTS: 52036408Ssklower * 52136408Ssklower * NOTES: 52236408Ssklower */ 52336408Ssklower static RefNum 52436408Ssklower tp_getref(tpcb) 52536408Ssklower register struct tp_pcb *tpcb; 52636408Ssklower { 52736408Ssklower register struct tp_ref *r = tp_ref; 52836408Ssklower register int i=1; 52936408Ssklower 53036408Ssklower r++; /* tp_ref[0] is never used */ 53136408Ssklower 53236408Ssklower /* REF_FREE is zero */ 53336408Ssklower while( r->tpr_state ) { 53436408Ssklower r++; 53536408Ssklower if ( i == N_TPREF ) { 53636408Ssklower return TP_ENOREF; 53736408Ssklower } 53836408Ssklower i++; 53936408Ssklower } 54036408Ssklower r->tpr_state = REF_OPENING; 54136408Ssklower if (tp_maxrefopen < i) 54236408Ssklower tp_maxrefopen = i; 54336408Ssklower r->tpr_pcb = tpcb; 54436408Ssklower tpcb->tp_refp = r; 54536408Ssklower 54636408Ssklower return i; 54736408Ssklower } 54836408Ssklower 54936408Ssklower /* 55036408Ssklower * NAME: tp_attach() 55136408Ssklower * 55236408Ssklower * CALLED FROM: 55336408Ssklower * tp_usrreq, PRU_ATTACH 55436408Ssklower * 55536408Ssklower * FUNCTION and ARGUMENTS: 55636408Ssklower * given a socket (so) and a protocol family (dom), allocate a tpcb 55736408Ssklower * and ref structure, initialize everything in the structures that 55836408Ssklower * needs to be initialized. 55936408Ssklower * 56036408Ssklower * RETURN VALUE: 56136408Ssklower * 0 ok 56236408Ssklower * EINVAL if DEBUG(X) in is on and a disaster has occurred 56336408Ssklower * ENOPROTOOPT if TP hasn't been configured or if the 56436408Ssklower * socket wasn't created with tp as its protocol 56536408Ssklower * EISCONN if this socket is already part of a connection 56636408Ssklower * ETOOMANYREFS if ran out of tp reference numbers. 56736408Ssklower * E* whatever error is returned from soreserve() 56836408Ssklower * for from the network-layer pcb allocation routine 56936408Ssklower * 57036408Ssklower * SIDE EFFECTS: 57136408Ssklower * 57236408Ssklower * NOTES: 57336408Ssklower */ 57437469Ssklower tp_attach(so, dom) 57536408Ssklower struct socket *so; 57636408Ssklower int dom; 57736408Ssklower { 57836408Ssklower register struct tp_pcb *tpcb; 57936408Ssklower int error; 58036408Ssklower int protocol = so->so_proto->pr_protocol; 58136408Ssklower extern struct tp_conn_param tp_conn_param[]; 58236408Ssklower 58336408Ssklower IFDEBUG(D_CONN) 58436408Ssklower printf("tp_attach:dom 0x%x so 0x%x ", dom, so); 58536408Ssklower ENDDEBUG 58636408Ssklower IFTRACE(D_CONN) 58736408Ssklower tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0); 58836408Ssklower ENDTRACE 58936408Ssklower if ( ! tp_param.tpp_configed ) { 59036408Ssklower error = ENOPROTOOPT; /* protocol not available */ 59136408Ssklower goto bad2; 59236408Ssklower } 59336408Ssklower 59436408Ssklower if (so->so_pcb != NULL) { 59536408Ssklower return EISCONN; /* socket already part of a connection*/ 59636408Ssklower } 59736408Ssklower 59836408Ssklower error = soreserve(so, TP_SOCKBUFSIZE, TP_SOCKBUFSIZE); 59936408Ssklower /* later an ioctl will allow reallocation IF still in closed state */ 60036408Ssklower 60136408Ssklower if (error) 60236408Ssklower goto bad2; 60336408Ssklower 60437469Ssklower MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT); 60537469Ssklower if (tpcb == NULL) { 60636408Ssklower error = ENOBUFS; 60736408Ssklower goto bad2; 60836408Ssklower } 60936408Ssklower bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) ); 61036408Ssklower 61136408Ssklower if ( ((tpcb->tp_lref = tp_getref(tpcb)) & TP_ENOREF) != 0 ) { 61236408Ssklower error = ETOOMANYREFS; 61336408Ssklower goto bad3; 61436408Ssklower } 61536408Ssklower tpcb->tp_sock = so; 61636408Ssklower tpcb->tp_domain = dom; 61736408Ssklower if (protocol<ISOPROTO_TP4) { 61836408Ssklower tpcb->tp_netservice = ISO_CONS; 61936408Ssklower tpcb->tp_snduna = (SeqNum) -1;/* kludge so the pseudo-ack from the CR/CC 62036408Ssklower * will generate correct fake-ack values 62136408Ssklower */ 62236408Ssklower } else { 62336408Ssklower tpcb->tp_netservice = (dom== AF_INET)?IN_CLNS:ISO_CLNS; 62436408Ssklower /* the default */ 62536408Ssklower } 62636408Ssklower tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice]; 62736408Ssklower 62836408Ssklower tpcb->tp_cong_win = 1; 62936408Ssklower tpcb->tp_state = TP_CLOSED; 63036408Ssklower tpcb->tp_vers = TP_VERSION; 63136408Ssklower 63236408Ssklower /* Spec says default is 128 octets, 63336408Ssklower * that is, if the tpdusize argument never appears, use 128. 63436408Ssklower * As the initiator, we will always "propose" the 2048 63536408Ssklower * size, that is, we will put this argument in the CR 63636408Ssklower * always, but accept what the other side sends on the CC. 63736408Ssklower * If the initiator sends us something larger on a CR, 63836408Ssklower * we'll respond w/ this. 63936408Ssklower * Our maximum is 4096. See tp_chksum.c comments. 64036408Ssklower */ 64136408Ssklower tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize; 64236408Ssklower 64336408Ssklower tpcb->tp_seqmask = TP_NML_FMT_MASK; 64436408Ssklower tpcb->tp_seqbit = TP_NML_FMT_BIT; 64536408Ssklower tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; 64636408Ssklower tpcb->tp_sndhiwat = (SeqNum) - 1; /* a kludge but it works */ 64736408Ssklower tpcb->tp_s_subseq = 0; 64836408Ssklower 64936408Ssklower /* attach to a network-layer protoswitch */ 65036408Ssklower /* new way */ 65136408Ssklower tpcb->tp_nlproto = & nl_protosw[tpcb->tp_netservice]; 65236408Ssklower ASSERT( tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain); 65336408Ssklower #ifdef notdef 65436408Ssklower /* OLD WAY */ 65536408Ssklower /* TODO: properly, this search would be on the basis of 65636408Ssklower * domain,netservice or just netservice only (if you have 65736408Ssklower * IN_CLNS, ISO_CLNS, and ISO_CONS) 65836408Ssklower */ 65936408Ssklower tpcb->tp_nlproto = nl_protosw; 66036408Ssklower while(tpcb->tp_nlproto->nlp_afamily != tpcb->tp_domain ) { 66136408Ssklower if( tpcb->tp_nlproto->nlp_afamily == 0 ) { 66236408Ssklower error = EAFNOSUPPORT; 66336408Ssklower goto bad4; 66436408Ssklower } 66536408Ssklower tpcb->tp_nlproto ++; 66636408Ssklower } 66736408Ssklower #endif notdef 66836408Ssklower 66936408Ssklower /* xx_pcballoc sets so_pcb */ 67036408Ssklower if ( error = (tpcb->tp_nlproto->nlp_pcballoc) ( 67136408Ssklower so, tpcb->tp_nlproto->nlp_pcblist ) ) { 67236408Ssklower goto bad4; 67336408Ssklower } 67436408Ssklower 67536408Ssklower if( dom == AF_INET ) 67636408Ssklower sotoinpcb(so)->inp_ppcb = (caddr_t) tpcb; 67736408Ssklower /* nothing to do for iso case */ 67836408Ssklower 67936408Ssklower tpcb->tp_npcb = (caddr_t) so->so_pcb; 68036408Ssklower so->so_tpcb = (caddr_t) tpcb; 68136408Ssklower 68236408Ssklower return 0; 68336408Ssklower 68436408Ssklower bad4: 68536408Ssklower IFDEBUG(D_CONN) 68636408Ssklower printf("BAD4 in tp_attach, so 0x%x\n", so); 68736408Ssklower ENDDEBUG 68836408Ssklower tp_freeref(tpcb->tp_refp); 68936408Ssklower 69036408Ssklower bad3: 69136408Ssklower IFDEBUG(D_CONN) 69236408Ssklower printf("BAD3 in tp_attach, so 0x%x\n", so); 69336408Ssklower ENDDEBUG 69436408Ssklower 69537469Ssklower free((caddr_t)tpcb, M_PCB); /* never a cluster */ 69636408Ssklower 69736408Ssklower bad2: 69836408Ssklower IFDEBUG(D_CONN) 69936408Ssklower printf("BAD2 in tp_attach, so 0x%x\n", so); 70036408Ssklower ENDDEBUG 70136408Ssklower so->so_pcb = 0; 70236408Ssklower so->so_tpcb = 0; 70336408Ssklower sofree(so); 70436408Ssklower 70537469Ssklower /*bad:*/ 70636408Ssklower IFDEBUG(D_CONN) 70736408Ssklower printf("BAD in tp_attach, so 0x%x\n", so); 70836408Ssklower ENDDEBUG 70936408Ssklower return error; 71036408Ssklower } 71136408Ssklower 71236408Ssklower /* 71336408Ssklower * NAME: tp_detach() 71436408Ssklower * 71536408Ssklower * CALLED FROM: 71636408Ssklower * tp.trans, on behalf of a user close request 71736408Ssklower * and when the reference timer goes off 71836408Ssklower * (if the disconnect was initiated by the protocol entity 71936408Ssklower * rather than by the user) 72036408Ssklower * 72136408Ssklower * FUNCTION and ARGUMENTS: 72236408Ssklower * remove the tpcb structure from the list of active or 72336408Ssklower * partially active connections, recycle all the mbufs 72436408Ssklower * associated with the pcb, ref structure, sockbufs, etc. 72536408Ssklower * Only free the ref structure if you know that a ref timer 72636408Ssklower * wasn't set for this tpcb. 72736408Ssklower * 72836408Ssklower * RETURNS: Nada 72936408Ssklower * 73036408Ssklower * SIDE EFFECTS: 73136408Ssklower * 73236408Ssklower * NOTES: 73336408Ssklower * tp_soisdisconnected() was already when this is called 73436408Ssklower */ 73536408Ssklower void 73636408Ssklower tp_detach(tpcb) 73736408Ssklower register struct tp_pcb *tpcb; 73836408Ssklower { 73936408Ssklower void tp_freeref(); 74036408Ssklower register struct socket *so = tpcb->tp_sock; 74136408Ssklower 74236408Ssklower IFDEBUG(D_CONN) 74337469Ssklower printf("tp_detach(tpcb 0x%x, so 0x%x)\n", 74437469Ssklower tpcb,so); 74536408Ssklower ENDDEBUG 74636408Ssklower IFTRACE(D_CONN) 74736408Ssklower tptraceTPCB(TPPTmisc, "tp_detach tpcb so lsufx", 74839196Ssklower tpcb, so, *(u_short *)(tpcb->tp_lsuffix), 0); 74936408Ssklower ENDTRACE 75036408Ssklower 75136408Ssklower if (so->so_head) { 75236408Ssklower if (!soqremque(so, 0) && !soqremque(so, 1)) 75336408Ssklower panic("sofree dq"); 75436408Ssklower so->so_head = 0; 75536408Ssklower } 75636408Ssklower 75736408Ssklower IFDEBUG(D_CONN) 75836408Ssklower printf("tp_detach(freeing RTC list snduna 0x%x rcvnxt 0x%x)\n", 75936408Ssklower tpcb->tp_snduna_rtc, 76036408Ssklower tpcb->tp_rcvnxt_rtc); 76136408Ssklower ENDDEBUG 76236408Ssklower 76336408Ssklower #define FREE_RTC_LIST(XXX)\ 76436408Ssklower { register struct tp_rtc *xxr = XXX, *xxs; while (xxr) {\ 76536408Ssklower xxs = xxr->tprt_next;\ 76636408Ssklower m_freem( xxr->tprt_data );\ 76736408Ssklower m_free( dtom(xxr) ); xxr = xxs; }\ 76836408Ssklower XXX = (struct tp_rtc *)0;\ 76936408Ssklower } 77036408Ssklower 77136408Ssklower FREE_RTC_LIST( tpcb->tp_snduna_rtc ); 77236408Ssklower tpcb->tp_sndhiwat_rtc = (struct tp_rtc *)0; 77336408Ssklower 77436408Ssklower FREE_RTC_LIST( tpcb->tp_rcvnxt_rtc ); 77536408Ssklower 77636408Ssklower #undef FREE_RTC_LIST 77736408Ssklower 77836408Ssklower IFDEBUG(D_CONN) 77936408Ssklower printf("calling (...nlproto->...)(0x%x, so 0x%x)\n", 78036408Ssklower so->so_pcb, so); 78136408Ssklower printf("so 0x%x so_head 0x%x, qlen %d q0len %d qlimit %d\n", 78236408Ssklower so, so->so_head, 78336408Ssklower so->so_q0len, so->so_qlen, so->so_qlimit); 78436408Ssklower ENDDEBUG 78536408Ssklower 78637469Ssklower if ( tpcb->tp_flags & (TPF_DISC_DATA_OUT | TPF_CONN_DATA_OUT ) ) { 78736408Ssklower ASSERT( so->so_snd.sb_cc != 0 ); 78836408Ssklower IFDEBUG(D_CONN) 78936408Ssklower printf( 79036408Ssklower "detach, flags 0x%x doing sbdrop on so_snd, mb 0x%x cc 0x%x\n", 79136408Ssklower tpcb->tp_flags, so->so_snd.sb_mb, so->so_snd.sb_cc); 79236408Ssklower dump_mbuf( so->so_snd.sb_mb, "detach so snd: \n"); 79336408Ssklower ENDDEBUG 79436408Ssklower if ( so->so_snd.sb_cc != 0 ) 79537469Ssklower sbflush(&so->so_snd); 79636408Ssklower tpcb->tp_flags &= ~(TPF_CONN_DATA_OUT | TPF_DISC_DATA_OUT); 79736408Ssklower } 79836408Ssklower if ( tpcb->tp_flags & (TPF_DISC_DATA_IN | TPF_CONN_DATA_IN ) ) { 79936408Ssklower ASSERT( tpcb->tp_Xrcv.sb_cc != 0 ); 80036408Ssklower IFDEBUG(D_CONN) 80136408Ssklower printf( 80236408Ssklower "detach, flags 0x%x doing sbdrop on tp_Xrcv, mb 0x%x cc 0x%x\n", 80336408Ssklower tpcb->tp_flags, tpcb->tp_Xrcv.sb_mb, tpcb->tp_Xrcv.sb_cc); 80436408Ssklower dump_mbuf( tpcb->tp_Xrcv.sb_mb, "detach Xrcv: \n"); 80536408Ssklower ENDDEBUG 80636408Ssklower if( tpcb->tp_Xrcv.sb_cc != 0 ) 80737469Ssklower sbdrop(&tpcb->tp_Xrcv, (int)tpcb->tp_Xrcv.sb_cc); 80836408Ssklower tpcb->tp_flags &= ~(TPF_CONN_DATA_IN | TPF_DISC_DATA_IN); 80936408Ssklower } 81036408Ssklower 81136408Ssklower IFDEBUG(D_CONN) 81236408Ssklower printf("so_snd at 0x%x so_rcv at 0x%x\n", &so->so_snd, &so->so_rcv); 81336408Ssklower dump_mbuf(so->so_snd.sb_mb, "so_snd at detach "); 81436408Ssklower printf("about to call LL detach, nlproto 0x%x, nl_detach 0x%x\n", 81536408Ssklower tpcb->tp_nlproto, tpcb->tp_nlproto->nlp_pcbdetach); 81636408Ssklower ENDDEBUG 81736408Ssklower 81836408Ssklower 81937469Ssklower 82037469Ssklower (tpcb->tp_nlproto->nlp_pcbdetach)((struct inpcb *)so->so_pcb); 82137469Ssklower /* does an sofree(so) */ 82237469Ssklower 82336408Ssklower IFDEBUG(D_CONN) 82436408Ssklower printf("after xxx_pcbdetach\n"); 82536408Ssklower ENDDEBUG 82636408Ssklower 82736408Ssklower if( tpcb->tp_refp->tpr_state == REF_OPENING ) { 82836408Ssklower /* no connection existed here so no reference timer will be called */ 82936408Ssklower IFDEBUG(D_CONN) 83036408Ssklower printf("SETTING ref %d, 0x%x to REF_FREE\n", tpcb->tp_lref, 83136408Ssklower tpcb->tp_refp - &tp_ref[0]); 83236408Ssklower ENDDEBUG 83336408Ssklower 83436408Ssklower tp_freeref(tpcb->tp_refp); 83536408Ssklower } 83636408Ssklower 83737469Ssklower if (tpcb->tp_Xsnd.sb_mb) { 83837469Ssklower printf("Unsent Xdata on detach; would panic"); 83937469Ssklower sbflush(&tpcb->tp_Xsnd); 84037469Ssklower } 84136408Ssklower so->so_tpcb = (caddr_t)0; 84236408Ssklower 84336408Ssklower /* 84436408Ssklower * Get rid of the cluster mbuf allocated for performance measurements, if 84536408Ssklower * there is one. Note that tpcb->tp_perf_on says nothing about whether or 84636408Ssklower * not a cluster mbuf was allocated, so you have to check for a pointer 84736408Ssklower * to one (that is, we need the TP_PERF_MEASs around the following section 84836408Ssklower * of code, not the IFPERFs) 84936408Ssklower */ 85036408Ssklower #ifdef TP_PERF_MEAS 85137469Ssklower if(tpcb->tp_p_mbuf) { 85237469Ssklower register struct mbuf *m = tpcb->tp_p_mbuf; 85337469Ssklower struct mbuf *n; 85436408Ssklower IFDEBUG(D_PERF_MEAS) 85536408Ssklower printf("freeing tp_p_meas 0x%x ", tpcb->tp_p_meas); 85636408Ssklower ENDDEBUG 85737469Ssklower do { 85837469Ssklower MFREE(m, n); 85937469Ssklower m = n; 86037469Ssklower } while (n); 86137469Ssklower tpcb->tp_p_meas = 0; 86237469Ssklower tpcb->tp_p_mbuf = 0; 86336408Ssklower } 86436408Ssklower #endif TP_PERF_MEAS 86536408Ssklower 86636408Ssklower IFDEBUG(D_CONN) 86737469Ssklower printf( "end of detach, NOT single, tpcb 0x%x\n", tpcb); 86836408Ssklower ENDDEBUG 86937469Ssklower /* free((caddr_t)tpcb, M_PCB); WHere to put this ? */ 87036408Ssklower } 871