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