136408Ssklower /*********************************************************** 236408Ssklower 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 $ 3236408Ssklower * 3336408Ssklower * 3436408Ssklower * This is the initialization and cleanup stuff - 3536408Ssklower * for the tp machine in general as well as for the individual pcbs. 3636408Ssklower * tp_init() is called at system startup. tp_attach() and tp_getref() are 3736408Ssklower * called when a socket is created. tp_detach() and tp_freeref() 3836408Ssklower * are called during the closing stage and/or when the reference timer 3936408Ssklower * goes off. 4036408Ssklower * tp_soisdisconnecting() and tp_soisdisconnected() are tp-specific 4136408Ssklower * versions of soisconnect* 4236408Ssklower * and are called (obviously) during the closing phase. 4336408Ssklower * 4436408Ssklower */ 4536408Ssklower 4636408Ssklower #ifndef lint 4736408Ssklower static char *rcsid = "$Header: tp_pcb.c,v 5.4 88/11/18 17:28:24 nhall Exp $"; 4836408Ssklower #endif lint 4936408Ssklower 5036408Ssklower #include "argoxtwentyfive.h" 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" 59*37469Ssklower #include "argo_debug.h" 60*37469Ssklower #include "tp_param.h" 61*37469Ssklower #include "tp_timer.h" 62*37469Ssklower #include "tp_ip.h" 63*37469Ssklower #include "tp_stat.h" 64*37469Ssklower #include "tp_pcb.h" 65*37469Ssklower #include "tp_tpdu.h" 66*37469Ssklower #include "tp_trace.h" 67*37469Ssklower #include "tp_meas.h" 68*37469Ssklower #include "tp_seq.h" 69*37469Ssklower #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 */ 11636408Ssklower 0, /* 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 */ 15136408Ssklower 0, /* 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(); 23236408Ssklower int in_putsufx(); 23336408Ssklower int in_getsufx(); 23436408Ssklower int in_recycle_tsuffix(); 23536408Ssklower int tpip_mtu(); 23636408Ssklower int in_pcbbind(); 23736408Ssklower int in_pcbconnect(); 23836408Ssklower int in_pcbdisconnect(); 23936408Ssklower int in_pcbdetach(); 24036408Ssklower int in_pcballoc(); 24136408Ssklower int tpip_output(); 24236408Ssklower int tpip_output_dg(); 24336408Ssklower struct inpcb tp_inpcb; 24436408Ssklower #endif INET 24536408Ssklower #ifdef ISO 24636408Ssklower int iso_putnetaddr(); 24736408Ssklower int iso_getnetaddr(); 24836408Ssklower int iso_putsufx(); 24936408Ssklower int iso_getsufx(); 25036408Ssklower int iso_recycle_tsuffix(); 25136408Ssklower int tpclnp_mtu(); 25236408Ssklower int iso_pcbbind(); 25336408Ssklower int iso_pcbconnect(); 25436408Ssklower int iso_pcbdisconnect(); 25536408Ssklower int iso_pcbdetach(); 25636408Ssklower int iso_pcballoc(); 25736408Ssklower int tpclnp_output(); 25836408Ssklower int tpclnp_output_dg(); 25936408Ssklower int iso_nlctloutput(); 26036408Ssklower struct isopcb tp_isopcb; 26136408Ssklower #endif ISO 26236408Ssklower #if NARGOXTWENTYFIVE > 0 26336408Ssklower int iso_putnetaddr(); 26436408Ssklower int iso_getnetaddr(); 26536408Ssklower int iso_putsufx(); 26636408Ssklower int iso_getsufx(); 26736408Ssklower int iso_recycle_tsuffix(); 26836408Ssklower int tpcons_mtu(); 26936408Ssklower int iso_pcbbind(); 27036408Ssklower int iso_pcbconnect(); 27136408Ssklower int iso_pcbdisconnect(); 27236408Ssklower int iso_pcbdetach(); 27336408Ssklower int iso_pcballoc(); 27436408Ssklower int tpcons_output(); 27536408Ssklower int tpcons_output_dg(); 27636408Ssklower struct isopcb tp_isopcb; 27736408Ssklower #endif NARGOXTWENTYFIVE 27836408Ssklower 279*37469Ssklower 28036408Ssklower struct nl_protosw nl_protosw[] = { 28136408Ssklower /* ISO_CLNS */ 28236408Ssklower #ifdef ISO 28336408Ssklower { AF_ISO, iso_putnetaddr, iso_getnetaddr, 28436408Ssklower iso_putsufx, iso_getsufx, 28536408Ssklower iso_recycle_tsuffix, 28636408Ssklower tpclnp_mtu, iso_pcbbind, iso_pcbconnect, 28736408Ssklower iso_pcbdisconnect, iso_pcbdetach, 28836408Ssklower iso_pcballoc, 28936408Ssklower tpclnp_output, tpclnp_output_dg, iso_nlctloutput, 29036408Ssklower (caddr_t) &tp_isopcb, 29136408Ssklower }, 292*37469Ssklower #else 293*37469Ssklower { 0 }, 29436408Ssklower #endif ISO 29536408Ssklower /* IN_CLNS */ 29636408Ssklower #ifdef INET 29736408Ssklower { AF_INET, in_putnetaddr, in_getnetaddr, 29836408Ssklower in_putsufx, in_getsufx, 29936408Ssklower in_recycle_tsuffix, 30036408Ssklower tpip_mtu, in_pcbbind, in_pcbconnect, 30136408Ssklower in_pcbdisconnect, in_pcbdetach, 30236408Ssklower in_pcballoc, 30336408Ssklower tpip_output, tpip_output_dg, /* nl_ctloutput */ NULL, 30436408Ssklower (caddr_t) &tp_inpcb, 30536408Ssklower }, 306*37469Ssklower #else 307*37469Ssklower { 0 }, 30836408Ssklower #endif INET 30936408Ssklower /* ISO_CONS */ 310*37469Ssklower #if defined(ISO) && (NARGOXTWENTYFIVE > 0) 31136408Ssklower { AF_ISO, iso_putnetaddr, iso_getnetaddr, 31236408Ssklower iso_putsufx, iso_getsufx, 31336408Ssklower iso_recycle_tsuffix, 31436408Ssklower tpcons_mtu, iso_pcbbind, iso_pcbconnect, 31536408Ssklower iso_pcbdisconnect, iso_pcbdetach, 31636408Ssklower iso_pcballoc, 31736408Ssklower tpcons_output, tpcons_output_dg, iso_nlctloutput, 31836408Ssklower (caddr_t) &tp_isopcb, 31936408Ssklower }, 320*37469Ssklower #else 321*37469Ssklower { 0 }, 322*37469Ssklower #endif ISO_CONS 323*37469Ssklower /* End of protosw marker */ 324*37469Ssklower { 0 } 32536408Ssklower }; 32636408Ssklower 32736408Ssklower /* 32836408Ssklower * NAME: tp_init() 32936408Ssklower * 33036408Ssklower * CALLED FROM: 33136408Ssklower * autoconf through the protosw structure 33236408Ssklower * 33336408Ssklower * FUNCTION: 33436408Ssklower * initialize tp machine 33536408Ssklower * 33636408Ssklower * RETURNS: Nada 33736408Ssklower * 33836408Ssklower * SIDE EFFECTS: 33936408Ssklower * 34036408Ssklower * NOTES: 34136408Ssklower */ 342*37469Ssklower int 34336408Ssklower tp_init() 34436408Ssklower { 34536408Ssklower static int init_done=0; 34636408Ssklower void tp_timerinit(); 34736408Ssklower 34836408Ssklower if (init_done++) 349*37469Ssklower return 0; 35036408Ssklower 35136408Ssklower 35236408Ssklower /* FOR INET */ 35336408Ssklower tp_inpcb.inp_next = tp_inpcb.inp_prev = &tp_inpcb; 35436408Ssklower /* FOR ISO */ 35536408Ssklower tp_isopcb.isop_next = tp_isopcb.isop_prev = &tp_isopcb; 35636408Ssklower 35736408Ssklower tp_timerinit(); 35836408Ssklower bzero((caddr_t)&tp_stat, sizeof(struct tp_stat)); 359*37469Ssklower return 0; 36036408Ssklower } 36136408Ssklower 36236408Ssklower /* 36336408Ssklower * NAME: tp_soisdisconnecting() 36436408Ssklower * 36536408Ssklower * CALLED FROM: 36636408Ssklower * tp.trans 36736408Ssklower * 36836408Ssklower * FUNCTION and ARGUMENTS: 36936408Ssklower * Set state of the socket (so) to reflect that fact that we're disconnectING 37036408Ssklower * 37136408Ssklower * RETURNS: Nada 37236408Ssklower * 37336408Ssklower * SIDE EFFECTS: 37436408Ssklower * 37536408Ssklower * NOTES: 37636408Ssklower * This differs from the regular soisdisconnecting() in that the latter 37736408Ssklower * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags. 37836408Ssklower * We don't want to set those flags because those flags will cause 37936408Ssklower * a SIGPIPE to be delivered in sosend() and we don't like that. 38036408Ssklower * If anyone else is sleeping on this socket, wake 'em up. 38136408Ssklower */ 38236408Ssklower void 38336408Ssklower tp_soisdisconnecting(so) 38436408Ssklower register struct socket *so; 38536408Ssklower { 38636408Ssklower so->so_state &= ~SS_ISCONNECTING; 38736408Ssklower so->so_state |= SS_ISDISCONNECTING; 38836408Ssklower if (so->so_head) { 38936408Ssklower if (!soqremque(so, 0) && !soqremque(so, 1)) 39036408Ssklower panic("tp_soisdisconnecting"); 39136408Ssklower so->so_head = 0; 39236408Ssklower } 39336408Ssklower wakeup((caddr_t)&so->so_timeo); 39436408Ssklower sowwakeup(so); 39536408Ssklower sorwakeup(so); 39636408Ssklower IFPERF(sototpcb(so)) 39736408Ssklower register struct tp_pcb *tpcb = sototpcb(so); 39836408Ssklower u_int fsufx, lsufx; 39936408Ssklower 400*37469Ssklower bcopy ((caddr_t)tpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) ); 401*37469Ssklower bcopy ((caddr_t)tpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) ); 40236408Ssklower 403*37469Ssklower tpmeas(tpcb->tp_lref, TPtime_close, &time, fsufx, lsufx, tpcb->tp_fref); 40436408Ssklower tpcb->tp_perf_on = 0; /* turn perf off */ 40536408Ssklower ENDPERF 40636408Ssklower } 40736408Ssklower 40836408Ssklower 40936408Ssklower /* 41036408Ssklower * NAME: tp_soisdisconnected() 41136408Ssklower * 41236408Ssklower * CALLED FROM: 41336408Ssklower * tp.trans 41436408Ssklower * 41536408Ssklower * FUNCTION and ARGUMENTS: 41636408Ssklower * Set state of the socket (so) to reflect that fact that we're disconnectED 41736408Ssklower * Set the state of the reference structure to closed, and 41836408Ssklower * recycle the suffix. 41936408Ssklower * Start a reference timer. 42036408Ssklower * 42136408Ssklower * RETURNS: Nada 42236408Ssklower * 42336408Ssklower * SIDE EFFECTS: 42436408Ssklower * 42536408Ssklower * NOTES: 42636408Ssklower * This differs from the regular soisdisconnected() in that the latter 42736408Ssklower * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags. 42836408Ssklower * We don't want to set those flags because those flags will cause 42936408Ssklower * a SIGPIPE to be delivered in sosend() and we don't like that. 43036408Ssklower * If anyone else is sleeping on this socket, wake 'em up. 43136408Ssklower */ 43236408Ssklower void 43336408Ssklower tp_soisdisconnected(tpcb) 43436408Ssklower register struct tp_pcb *tpcb; 43536408Ssklower { 43636408Ssklower register struct socket *so = tpcb->tp_sock; 43736408Ssklower 43836408Ssklower so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 43936408Ssklower if (so->so_head) { 44036408Ssklower if (!soqremque(so, 0) && !soqremque(so, 1)) 44136408Ssklower panic("tp_soisdisconnected"); 44236408Ssklower so->so_head = 0; 44336408Ssklower } 44436408Ssklower wakeup((caddr_t)&so->so_timeo); 44536408Ssklower sowwakeup(so); 44636408Ssklower sorwakeup(so); 44736408Ssklower IFPERF(sototpcb(so)) 448*37469Ssklower register struct tp_pcb *ttpcb = sototpcb(so); 44936408Ssklower u_int fsufx, lsufx; 45036408Ssklower 45136408Ssklower /* CHOKE */ 452*37469Ssklower bcopy ((caddr_t)ttpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) ); 453*37469Ssklower bcopy ((caddr_t)ttpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) ); 45436408Ssklower 455*37469Ssklower tpmeas(ttpcb->tp_lref, TPtime_close, 456*37469Ssklower &time, &lsufx, &fsufx, ttpcb->tp_fref); 45736408Ssklower tpcb->tp_perf_on = 0; /* turn perf off */ 45836408Ssklower ENDPERF 45936408Ssklower 46036408Ssklower tpcb->tp_refp->tpr_state = REF_FROZEN; 46136408Ssklower tp_recycle_tsuffix( tpcb ); 46236408Ssklower tp_etimeout(tpcb->tp_refp, TM_reference, 0,0,0, (int)tpcb->tp_refer_ticks); 46336408Ssklower } 46436408Ssklower 46536408Ssklower int tp_maxrefopen; /* highest reference # of the set of open tp connections */ 46636408Ssklower 46736408Ssklower /* 46836408Ssklower * NAME: tp_freeref() 46936408Ssklower * 47036408Ssklower * CALLED FROM: 47136408Ssklower * tp.trans when the reference timer goes off, and 47236408Ssklower * from tp_attach() and tp_detach() when a tpcb is partially set up but not 47336408Ssklower * set up enough to have a ref timer set for it, and it's discarded 47436408Ssklower * due to some sort of error or an early close() 47536408Ssklower * 47636408Ssklower * FUNCTION and ARGUMENTS: 47736408Ssklower * Frees the reference represented by (r) for re-use. 47836408Ssklower * 47936408Ssklower * RETURNS: Nothing 48036408Ssklower * 48136408Ssklower * SIDE EFFECTS: 48236408Ssklower * 48336408Ssklower * NOTES: better be called at clock priority !!!!! 48436408Ssklower */ 48536408Ssklower void 48636408Ssklower tp_freeref(r) 48736408Ssklower register struct tp_ref *r; 48836408Ssklower { 48936408Ssklower IFDEBUG(D_TIMER) 49036408Ssklower printf("tp_freeref called for ref %d maxrefopen %d\n", 49136408Ssklower r - tp_ref, tp_maxrefopen); 49236408Ssklower ENDDEBUG 49336408Ssklower IFTRACE(D_TIMER) 49436408Ssklower tptrace(TPPTmisc, "tp_freeref ref tp_maxrefopen", 49536408Ssklower r - tp_ref, tp_maxrefopen, 0, 0); 49636408Ssklower ENDTRACE 49736408Ssklower r->tpr_state = REF_FREE; 49836408Ssklower IFDEBUG(D_CONN) 49936408Ssklower printf("tp_freeref: CLEARING tpr_pcb 0x%x\n", r->tpr_pcb); 50036408Ssklower ENDDEBUG 50136408Ssklower r->tpr_pcb = (struct tp_pcb *)0; 50236408Ssklower 50336408Ssklower r = &tp_ref[tp_maxrefopen]; 50436408Ssklower 50536408Ssklower while( tp_maxrefopen > 0 ) { 50636408Ssklower if(r->tpr_state ) 50736408Ssklower break; 50836408Ssklower tp_maxrefopen--; 50936408Ssklower r--; 51036408Ssklower } 51136408Ssklower IFDEBUG(D_TIMER) 51236408Ssklower printf("tp_freeref ends w/ maxrefopen %d\n", tp_maxrefopen); 51336408Ssklower ENDDEBUG 51436408Ssklower } 51536408Ssklower 51636408Ssklower /* 51736408Ssklower * NAME: tp_getref() 51836408Ssklower * 51936408Ssklower * CALLED FROM: 52036408Ssklower * tp_attach() 52136408Ssklower * 52236408Ssklower * FUNCTION and ARGUMENTS: 52336408Ssklower * obtains the next free reference and allocates the appropriate 52436408Ssklower * ref structure, links that structure to (tpcb) 52536408Ssklower * 52636408Ssklower * RETURN VALUE: 52736408Ssklower * a reference number 52836408Ssklower * or TP_ENOREF 52936408Ssklower * 53036408Ssklower * SIDE EFFECTS: 53136408Ssklower * 53236408Ssklower * NOTES: 53336408Ssklower */ 53436408Ssklower static RefNum 53536408Ssklower tp_getref(tpcb) 53636408Ssklower register struct tp_pcb *tpcb; 53736408Ssklower { 53836408Ssklower register struct tp_ref *r = tp_ref; 53936408Ssklower register int i=1; 54036408Ssklower 54136408Ssklower r++; /* tp_ref[0] is never used */ 54236408Ssklower 54336408Ssklower /* REF_FREE is zero */ 54436408Ssklower while( r->tpr_state ) { 54536408Ssklower r++; 54636408Ssklower if ( i == N_TPREF ) { 54736408Ssklower return TP_ENOREF; 54836408Ssklower } 54936408Ssklower i++; 55036408Ssklower } 55136408Ssklower r->tpr_state = REF_OPENING; 55236408Ssklower if (tp_maxrefopen < i) 55336408Ssklower tp_maxrefopen = i; 55436408Ssklower r->tpr_pcb = tpcb; 55536408Ssklower tpcb->tp_refp = r; 55636408Ssklower 55736408Ssklower return i; 55836408Ssklower } 55936408Ssklower 56036408Ssklower /* 56136408Ssklower * NAME: tp_attach() 56236408Ssklower * 56336408Ssklower * CALLED FROM: 56436408Ssklower * tp_usrreq, PRU_ATTACH 56536408Ssklower * 56636408Ssklower * FUNCTION and ARGUMENTS: 56736408Ssklower * given a socket (so) and a protocol family (dom), allocate a tpcb 56836408Ssklower * and ref structure, initialize everything in the structures that 56936408Ssklower * needs to be initialized. 57036408Ssklower * 57136408Ssklower * RETURN VALUE: 57236408Ssklower * 0 ok 57336408Ssklower * EINVAL if DEBUG(X) in is on and a disaster has occurred 57436408Ssklower * ENOPROTOOPT if TP hasn't been configured or if the 57536408Ssklower * socket wasn't created with tp as its protocol 57636408Ssklower * EISCONN if this socket is already part of a connection 57736408Ssklower * ETOOMANYREFS if ran out of tp reference numbers. 57836408Ssklower * E* whatever error is returned from soreserve() 57936408Ssklower * for from the network-layer pcb allocation routine 58036408Ssklower * 58136408Ssklower * SIDE EFFECTS: 58236408Ssklower * 58336408Ssklower * NOTES: 58436408Ssklower */ 585*37469Ssklower tp_attach(so, dom) 58636408Ssklower struct socket *so; 58736408Ssklower int dom; 58836408Ssklower { 58936408Ssklower register struct tp_pcb *tpcb; 59036408Ssklower int error; 59136408Ssklower int protocol = so->so_proto->pr_protocol; 59236408Ssklower extern struct tp_conn_param tp_conn_param[]; 59336408Ssklower 59436408Ssklower IFDEBUG(D_CONN) 59536408Ssklower printf("tp_attach:dom 0x%x so 0x%x ", dom, so); 59636408Ssklower ENDDEBUG 59736408Ssklower IFTRACE(D_CONN) 59836408Ssklower tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0); 59936408Ssklower ENDTRACE 60036408Ssklower if ( ! tp_param.tpp_configed ) { 60136408Ssklower error = ENOPROTOOPT; /* protocol not available */ 60236408Ssklower goto bad2; 60336408Ssklower } 60436408Ssklower 60536408Ssklower if (so->so_pcb != NULL) { 60636408Ssklower return EISCONN; /* socket already part of a connection*/ 60736408Ssklower } 60836408Ssklower 60936408Ssklower error = soreserve(so, TP_SOCKBUFSIZE, TP_SOCKBUFSIZE); 61036408Ssklower /* later an ioctl will allow reallocation IF still in closed state */ 61136408Ssklower 61236408Ssklower if (error) 61336408Ssklower goto bad2; 61436408Ssklower 615*37469Ssklower MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT); 616*37469Ssklower if (tpcb == NULL) { 61736408Ssklower error = ENOBUFS; 61836408Ssklower goto bad2; 61936408Ssklower } 62036408Ssklower bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) ); 62136408Ssklower 62236408Ssklower if ( ((tpcb->tp_lref = tp_getref(tpcb)) & TP_ENOREF) != 0 ) { 62336408Ssklower error = ETOOMANYREFS; 62436408Ssklower goto bad3; 62536408Ssklower } 62636408Ssklower tpcb->tp_sock = so; 62736408Ssklower tpcb->tp_domain = dom; 62836408Ssklower if (protocol<ISOPROTO_TP4) { 62936408Ssklower tpcb->tp_netservice = ISO_CONS; 63036408Ssklower tpcb->tp_snduna = (SeqNum) -1;/* kludge so the pseudo-ack from the CR/CC 63136408Ssklower * will generate correct fake-ack values 63236408Ssklower */ 63336408Ssklower } else { 63436408Ssklower tpcb->tp_netservice = (dom== AF_INET)?IN_CLNS:ISO_CLNS; 63536408Ssklower /* the default */ 63636408Ssklower } 63736408Ssklower tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice]; 63836408Ssklower 63936408Ssklower tpcb->tp_cong_win = 1; 64036408Ssklower tpcb->tp_state = TP_CLOSED; 64136408Ssklower tpcb->tp_vers = TP_VERSION; 64236408Ssklower 64336408Ssklower /* Spec says default is 128 octets, 64436408Ssklower * that is, if the tpdusize argument never appears, use 128. 64536408Ssklower * As the initiator, we will always "propose" the 2048 64636408Ssklower * size, that is, we will put this argument in the CR 64736408Ssklower * always, but accept what the other side sends on the CC. 64836408Ssklower * If the initiator sends us something larger on a CR, 64936408Ssklower * we'll respond w/ this. 65036408Ssklower * Our maximum is 4096. See tp_chksum.c comments. 65136408Ssklower */ 65236408Ssklower tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize; 65336408Ssklower 65436408Ssklower tpcb->tp_seqmask = TP_NML_FMT_MASK; 65536408Ssklower tpcb->tp_seqbit = TP_NML_FMT_BIT; 65636408Ssklower tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; 65736408Ssklower tpcb->tp_sndhiwat = (SeqNum) - 1; /* a kludge but it works */ 65836408Ssklower tpcb->tp_s_subseq = 0; 65936408Ssklower 66036408Ssklower /* attach to a network-layer protoswitch */ 66136408Ssklower /* new way */ 66236408Ssklower tpcb->tp_nlproto = & nl_protosw[tpcb->tp_netservice]; 66336408Ssklower ASSERT( tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain); 66436408Ssklower #ifdef notdef 66536408Ssklower /* OLD WAY */ 66636408Ssklower /* TODO: properly, this search would be on the basis of 66736408Ssklower * domain,netservice or just netservice only (if you have 66836408Ssklower * IN_CLNS, ISO_CLNS, and ISO_CONS) 66936408Ssklower */ 67036408Ssklower tpcb->tp_nlproto = nl_protosw; 67136408Ssklower while(tpcb->tp_nlproto->nlp_afamily != tpcb->tp_domain ) { 67236408Ssklower if( tpcb->tp_nlproto->nlp_afamily == 0 ) { 67336408Ssklower error = EAFNOSUPPORT; 67436408Ssklower goto bad4; 67536408Ssklower } 67636408Ssklower tpcb->tp_nlproto ++; 67736408Ssklower } 67836408Ssklower #endif notdef 67936408Ssklower 68036408Ssklower /* xx_pcballoc sets so_pcb */ 68136408Ssklower if ( error = (tpcb->tp_nlproto->nlp_pcballoc) ( 68236408Ssklower so, tpcb->tp_nlproto->nlp_pcblist ) ) { 68336408Ssklower goto bad4; 68436408Ssklower } 68536408Ssklower 68636408Ssklower if( dom == AF_INET ) 68736408Ssklower sotoinpcb(so)->inp_ppcb = (caddr_t) tpcb; 68836408Ssklower /* nothing to do for iso case */ 68936408Ssklower 69036408Ssklower tpcb->tp_npcb = (caddr_t) so->so_pcb; 69136408Ssklower so->so_tpcb = (caddr_t) tpcb; 69236408Ssklower 69336408Ssklower return 0; 69436408Ssklower 69536408Ssklower bad4: 69636408Ssklower IFDEBUG(D_CONN) 69736408Ssklower printf("BAD4 in tp_attach, so 0x%x\n", so); 69836408Ssklower ENDDEBUG 69936408Ssklower tp_freeref(tpcb->tp_refp); 70036408Ssklower 70136408Ssklower bad3: 70236408Ssklower IFDEBUG(D_CONN) 70336408Ssklower printf("BAD3 in tp_attach, so 0x%x\n", so); 70436408Ssklower ENDDEBUG 70536408Ssklower 706*37469Ssklower free((caddr_t)tpcb, M_PCB); /* never a cluster */ 70736408Ssklower 70836408Ssklower bad2: 70936408Ssklower IFDEBUG(D_CONN) 71036408Ssklower printf("BAD2 in tp_attach, so 0x%x\n", so); 71136408Ssklower ENDDEBUG 71236408Ssklower so->so_pcb = 0; 71336408Ssklower so->so_tpcb = 0; 71436408Ssklower sofree(so); 71536408Ssklower 716*37469Ssklower /*bad:*/ 71736408Ssklower IFDEBUG(D_CONN) 71836408Ssklower printf("BAD in tp_attach, so 0x%x\n", so); 71936408Ssklower ENDDEBUG 72036408Ssklower return error; 72136408Ssklower } 72236408Ssklower 72336408Ssklower /* 72436408Ssklower * NAME: tp_detach() 72536408Ssklower * 72636408Ssklower * CALLED FROM: 72736408Ssklower * tp.trans, on behalf of a user close request 72836408Ssklower * and when the reference timer goes off 72936408Ssklower * (if the disconnect was initiated by the protocol entity 73036408Ssklower * rather than by the user) 73136408Ssklower * 73236408Ssklower * FUNCTION and ARGUMENTS: 73336408Ssklower * remove the tpcb structure from the list of active or 73436408Ssklower * partially active connections, recycle all the mbufs 73536408Ssklower * associated with the pcb, ref structure, sockbufs, etc. 73636408Ssklower * Only free the ref structure if you know that a ref timer 73736408Ssklower * wasn't set for this tpcb. 73836408Ssklower * 73936408Ssklower * RETURNS: Nada 74036408Ssklower * 74136408Ssklower * SIDE EFFECTS: 74236408Ssklower * 74336408Ssklower * NOTES: 74436408Ssklower * tp_soisdisconnected() was already when this is called 74536408Ssklower */ 74636408Ssklower void 74736408Ssklower tp_detach(tpcb) 74836408Ssklower register struct tp_pcb *tpcb; 74936408Ssklower { 75036408Ssklower void tp_freeref(); 75136408Ssklower register struct socket *so = tpcb->tp_sock; 75236408Ssklower 75336408Ssklower IFDEBUG(D_CONN) 754*37469Ssklower printf("tp_detach(tpcb 0x%x, so 0x%x)\n", 755*37469Ssklower tpcb,so); 75636408Ssklower ENDDEBUG 75736408Ssklower IFTRACE(D_CONN) 75836408Ssklower tptraceTPCB(TPPTmisc, "tp_detach tpcb so lsufx", 75936408Ssklower tpcb, so, *(int *)(tpcb->tp_lsuffix), 0); 76036408Ssklower ENDTRACE 76136408Ssklower 76236408Ssklower if (so->so_head) { 76336408Ssklower if (!soqremque(so, 0) && !soqremque(so, 1)) 76436408Ssklower panic("sofree dq"); 76536408Ssklower so->so_head = 0; 76636408Ssklower } 76736408Ssklower 76836408Ssklower IFDEBUG(D_CONN) 76936408Ssklower printf("tp_detach(freeing RTC list snduna 0x%x rcvnxt 0x%x)\n", 77036408Ssklower tpcb->tp_snduna_rtc, 77136408Ssklower tpcb->tp_rcvnxt_rtc); 77236408Ssklower ENDDEBUG 77336408Ssklower 77436408Ssklower #define FREE_RTC_LIST(XXX)\ 77536408Ssklower { register struct tp_rtc *xxr = XXX, *xxs; while (xxr) {\ 77636408Ssklower xxs = xxr->tprt_next;\ 77736408Ssklower m_freem( xxr->tprt_data );\ 77836408Ssklower m_free( dtom(xxr) ); xxr = xxs; }\ 77936408Ssklower XXX = (struct tp_rtc *)0;\ 78036408Ssklower } 78136408Ssklower 78236408Ssklower FREE_RTC_LIST( tpcb->tp_snduna_rtc ); 78336408Ssklower tpcb->tp_sndhiwat_rtc = (struct tp_rtc *)0; 78436408Ssklower 78536408Ssklower FREE_RTC_LIST( tpcb->tp_rcvnxt_rtc ); 78636408Ssklower 78736408Ssklower #undef FREE_RTC_LIST 78836408Ssklower 78936408Ssklower IFDEBUG(D_CONN) 79036408Ssklower printf("calling (...nlproto->...)(0x%x, so 0x%x)\n", 79136408Ssklower so->so_pcb, so); 79236408Ssklower printf("so 0x%x so_head 0x%x, qlen %d q0len %d qlimit %d\n", 79336408Ssklower so, so->so_head, 79436408Ssklower so->so_q0len, so->so_qlen, so->so_qlimit); 79536408Ssklower ENDDEBUG 79636408Ssklower 797*37469Ssklower if ( tpcb->tp_flags & (TPF_DISC_DATA_OUT | TPF_CONN_DATA_OUT ) ) { 79836408Ssklower ASSERT( so->so_snd.sb_cc != 0 ); 79936408Ssklower IFDEBUG(D_CONN) 80036408Ssklower printf( 80136408Ssklower "detach, flags 0x%x doing sbdrop on so_snd, mb 0x%x cc 0x%x\n", 80236408Ssklower tpcb->tp_flags, so->so_snd.sb_mb, so->so_snd.sb_cc); 80336408Ssklower dump_mbuf( so->so_snd.sb_mb, "detach so snd: \n"); 80436408Ssklower ENDDEBUG 80536408Ssklower if ( so->so_snd.sb_cc != 0 ) 806*37469Ssklower sbflush(&so->so_snd); 80736408Ssklower tpcb->tp_flags &= ~(TPF_CONN_DATA_OUT | TPF_DISC_DATA_OUT); 80836408Ssklower } 80936408Ssklower if ( tpcb->tp_flags & (TPF_DISC_DATA_IN | TPF_CONN_DATA_IN ) ) { 81036408Ssklower ASSERT( tpcb->tp_Xrcv.sb_cc != 0 ); 81136408Ssklower IFDEBUG(D_CONN) 81236408Ssklower printf( 81336408Ssklower "detach, flags 0x%x doing sbdrop on tp_Xrcv, mb 0x%x cc 0x%x\n", 81436408Ssklower tpcb->tp_flags, tpcb->tp_Xrcv.sb_mb, tpcb->tp_Xrcv.sb_cc); 81536408Ssklower dump_mbuf( tpcb->tp_Xrcv.sb_mb, "detach Xrcv: \n"); 81636408Ssklower ENDDEBUG 81736408Ssklower if( tpcb->tp_Xrcv.sb_cc != 0 ) 818*37469Ssklower sbdrop(&tpcb->tp_Xrcv, (int)tpcb->tp_Xrcv.sb_cc); 81936408Ssklower tpcb->tp_flags &= ~(TPF_CONN_DATA_IN | TPF_DISC_DATA_IN); 82036408Ssklower } 82136408Ssklower 82236408Ssklower IFDEBUG(D_CONN) 82336408Ssklower printf("so_snd at 0x%x so_rcv at 0x%x\n", &so->so_snd, &so->so_rcv); 82436408Ssklower dump_mbuf(so->so_snd.sb_mb, "so_snd at detach "); 82536408Ssklower printf("about to call LL detach, nlproto 0x%x, nl_detach 0x%x\n", 82636408Ssklower tpcb->tp_nlproto, tpcb->tp_nlproto->nlp_pcbdetach); 82736408Ssklower ENDDEBUG 82836408Ssklower 82936408Ssklower 830*37469Ssklower 831*37469Ssklower (tpcb->tp_nlproto->nlp_pcbdetach)((struct inpcb *)so->so_pcb); 832*37469Ssklower /* does an sofree(so) */ 833*37469Ssklower 83436408Ssklower IFDEBUG(D_CONN) 83536408Ssklower printf("after xxx_pcbdetach\n"); 83636408Ssklower ENDDEBUG 83736408Ssklower 83836408Ssklower if( tpcb->tp_refp->tpr_state == REF_OPENING ) { 83936408Ssklower /* no connection existed here so no reference timer will be called */ 84036408Ssklower IFDEBUG(D_CONN) 84136408Ssklower printf("SETTING ref %d, 0x%x to REF_FREE\n", tpcb->tp_lref, 84236408Ssklower tpcb->tp_refp - &tp_ref[0]); 84336408Ssklower ENDDEBUG 84436408Ssklower 84536408Ssklower tp_freeref(tpcb->tp_refp); 84636408Ssklower } 84736408Ssklower 848*37469Ssklower if (tpcb->tp_Xsnd.sb_mb) { 849*37469Ssklower printf("Unsent Xdata on detach; would panic"); 850*37469Ssklower sbflush(&tpcb->tp_Xsnd); 851*37469Ssklower } 85236408Ssklower so->so_tpcb = (caddr_t)0; 85336408Ssklower 85436408Ssklower /* 85536408Ssklower * Get rid of the cluster mbuf allocated for performance measurements, if 85636408Ssklower * there is one. Note that tpcb->tp_perf_on says nothing about whether or 85736408Ssklower * not a cluster mbuf was allocated, so you have to check for a pointer 85836408Ssklower * to one (that is, we need the TP_PERF_MEASs around the following section 85936408Ssklower * of code, not the IFPERFs) 86036408Ssklower */ 86136408Ssklower #ifdef TP_PERF_MEAS 862*37469Ssklower if(tpcb->tp_p_mbuf) { 863*37469Ssklower register struct mbuf *m = tpcb->tp_p_mbuf; 864*37469Ssklower struct mbuf *n; 86536408Ssklower IFDEBUG(D_PERF_MEAS) 86636408Ssklower printf("freeing tp_p_meas 0x%x ", tpcb->tp_p_meas); 86736408Ssklower ENDDEBUG 868*37469Ssklower do { 869*37469Ssklower MFREE(m, n); 870*37469Ssklower m = n; 871*37469Ssklower } while (n); 872*37469Ssklower tpcb->tp_p_meas = 0; 873*37469Ssklower tpcb->tp_p_mbuf = 0; 87436408Ssklower } 87536408Ssklower #endif TP_PERF_MEAS 87636408Ssklower 87736408Ssklower IFDEBUG(D_CONN) 878*37469Ssklower printf( "end of detach, NOT single, tpcb 0x%x\n", tpcb); 87936408Ssklower ENDDEBUG 880*37469Ssklower /* free((caddr_t)tpcb, M_PCB); WHere to put this ? */ 88136408Ssklower } 882