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