xref: /csrg-svn/sys/netiso/tp_usrreq.c (revision 37469)
136420Ssklower /***********************************************************
236420Ssklower 		Copyright IBM Corporation 1987
336420Ssklower 
436420Ssklower                       All Rights Reserved
536420Ssklower 
636420Ssklower Permission to use, copy, modify, and distribute this software and its
736420Ssklower documentation for any purpose and without fee is hereby granted,
836420Ssklower provided that the above copyright notice appear in all copies and that
936420Ssklower both that copyright notice and this permission notice appear in
1036420Ssklower supporting documentation, and that the name of IBM not be
1136420Ssklower used in advertising or publicity pertaining to distribution of the
1236420Ssklower software without specific, written prior permission.
1336420Ssklower 
1436420Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1536420Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1636420Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1736420Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1836420Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1936420Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2036420Ssklower SOFTWARE.
2136420Ssklower 
2236420Ssklower ******************************************************************/
2336420Ssklower 
2436420Ssklower /*
2536420Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
2636420Ssklower  */
2736420Ssklower /*
2836420Ssklower  * ARGO TP
2936420Ssklower  *
3036420Ssklower  * $Header: tp_usrreq.c,v 5.4 88/11/18 17:29:18 nhall Exp $
3136420Ssklower  * $Source: /usr/argo/sys/netiso/RCS/tp_usrreq.c,v $
3236420Ssklower  *
3336420Ssklower  * tp_usrreq(), the fellow that gets called from most of the socket code.
3436420Ssklower  * Pretty straighforward.
3536420Ssklower  * THe only really awful stuff here is the OOB processing, which is done
3636420Ssklower  * wholly here.
3736420Ssklower  * tp_rcvoob() and tp_sendoob() are contained here and called by tp_usrreq().
3836420Ssklower  */
3936420Ssklower 
4036420Ssklower #ifndef lint
4136420Ssklower static char *rcsid = "$Header: tp_usrreq.c,v 5.4 88/11/18 17:29:18 nhall Exp $";
4236420Ssklower #endif lint
4336420Ssklower 
4436420Ssklower #include "param.h"
4536420Ssklower #include "systm.h"
4636420Ssklower #include "dir.h"
4736420Ssklower #include "user.h"
4836420Ssklower #include "mbuf.h"
4936420Ssklower #include "socket.h"
5036420Ssklower #include "socketvar.h"
5136420Ssklower #include "domain.h"
5236420Ssklower #include "protosw.h"
5336420Ssklower #include "errno.h"
5436420Ssklower 
55*37469Ssklower #include "tp_param.h"
56*37469Ssklower #include "tp_timer.h"
57*37469Ssklower #include "tp_stat.h"
58*37469Ssklower #include "tp_seq.h"
59*37469Ssklower #include "tp_ip.h"
60*37469Ssklower #include "tp_pcb.h"
61*37469Ssklower #include "argo_debug.h"
62*37469Ssklower #include "tp_trace.h"
63*37469Ssklower #include "tp_meas.h"
64*37469Ssklower #include "iso.h"
65*37469Ssklower #include "iso_errno.h"
6636420Ssklower 
6736420Ssklower int tp_attach(), tp_driver();
6836420Ssklower 
6936420Ssklower #ifdef ARGO_DEBUG
7036420Ssklower /*
7136420Ssklower  * CALLED FROM:
7236420Ssklower  *  anywhere you want to debug...
7336420Ssklower  * FUNCTION and ARGUMENTS:
7436420Ssklower  *  print (str) followed by the control info in the mbufs of an mbuf chain (n)
7536420Ssklower  */
7636420Ssklower void
7736420Ssklower dump_mbuf(n, str)
7836420Ssklower 	struct mbuf *n;
7936420Ssklower 	char *str;
8036420Ssklower {
8136420Ssklower 	struct mbuf *nextrecord;
8236420Ssklower 
8336420Ssklower 	printf("dump %s\n", str);
8436420Ssklower 
8536420Ssklower 	if( n == MNULL)  {
8636420Ssklower 		printf("EMPTY:\n");
8736420Ssklower 		return;
8836420Ssklower 	}
8936420Ssklower 
9036420Ssklower 	for(;n;) {
9136420Ssklower 		nextrecord = n->m_act;
9236420Ssklower 		printf("RECORD:\n");
9336420Ssklower 		while (n) {
94*37469Ssklower 			printf("%x : Len %x Data %x A %x Nx %x Tp %x\n",
95*37469Ssklower 				n, n->m_len, n->m_data, n->m_act, n->m_next, n->m_type);
9636420Ssklower #ifdef notdef
9736420Ssklower 			{
9836420Ssklower 				register char *p = mtod(n, char *);
9936420Ssklower 				register int i;
10036420Ssklower 
10136420Ssklower 				printf("data: ");
10236420Ssklower 				for(i=0; i < n->m_len; i++ ) {
10336420Ssklower 					if(i%8 == 0)
10436420Ssklower 						printf("\n");
10536420Ssklower 					printf("0x%x ", *(p+i));
10636420Ssklower 				}
10736420Ssklower 				printf("\n");
10836420Ssklower 			}
10936420Ssklower #endif notdef
11036420Ssklower 			if( n->m_next == n ) {
11136420Ssklower 				printf("LOOP!\n");
11236420Ssklower 				return;
11336420Ssklower 			}
11436420Ssklower 			n = n->m_next;
11536420Ssklower 		}
11636420Ssklower 		n = nextrecord;
11736420Ssklower 	}
11836420Ssklower 	printf("\n");
11936420Ssklower }
12036420Ssklower 
12136420Ssklower #endif ARGO_DEBUG
12236420Ssklower 
12336420Ssklower /*
12436420Ssklower  * CALLED FROM:
12536420Ssklower  *  tp_usrreq(), PRU_RCVOOB
12636420Ssklower  * FUNCTION and ARGUMENTS:
12736420Ssklower  * 	Copy data from the expedited data socket buffer into
12836420Ssklower  * 	the pre-allocated mbuf m.
12936420Ssklower  * 	There is an isomorphism between XPD TPDUs and expedited data TSDUs.
13036420Ssklower  * 	XPD tpdus are limited to 16 bytes of data so they fit in one mbuf.
13136420Ssklower  * RETURN VALUE:
13236420Ssklower  *  EINVAL if debugging is on and a disaster has occurred
13336420Ssklower  *  ENOTCONN if the socket isn't connected
13436420Ssklower  *  EWOULDBLOCK if the socket is in non-blocking mode and there's no
13536420Ssklower  *		xpd data in the buffer
13636420Ssklower  *  E* whatever is returned from the fsm.
13736420Ssklower  */
13836420Ssklower tp_rcvoob(tpcb, so, m, outflags, inflags)
13936420Ssklower 	struct tp_pcb	*tpcb;
14036420Ssklower 	register struct socket	*so;
14136420Ssklower 	register struct mbuf 	*m;
14236420Ssklower 	int 		 	*outflags;
14336420Ssklower 	int 		 	inflags;
14436420Ssklower {
14536420Ssklower 	register struct mbuf *n;
146*37469Ssklower 	register struct sockbuf *sb = &so->so_rcv;
14736420Ssklower 	struct tp_event E;
14836420Ssklower 	int error = 0;
149*37469Ssklower 	register struct mbuf **nn;
15036420Ssklower 
15136420Ssklower 	IFDEBUG(D_XPD)
15236420Ssklower 		printf("PRU_RCVOOB, sostate 0x%x\n", so->so_state);
15336420Ssklower 	ENDDEBUG
15436420Ssklower 
15536420Ssklower 	/* if you use soreceive */
15636420Ssklower 	if (m==MNULL)
15736420Ssklower 		return ENOBUFS;
15836420Ssklower 
15936420Ssklower restart:
16036420Ssklower 	sblock(sb);
16136420Ssklower 
16236420Ssklower 	if ((((so->so_state & SS_ISCONNECTED) == 0)
16336420Ssklower 		 || (so->so_state & SS_ISDISCONNECTING) != 0) &&
16436420Ssklower 		(so->so_proto->pr_flags & PR_CONNREQUIRED)) {
16536420Ssklower 			return ENOTCONN;
16636420Ssklower 	}
16736420Ssklower 
168*37469Ssklower 	/* Take the first mbuf off the chain.
169*37469Ssklower 	 * Each XPD TPDU gives you a complete TSDU so the chains don't get
170*37469Ssklower 	 * coalesced, but one TSDU may span several mbufs.
171*37469Ssklower 	 * Nevertheless, since n should have a most 16 bytes, it
172*37469Ssklower 	 * will fit into m.  (size was checked in tp_input() )
173*37469Ssklower 	 */
174*37469Ssklower 
175*37469Ssklower 	/*
176*37469Ssklower 	 * Code for excision of OOB data should be added to
177*37469Ssklower 	 * uipc_socket2.c (like sbappend).
178*37469Ssklower 	 */
179*37469Ssklower 
180*37469Ssklower 	for (nn = &sb->sb_mb; n = *nn; nn = &n->m_act)
181*37469Ssklower 		if (n->m_type == MT_OOBDATA)
182*37469Ssklower 			break;
183*37469Ssklower 
184*37469Ssklower 	if (n == 0) {
18536420Ssklower 		ASSERT( (tpcb->tp_flags & TPF_DISC_DATA_IN)  == 0 );
18636420Ssklower 		IFDEBUG(D_XPD)
18736420Ssklower 			printf("RCVOOB: empty queue!\n");
18836420Ssklower 		ENDDEBUG
18936420Ssklower 		if (so->so_state & SS_NBIO) {
19036420Ssklower 			return  EWOULDBLOCK;
19136420Ssklower 		}
19236420Ssklower 		sbunlock(sb);
19336420Ssklower 		sbwait(sb);
19436420Ssklower 		goto restart;
19536420Ssklower 	}
19636420Ssklower 	m->m_len = 0;
19736420Ssklower 
19836420Ssklower 	/* Assuming at most one xpd tpdu is in the buffer at once */
19936420Ssklower 	while ( n != MNULL ) {
20036420Ssklower 		m->m_len += n->m_len;
201*37469Ssklower 		bcopy(mtod(n, caddr_t), mtod(m, caddr_t), (unsigned)n->m_len);
202*37469Ssklower 		m->m_data += n->m_len; /* so mtod() in bcopy() above gives right addr */
20336420Ssklower 		n = n->m_next;
20436420Ssklower 	}
205*37469Ssklower 	m->m_data = m->m_dat;
206*37469Ssklower 	m->m_flags |= M_EOR;
20736420Ssklower 
20836420Ssklower 	IFDEBUG(D_XPD)
20936420Ssklower 		printf("tp_rcvoob: xpdlen 0x%x\n", m->m_len);
21036420Ssklower 		dump_mbuf(so->so_rcv.sb_mb, "RCVOOB: Rcv socketbuf");
21136420Ssklower 		dump_mbuf(sb->sb_mb, "RCVOOB: Xrcv socketbuf");
21236420Ssklower 	ENDDEBUG
21336420Ssklower 
214*37469Ssklower 	if( (inflags & MSG_PEEK) == 0 ) {
215*37469Ssklower 		n = *nn;
216*37469Ssklower 		*nn = n->m_act;
217*37469Ssklower 		sb->sb_cc -= m->m_len;
218*37469Ssklower 	}
21936420Ssklower 
22036420Ssklower release:
22136420Ssklower 	sbunlock(sb);
22236420Ssklower 
22336420Ssklower 	IFTRACE(D_XPD)
22436420Ssklower 		tptraceTPCB(TPPTmisc, "PRU_RCVOOB @ release sb_cc m_len",
22536420Ssklower 			tpcb->tp_Xrcv.sb_cc, m->m_len,0,0 );
22636420Ssklower 	ENDTRACE
22736420Ssklower 	if (error == 0)
22836420Ssklower 		error = DoEvent(T_USR_Xrcvd);
22936420Ssklower 	return error;
23036420Ssklower }
23136420Ssklower 
23236420Ssklower /*
23336420Ssklower  * CALLED FROM:
23436420Ssklower  *  tp_usrreq(), PRU_SENDOOB
23536420Ssklower  * FUNCTION and ARGUMENTS:
23636420Ssklower  * 	Send what's in the mbuf chain (m) as an XPD TPDU.
23736420Ssklower  * 	The mbuf may not contain more then 16 bytes of data.
23836420Ssklower  * 	XPD TSDUs aren't segmented, so they translate into
23936420Ssklower  * 	exactly one XPD TPDU, with EOT bit set.
24036420Ssklower  * RETURN VALUE:
24136420Ssklower  *  EWOULDBLOCK if socket is in non-blocking mode and the previous
24236420Ssklower  *   xpd data haven't been acked yet.
24336420Ssklower  *  EMSGSIZE if trying to send > max-xpd bytes (16)
24436420Ssklower  *  ENOBUFS if ran out of mbufs
24536420Ssklower  */
24636420Ssklower tp_sendoob(tpcb, so, xdata, outflags)
24736420Ssklower 	struct tp_pcb	*tpcb;
24836420Ssklower 	register struct socket	*so;
24936420Ssklower 	register struct mbuf 	*xdata;
25036420Ssklower 	int 		 	*outflags; /* not used */
25136420Ssklower {
25236420Ssklower 	/*
25336420Ssklower 	 * Each mbuf chain represents a sequence # in the XPD seq space.
25436420Ssklower 	 * The first one in the queue has sequence # tp_Xuna.
25536420Ssklower 	 * When we add to the XPD queue, we stuff a zero-length
25636420Ssklower 	 * mbuf (mark) into the DATA queue, with its sequence number in m_next
25736420Ssklower 	 * to be assigned to this XPD tpdu, so data xfer can stop
25836420Ssklower 	 * when it reaches the zero-length mbuf if this XPD TPDU hasn't
25936420Ssklower 	 * yet been acknowledged.
26036420Ssklower 	 */
26136420Ssklower 	register struct sockbuf *sb = &(tpcb->tp_Xsnd);
26236420Ssklower 	register struct mbuf 	*xmark;
26336420Ssklower 	register int 			len=0;
26436420Ssklower 	struct tp_event E;
26536420Ssklower 
26636420Ssklower 	IFDEBUG(D_XPD)
26736420Ssklower 		printf("tp_sendoob:");
26836420Ssklower 		if(xdata)
26936420Ssklower 			printf("xdata len 0x%x\n", xdata->m_len);
27036420Ssklower 	ENDDEBUG
27136420Ssklower oob_again:
27236420Ssklower 	/* DO NOT LOCK the Xsnd buffer!!!! You can have at MOST one
27336420Ssklower 	 * socket buf locked at any time!!! (otherwise you might
27436420Ssklower 	 * sleep() in sblock() w/ a signal pending and cause the
27536420Ssklower 	 * system call to be aborted w/ a locked socketbuf, which
27636420Ssklower 	 * is a problem.  So the so_snd buffer lock
27736420Ssklower 	 * (done in sosend()) serves as the lock for Xpd.
27836420Ssklower 	 */
27936420Ssklower 	if (sb->sb_mb) { /* anything already in this sockbuf? */
28036420Ssklower 		if (so->so_state & SS_NBIO) {
28136420Ssklower 			return EWOULDBLOCK;
28236420Ssklower 		}
28336420Ssklower 		sbunlock(&so->so_snd);
28436420Ssklower 		sbwait(&so->so_snd);
28536420Ssklower 		sblock(&so->so_snd);
28636420Ssklower 		goto oob_again;
28736420Ssklower 	}
28836420Ssklower 
28936420Ssklower 	if (xdata == (struct mbuf *)0) {
29036420Ssklower 		/* empty xpd packet */
291*37469Ssklower 		MGETHDR(xdata, M_WAIT, MT_OOBDATA);
29236420Ssklower 		if (xdata == NULL) {
29336420Ssklower 			return ENOBUFS;
29436420Ssklower 		}
29536420Ssklower 		xdata->m_len = 0;
296*37469Ssklower 		xdata->m_pkthdr.len = 0;
29736420Ssklower 	}
29836420Ssklower 	IFDEBUG(D_XPD)
29936420Ssklower 		printf("tp_sendoob 1:");
30036420Ssklower 		if(xdata)
30136420Ssklower 			printf("xdata len 0x%x\n", xdata->m_len);
30236420Ssklower 	ENDDEBUG
30336420Ssklower 	xmark = xdata; /* temporary use of variable xmark */
30436420Ssklower 	while (xmark) {
30536420Ssklower 		len += xmark->m_len;
30636420Ssklower 		xmark = xmark->m_next;
30736420Ssklower 	}
30836420Ssklower 	if (len > TP_MAX_XPD_DATA) {
30936420Ssklower 		return EMSGSIZE;
31036420Ssklower 	}
31136420Ssklower 	IFDEBUG(D_XPD)
31236420Ssklower 		printf("tp_sendoob 2:");
31336420Ssklower 		if(xdata)
31436420Ssklower 			printf("xdata len 0x%x\n", len);
31536420Ssklower 	ENDDEBUG
31636420Ssklower 
31736420Ssklower 
31836420Ssklower 	IFTRACE(D_XPD)
31936420Ssklower 		tptraceTPCB(TPPTmisc, "XPD mark m_next ", xmark->m_next, 0, 0, 0);
32036420Ssklower 	ENDTRACE
32136420Ssklower 
32236420Ssklower 	sbappendrecord(sb, xdata);
32336420Ssklower 
32436420Ssklower 	IFDEBUG(D_XPD)
32536420Ssklower 		printf("tp_sendoob len 0x%x\n", len);
32636420Ssklower 		dump_mbuf(so->so_snd.sb_mb, "XPD request Regular sndbuf:");
32736420Ssklower 		dump_mbuf(tpcb->tp_Xsnd.sb_mb, "XPD request Xsndbuf:");
32836420Ssklower 	ENDDEBUG
32936420Ssklower 	return DoEvent(T_XPD_req);
33036420Ssklower 
33136420Ssklower }
33236420Ssklower 
33336420Ssklower /*
33436420Ssklower  * CALLED FROM:
33536420Ssklower  *  the socket routines
33636420Ssklower  * FUNCTION and ARGUMENTS:
33736420Ssklower  * 	Handles all "user requests" except the [gs]ockopts() requests.
33836420Ssklower  * 	The argument (req) is the request type (PRU*),
33936420Ssklower  * 	(m) is an mbuf chain, generally used for send and
34036420Ssklower  * 	receive type requests only.
34136420Ssklower  * 	(nam) is used for addresses usually, in particular for the bind request.
34236420Ssklower  *
34336420Ssklower  * 	The last argument (rights in most usrreq()s) has been stolen for
34436420Ssklower  * 	returning flags values.  Since rights can't be passed around w/ tp,
34536420Ssklower  * 	this field is used only for RCVOOB user requests, and is assumed
34636420Ssklower  * 	to be either 0 (as soreceive() would have it) or a ptr to the int flags
34736420Ssklower  * 	(as recvv()'s version of soreceive() would have it
34836420Ssklower  */
34936420Ssklower /*ARGSUSED*/
35036420Ssklower ProtoHook
351*37469Ssklower tp_usrreq(so, req, m, nam, rightsp, controlp)
35236420Ssklower 	struct socket *so;
35336420Ssklower 	u_int req;
354*37469Ssklower 	struct mbuf *m, *nam, *rightsp, *controlp;
35536420Ssklower {
35636420Ssklower 	register struct tp_pcb *tpcb =  sototpcb(so);
35736420Ssklower 	int s = splnet();
35836420Ssklower 	int error = 0;
359*37469Ssklower 	int flags, *outflags = &flags;
36036420Ssklower 	u_long eotsdu = 0;
36136420Ssklower 	struct tp_event E;
36236420Ssklower 
36336420Ssklower 	IFDEBUG(D_REQUEST)
36436420Ssklower 		printf("usrreq(0x%x,%d,0x%x,0x%x,0x%x)\n",so,req,m,nam,outflags);
36536420Ssklower 		if(so->so_error)
36636420Ssklower 			printf("WARNING!!! so->so_error is 0x%x\n", so->so_error);
36736420Ssklower 	ENDDEBUG
36836420Ssklower 	IFTRACE(D_REQUEST)
36936420Ssklower 		tptraceTPCB(TPPTusrreq, "req so m state [", req, so, m,
37036420Ssklower 			tpcb?tpcb->tp_state:0);
37136420Ssklower 	ENDTRACE
37236420Ssklower 
37336420Ssklower 	if ((u_int)tpcb == 0 && req != PRU_ATTACH) {
37436420Ssklower 		IFTRACE(D_REQUEST)
37536420Ssklower 			tptraceTPCB(TPPTusrreq, "req failed NO TPCB[", 0, 0, 0, 0);
37636420Ssklower 		ENDTRACE
37736420Ssklower 		splx(s);
37836420Ssklower 		return ENOTCONN;
37936420Ssklower 	}
38036420Ssklower 
38136420Ssklower 	switch (req) {
38236420Ssklower 
38336420Ssklower 	case PRU_ATTACH:
38436420Ssklower 		if (tpcb) {
38536420Ssklower 			error = EISCONN;
38636420Ssklower 			break;
38736420Ssklower 		}
38836420Ssklower 		if( error = tp_attach(so, so->so_proto->pr_domain->dom_family ) )
38936420Ssklower 			break;
39036420Ssklower 		tpcb = sototpcb(so);
39136420Ssklower 		break;
39236420Ssklower 
39336420Ssklower 	case PRU_ABORT: 	/* called from close() */
39436420Ssklower 		/* called for each incoming connect queued on the
39536420Ssklower 		 *	parent (accepting) socket
39636420Ssklower 		 */
39736420Ssklower 		if( tpcb->tp_state == TP_OPEN ) {
39836420Ssklower 			E.ATTR(T_DISC_req).e_reason = E_TP_NO_SESSION;
39936420Ssklower 			error = DoEvent(T_DISC_req); /* pretend it was a close() */
40036420Ssklower 			break;
40136420Ssklower 		} /* else DROP THROUGH */
40236420Ssklower 
40336420Ssklower 	case PRU_DETACH: 	/* called from close() */
40436420Ssklower 		/* called only after disconnect was called */
40536420Ssklower 		error = DoEvent(T_DETACH);
406*37469Ssklower 		if (tpcb->tp_state == TP_CLOSED) {
407*37469Ssklower 			free((caddr_t)tpcb, M_PCB);
408*37469Ssklower 			tpcb = 0;
409*37469Ssklower 		}
41036420Ssklower 		break;
41136420Ssklower 
41236420Ssklower 	case PRU_SHUTDOWN:
41336420Ssklower 		/* recv end may have been released; local credit might be zero  */
41436420Ssklower 	case PRU_DISCONNECT:
41536420Ssklower 		E.ATTR(T_DISC_req).e_reason = E_TP_NORMAL_DISC;
41636420Ssklower 		error = DoEvent(T_DISC_req);
41736420Ssklower 		break;
41836420Ssklower 
41936420Ssklower 	case PRU_BIND:
42036420Ssklower 		error =  (tpcb->tp_nlproto->nlp_pcbbind)( so->so_pcb, nam );
42136420Ssklower 		if (error == 0) {
422*37469Ssklower 			(tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen,
423*37469Ssklower 				tpcb->tp_lsuffix, TP_LOCAL );
42436420Ssklower 		}
42536420Ssklower 		break;
42636420Ssklower 
42736420Ssklower 	case PRU_LISTEN:
42836420Ssklower 		if ( *SHORT_LSUFXP(tpcb) == (short)0 ) {
42936420Ssklower 			/* note: this suffix is independent of the extended suffix */
43036420Ssklower 			if( error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL) )
43136420Ssklower 				break;
43236420Ssklower 		}
43336420Ssklower 		if( tpcb->tp_lsuffixlen ==  0) {
434*37469Ssklower 			(tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen,
435*37469Ssklower 				tpcb->tp_lsuffix, TP_LOCAL );
43636420Ssklower 		}
43736420Ssklower 		IFDEBUG(D_TPISO)
43836420Ssklower 			if(tpcb->tp_state != TP_CLOSED)
43936420Ssklower 				printf("LISTEN ERROR: state 0x%x\n", tpcb->tp_state);
44036420Ssklower 		ENDDEBUG
44136420Ssklower 		error = DoEvent(T_LISTEN_req);
44236420Ssklower 		break;
44336420Ssklower 
44436420Ssklower 	case PRU_CONNECT2:
44536420Ssklower 		error = EOPNOTSUPP; /* for unix domain sockets */
44636420Ssklower 		break;
44736420Ssklower 
44836420Ssklower 	case PRU_CONNECT:
44936420Ssklower 		IFTRACE(D_CONN)
45036420Ssklower 			tptraceTPCB(TPPTmisc,
451*37469Ssklower 			"PRU_CONNECT: so 0x%x *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x",
45236420Ssklower 			tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen,
45336420Ssklower 				tpcb->tp_class);
45436420Ssklower 		ENDTRACE
45536420Ssklower 		IFDEBUG(D_CONN)
45636420Ssklower 			printf("PRU_CONNECT: so *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x",
45736420Ssklower 			tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen,
45836420Ssklower 				tpcb->tp_class);
45936420Ssklower 		ENDDEBUG
46036420Ssklower 		if (*SHORT_LSUFXP(tpcb) == (short)0) {
46136420Ssklower 			/* no bind was done */
46236420Ssklower 			/* note: this suffix is independent of the extended suffix */
46336420Ssklower 			if( error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL) ) {
46436420Ssklower 				IFDEBUG(D_CONN)
46536420Ssklower 					printf("pcbbind returns error 0x%x\n", error );
46636420Ssklower 				ENDDEBUG
46736420Ssklower 				break;
46836420Ssklower 			}
46936420Ssklower 		}
470*37469Ssklower 		if( tpcb->tp_lsuffixlen ==  0) {
471*37469Ssklower 			(tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen,
472*37469Ssklower 				tpcb->tp_lsuffix, TP_LOCAL );
473*37469Ssklower 		}
47436420Ssklower 
47536420Ssklower 		IFDEBUG(D_CONN)
47636420Ssklower 			printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb);
47736420Ssklower 			dump_buf( tpcb->tp_npcb, 16);
47836420Ssklower 		ENDDEBUG
47936420Ssklower 		if( error = tp_route_to( nam, tpcb, /* channel */0) )
48036420Ssklower 			break;
48136420Ssklower 		IFDEBUG(D_CONN)
48236420Ssklower 			printf(
48336420Ssklower 				"PRU_CONNECT after tpcb 0x%x so 0x%x npcb 0x%x flags 0x%x\n",
48436420Ssklower 				tpcb, so, tpcb->tp_npcb, tpcb->tp_flags);
48536420Ssklower 			printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb);
48636420Ssklower 			dump_buf( tpcb->tp_npcb, 16);
48736420Ssklower 		ENDDEBUG
488*37469Ssklower 		if( tpcb->tp_fsuffixlen ==  0) {
48936420Ssklower 			/* didn't set peer extended suffix */
490*37469Ssklower 			(tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_fsuffixlen,
491*37469Ssklower 				tpcb->tp_fsuffix, TP_FOREIGN );
49236420Ssklower 		}
49336420Ssklower 		(void) (tpcb->tp_nlproto->nlp_mtu)(so, so->so_pcb,
49436420Ssklower 					&tpcb->tp_l_tpdusize, &tpcb->tp_tpdusize, 0);
49536420Ssklower 		if( tpcb->tp_state == TP_CLOSED) {
49636420Ssklower 			soisconnecting(so);
49736420Ssklower 			error = DoEvent(T_CONN_req);
49836420Ssklower 		} else {
49936420Ssklower 			(tpcb->tp_nlproto->nlp_pcbdisc)(so->so_pcb);
50036420Ssklower 			error = EISCONN;
50136420Ssklower 		}
50236420Ssklower 		IFPERF(tpcb)
50336420Ssklower 			u_int lsufx, fsufx;
50436420Ssklower 			lsufx = *(u_int *)(tpcb->tp_lsuffix);
50536420Ssklower 			fsufx = *(u_int *)(tpcb->tp_fsuffix);
50636420Ssklower 
50736420Ssklower 			tpmeas( tpcb->tp_lref,
50836420Ssklower 				TPtime_open | (tpcb->tp_xtd_format <<4 ),
50936420Ssklower 				&time, lsufx, fsufx, tpcb->tp_fref);
51036420Ssklower 		ENDPERF
51136420Ssklower 		break;
51236420Ssklower 
51336420Ssklower 	case PRU_ACCEPT:
51436420Ssklower 		/* all this garbage is to keep accept from returning
51536420Ssklower 		 * before the 3-way handshake is done in class 4.
51636420Ssklower 		 * it'll have to be modified for other classes
51736420Ssklower 		 */
51836420Ssklower 		IFDEBUG(D_REQUEST)
51936420Ssklower 			printf("PRU_ACCEPT so_error 0x%x\n", so->so_error);
52036420Ssklower 		ENDDEBUG
52136420Ssklower 		so->so_error = 0;
52236420Ssklower 		if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTED)== 0) {
52336420Ssklower 			error = EWOULDBLOCK;
52436420Ssklower 			break;
52536420Ssklower 		}
52636420Ssklower 		while ((so->so_state & SS_ISCONNECTED) == 0 && so->so_error == 0) {
52736420Ssklower 			sleep((caddr_t)&so->so_timeo, PZERO+1);
52836420Ssklower 		}
52936420Ssklower 		if (so->so_error) {
53036420Ssklower 			error = so->so_error;
53136420Ssklower 		} else {
532*37469Ssklower 			(tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN);
53336420Ssklower 			IFDEBUG(D_REQUEST)
53436420Ssklower 				printf("ACCEPT PEERADDDR:");
535*37469Ssklower 				dump_buf(mtod(nam, char *), nam->m_len);
53636420Ssklower 			ENDDEBUG
53736420Ssklower 		}
53836420Ssklower 		IFPERF(tpcb)
53936420Ssklower 			u_int lsufx, fsufx;
54036420Ssklower 			lsufx = *(u_int *)(tpcb->tp_lsuffix);
54136420Ssklower 			fsufx = *(u_int *)(tpcb->tp_fsuffix);
54236420Ssklower 
54336420Ssklower 			tpmeas( tpcb->tp_lref, TPtime_open,
54436420Ssklower 				&time, lsufx, fsufx, tpcb->tp_fref);
54536420Ssklower 		ENDPERF
54636420Ssklower 		break;
54736420Ssklower 
54836420Ssklower 	case PRU_RCVD:
54936420Ssklower 		IFTRACE(D_DATA)
55036420Ssklower 			tptraceTPCB(TPPTmisc,
55136420Ssklower 			"RCVD BF: lcredit sent_lcdt cc hiwat \n",
55236420Ssklower 				tpcb->tp_lcredit, tpcb->tp_sent_lcdt,
55336420Ssklower 				so->so_rcv.sb_cc, so->so_rcv.sb_hiwat);
55436420Ssklower 			LOCAL_CREDIT(tpcb);
55536420Ssklower 			tptraceTPCB(TPPTmisc,
55636420Ssklower 				"PRU_RCVD AF sbspace lcredit hiwat cc",
55736420Ssklower 				sbspace(&so->so_rcv), tpcb->tp_lcredit,
55836420Ssklower 				so->so_rcv.sb_cc, so->so_rcv.sb_hiwat);
55936420Ssklower 		ENDTRACE
560*37469Ssklower 		IFDEBUG(D_REQUEST)
561*37469Ssklower 			printf("RCVD: cc %d space %d hiwat %d\n",
562*37469Ssklower 				so->so_rcv.sb_cc, sbspace(&so->so_rcv),
563*37469Ssklower 				so->so_rcv.sb_hiwat);
564*37469Ssklower 		ENDDEBUG
565*37469Ssklower 		if (((int)nam) & MSG_OOB)
566*37469Ssklower 			error = DoEvent(T_USR_Xrcvd);
567*37469Ssklower 		else
568*37469Ssklower 			error = DoEvent(T_USR_rcvd);
56936420Ssklower 		break;
57036420Ssklower 
57136420Ssklower 	case PRU_RCVOOB:
57236420Ssklower 		if ((so->so_state & SS_ISCONNECTED) == 0) {
57336420Ssklower 			error = ENOTCONN;
57436420Ssklower 			break;
57536420Ssklower 		}
57636420Ssklower 		if( ! tpcb->tp_xpd_service ) {
57736420Ssklower 			error = EOPNOTSUPP;
57836420Ssklower 			break;
57936420Ssklower 		}
58036420Ssklower 		/* kludge - nam is really flags here */
58136420Ssklower 		error = tp_rcvoob(tpcb, so, m, outflags, (int)nam);
58236420Ssklower 		break;
58336420Ssklower 
58436420Ssklower 	case PRU_SENDOOB:
585*37469Ssklower 		if (controlp && (error = tp_snd_control(controlp, so, &m)))
58636420Ssklower 			break;
587*37469Ssklower 		if (m == 0)
588*37469Ssklower 			break;
589*37469Ssklower 		if (so->so_state & SS_ISCONFIRMING)
590*37469Ssklower 			tp_confirm();
59136420Ssklower 		if( ! tpcb->tp_xpd_service ) {
59236420Ssklower 			error = EOPNOTSUPP;
59336420Ssklower 			break;
59436420Ssklower 		}
59536420Ssklower 		error = tp_sendoob(tpcb, so, m, outflags);
59636420Ssklower 		break;
59736420Ssklower 
59836420Ssklower 	case PRU_SEND:
59936420Ssklower 		/*
60036420Ssklower 		 * The protocol machine copies mbuf chains,
60136420Ssklower 		 * prepends headers, assigns seq numbers, and
60236420Ssklower 		 * puts the packets on the device.
60336420Ssklower 		 * When they are acked they are removed from the socket buf.
60436420Ssklower 		 *
60536420Ssklower 		 * sosend calls this up until sbspace goes negative.
60636420Ssklower 		 * Sbspace may be made negative by appending this mbuf chain,
60736420Ssklower 		 * possibly by a whole cluster.
60836420Ssklower 		 */
609*37469Ssklower 		if (controlp && (error = tp_snd_control(controlp, so, &m)))
61036420Ssklower 			break;
611*37469Ssklower 		if (m == 0)
612*37469Ssklower 			break;
613*37469Ssklower 		if (so->so_state & SS_ISCONFIRMING)
614*37469Ssklower 			tp_confirm();
61536420Ssklower 		{
616*37469Ssklower 			register struct mbuf *n = m;
61736420Ssklower 			register int len=0;
61836420Ssklower 			register struct sockbuf *sb = &so->so_snd;
619*37469Ssklower 			int	maxsize = tpcb->tp_l_tpdusize
620*37469Ssklower 				    - tp_headersize(DT_TPDU_type, tpcb)
621*37469Ssklower 				    - (tpcb->tp_use_checksum?4:0) ;
622*37469Ssklower 			int totlen = n->m_pkthdr.len;
62336420Ssklower 
624*37469Ssklower 			/*
625*37469Ssklower 			 * Could have eotsdu and no data.(presently MUST have
626*37469Ssklower 			 * an mbuf though, even if its length == 0)
627*37469Ssklower 			 */
628*37469Ssklower 			if (n->m_flags & M_EOR)
629*37469Ssklower 				eotsdu = 1;
63036420Ssklower 			IFPERF(tpcb)
631*37469Ssklower 			   PStat(tpcb, Nb_from_sess) += totlen;
63236420Ssklower 			   tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0,
633*37469Ssklower 					PStat(tpcb, Nb_from_sess), totlen);
63436420Ssklower 			ENDPERF
63536420Ssklower 			IFDEBUG(D_SYSCALL)
63636420Ssklower 				printf(
63736420Ssklower 				"PRU_SEND: eot %d before sbappend 0x%x len 0x%x to sb @ 0x%x\n",
638*37469Ssklower 					eotsdu, m,len, sb);
63936420Ssklower 				dump_mbuf(sb->sb_mb, "so_snd.sb_mb");
64036420Ssklower 				dump_mbuf(m, "m : to be added");
64136420Ssklower 			ENDDEBUG
642*37469Ssklower 			/*
643*37469Ssklower 			 * Pre-packetize the data in the sockbuf
644*37469Ssklower 			 * according to negotiated mtu.  Do it here
645*37469Ssklower 			 * where we can safely wait for mbufs.
64636420Ssklower 			 */
647*37469Ssklower 			while (n->m_pkthdr.len > maxsize) {
648*37469Ssklower 				struct mbuf *nn
649*37469Ssklower 					    = m_copym(n, 0, maxsize, M_WAIT);
650*37469Ssklower 				if (eotsdu)
651*37469Ssklower 					n->m_flags &= ~M_EOR;
652*37469Ssklower 				sbappendrecord(sb, nn);
653*37469Ssklower 				m_adj(n, maxsize);
654*37469Ssklower 			}
655*37469Ssklower 			sbappendrecord(sb, n);
65636420Ssklower 			IFDEBUG(D_SYSCALL)
65736420Ssklower 				printf("PRU_SEND: eot %d after sbappend 0x%x len 0x%x\n",
658*37469Ssklower 					eotsdu, n, len);
65936420Ssklower 				dump_mbuf(sb->sb_mb, "so_snd.sb_mb");
66036420Ssklower 			ENDDEBUG
66136420Ssklower 			error = DoEvent(T_DATA_req);
66236420Ssklower 			IFDEBUG(D_SYSCALL)
66336420Ssklower 				printf("PRU_SEND: after driver error 0x%x \n",error);
664*37469Ssklower 				printf("so_snd 0x%x cc 0t%d mbcnt 0t%d\n",
665*37469Ssklower 						sb, sb->sb_cc, sb->sb_mbcnt);
666*37469Ssklower 				dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver");
66736420Ssklower 			ENDDEBUG
66836420Ssklower 		}
66936420Ssklower 		break;
67036420Ssklower 
671*37469Ssklower 	case PRU_SOCKADDR:
672*37469Ssklower 		(tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_LOCAL);
67336420Ssklower 		break;
67436420Ssklower 
67536420Ssklower 	case PRU_PEERADDR:
676*37469Ssklower 		if ((so->so_state & SS_ISCONNECTED) &&
677*37469Ssklower 		    (so->so_state & SS_ISDISCONNECTING) == 0) {
678*37469Ssklower 				(tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN);
679*37469Ssklower 				IFDEBUG(D_REQUEST)
680*37469Ssklower 					printf("PEERADDDR:");
681*37469Ssklower 					dump_buf(mtod(nam, char *), nam->m_len);
682*37469Ssklower 				ENDDEBUG
68336420Ssklower 		} else
68436420Ssklower 			error = ENOTCONN;
68536420Ssklower 		break;
68636420Ssklower 
68736420Ssklower 	case PRU_CONTROL:
68836420Ssklower 		error = EOPNOTSUPP;
68936420Ssklower 		break;
69036420Ssklower 
69136420Ssklower 	case PRU_PROTOSEND:
69236420Ssklower 	case PRU_PROTORCV:
69336420Ssklower 	case PRU_SENSE:
69436420Ssklower 	case PRU_SLOWTIMO:
69536420Ssklower 	case PRU_FASTTIMO:
69636420Ssklower 		error = EOPNOTSUPP;
69736420Ssklower 		break;
69836420Ssklower 
69936420Ssklower 	default:
70036420Ssklower #ifdef ARGO_DEBUG
70136420Ssklower 		printf("tp_usrreq UNKNOWN PRU %d\n", req);
70236420Ssklower #endif ARGO_DEBUG
70336420Ssklower 		error = EOPNOTSUPP;
70436420Ssklower 	}
70536420Ssklower 
70636420Ssklower 	IFDEBUG(D_REQUEST)
70736420Ssklower 		printf("returning from tp_usrreq(so 0x%x) error 0x%x\n", so, error);
70836420Ssklower 	ENDDEBUG
70936420Ssklower 	IFTRACE(D_REQUEST)
71036420Ssklower 		tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m,
71136420Ssklower 			tpcb?0:tpcb->tp_state);
71236420Ssklower 	ENDTRACE
71336420Ssklower 	splx(s);
71436420Ssklower 	return error;
71536420Ssklower }
716*37469Ssklower 
717*37469Ssklower /*
718*37469Ssklower  * Stub for future negotiated confirmation of connections.
719*37469Ssklower  */
720*37469Ssklower tp_confirm()
721*37469Ssklower {
722*37469Ssklower }
723*37469Ssklower 
724*37469Ssklower /*
725*37469Ssklower  * Process control data sent with sendmsg()
726*37469Ssklower  */
727*37469Ssklower tp_snd_control(m0, so, data)
728*37469Ssklower 	register struct mbuf *m0;
729*37469Ssklower 	struct socket *so;
730*37469Ssklower 	register struct mbuf **data;
731*37469Ssklower {
732*37469Ssklower 	register struct tp_control_hdr *ch;
733*37469Ssklower 	struct mbuf *m;
734*37469Ssklower 	int error = 0;
735*37469Ssklower 
736*37469Ssklower 	if (m0 && m0->m_len) {
737*37469Ssklower 		ch = mtod(m0, struct tp_control_hdr *);
738*37469Ssklower 		m0->m_len -= sizeof (*ch);
739*37469Ssklower 		m0->m_data += sizeof (*ch);
740*37469Ssklower 		m = m_copym(m0, 0, M_COPYALL, M_WAIT);
741*37469Ssklower 		error = tp_ctloutput(PRCO_SETOPT,
742*37469Ssklower 							 so, ch->cmsg_level, ch->cmsg_type, &m);
743*37469Ssklower 		if (m)
744*37469Ssklower 			m_freem(m);
745*37469Ssklower 		if (ch->cmsg_type == TPOPT_DISC_DATA) {
746*37469Ssklower 			if (data && *data) {
747*37469Ssklower 				m_freem(*data);
748*37469Ssklower 				*data = 0;
749*37469Ssklower 			}
750*37469Ssklower 			m0 = 0;
751*37469Ssklower 			error = tp_usrreq(so, PRU_DISCONNECT, m0, (caddr_t)0, m0, m0);
752*37469Ssklower 		}
753*37469Ssklower 	}
754*37469Ssklower 	return error;
755*37469Ssklower }
756