149268Sbostic /*-
2*63222Sbostic * Copyright (c) 1991, 1993
3*63222Sbostic * The Regents of the University of California. All rights reserved.
449268Sbostic *
549268Sbostic * %sccs.include.redist.c%
649268Sbostic *
7*63222Sbostic * @(#)tp_usrreq.c 8.1 (Berkeley) 06/10/93
849268Sbostic */
949268Sbostic
1036420Ssklower /***********************************************************
1139196Ssklower Copyright IBM Corporation 1987
1236420Ssklower
1336420Ssklower All Rights Reserved
1436420Ssklower
1536420Ssklower Permission to use, copy, modify, and distribute this software and its
1636420Ssklower documentation for any purpose and without fee is hereby granted,
1736420Ssklower provided that the above copyright notice appear in all copies and that
1836420Ssklower both that copyright notice and this permission notice appear in
1936420Ssklower supporting documentation, and that the name of IBM not be
2036420Ssklower used in advertising or publicity pertaining to distribution of the
2136420Ssklower software without specific, written prior permission.
2236420Ssklower
2336420Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2436420Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2536420Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2636420Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2736420Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2836420Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2936420Ssklower SOFTWARE.
3036420Ssklower
3136420Ssklower ******************************************************************/
3236420Ssklower
3336420Ssklower /*
3436420Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
3536420Ssklower */
3636420Ssklower /*
3736420Ssklower * ARGO TP
3836420Ssklower *
3936420Ssklower * $Header: tp_usrreq.c,v 5.4 88/11/18 17:29:18 nhall Exp $
4036420Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_usrreq.c,v $
4136420Ssklower *
4236420Ssklower * tp_usrreq(), the fellow that gets called from most of the socket code.
4336420Ssklower * Pretty straighforward.
4436420Ssklower * THe only really awful stuff here is the OOB processing, which is done
4536420Ssklower * wholly here.
4636420Ssklower * tp_rcvoob() and tp_sendoob() are contained here and called by tp_usrreq().
4736420Ssklower */
4836420Ssklower
4956533Sbostic #include <sys/param.h>
5056533Sbostic #include <sys/systm.h>
5156533Sbostic #include <sys/mbuf.h>
5256533Sbostic #include <sys/socket.h>
5356533Sbostic #include <sys/socketvar.h>
5456533Sbostic #include <sys/domain.h>
5556533Sbostic #include <sys/protosw.h>
5656533Sbostic #include <sys/errno.h>
5756533Sbostic #include <sys/time.h>
5836420Ssklower
5956533Sbostic #include <netiso/tp_param.h>
6056533Sbostic #include <netiso/tp_timer.h>
6156533Sbostic #include <netiso/tp_stat.h>
6256533Sbostic #include <netiso/tp_seq.h>
6356533Sbostic #include <netiso/tp_ip.h>
6456533Sbostic #include <netiso/tp_pcb.h>
6556533Sbostic #include <netiso/argo_debug.h>
6656533Sbostic #include <netiso/tp_trace.h>
6756533Sbostic #include <netiso/tp_meas.h>
6856533Sbostic #include <netiso/iso.h>
6956533Sbostic #include <netiso/iso_errno.h>
7036420Ssklower
7150500Ssklower int tp_attach(), tp_driver(), tp_pcbbind();
7239937Ssklower int TNew;
7339937Ssklower int TPNagle1, TPNagle2;
7444424Ssklower struct tp_pcb *tp_listeners, *tp_intercepts;
7536420Ssklower
7636420Ssklower #ifdef ARGO_DEBUG
7736420Ssklower /*
7836420Ssklower * CALLED FROM:
7936420Ssklower * anywhere you want to debug...
8036420Ssklower * FUNCTION and ARGUMENTS:
8136420Ssklower * print (str) followed by the control info in the mbufs of an mbuf chain (n)
8236420Ssklower */
8336420Ssklower void
dump_mbuf(n,str)8436420Ssklower dump_mbuf(n, str)
8536420Ssklower struct mbuf *n;
8636420Ssklower char *str;
8736420Ssklower {
8836420Ssklower struct mbuf *nextrecord;
8936420Ssklower
9036420Ssklower printf("dump %s\n", str);
9136420Ssklower
9244310Ssklower if (n == MNULL) {
9336420Ssklower printf("EMPTY:\n");
9436420Ssklower return;
9536420Ssklower }
9636420Ssklower
9744310Ssklower while (n) {
9836420Ssklower nextrecord = n->m_act;
9936420Ssklower printf("RECORD:\n");
10036420Ssklower while (n) {
10137469Ssklower printf("%x : Len %x Data %x A %x Nx %x Tp %x\n",
10237469Ssklower n, n->m_len, n->m_data, n->m_act, n->m_next, n->m_type);
10336420Ssklower #ifdef notdef
10436420Ssklower {
10536420Ssklower register char *p = mtod(n, char *);
10636420Ssklower register int i;
10736420Ssklower
10836420Ssklower printf("data: ");
10944310Ssklower for (i = 0; i < n->m_len; i++) {
11044310Ssklower if (i%8 == 0)
11136420Ssklower printf("\n");
11236420Ssklower printf("0x%x ", *(p+i));
11336420Ssklower }
11436420Ssklower printf("\n");
11536420Ssklower }
11660359Sbostic #endif /* notdef */
11744310Ssklower if (n->m_next == n) {
11836420Ssklower printf("LOOP!\n");
11936420Ssklower return;
12036420Ssklower }
12136420Ssklower n = n->m_next;
12236420Ssklower }
12336420Ssklower n = nextrecord;
12436420Ssklower }
12536420Ssklower printf("\n");
12636420Ssklower }
12736420Ssklower
12860359Sbostic #endif /* ARGO_DEBUG */
12936420Ssklower
13036420Ssklower /*
13136420Ssklower * CALLED FROM:
13236420Ssklower * tp_usrreq(), PRU_RCVOOB
13336420Ssklower * FUNCTION and ARGUMENTS:
13436420Ssklower * Copy data from the expedited data socket buffer into
13536420Ssklower * the pre-allocated mbuf m.
13636420Ssklower * There is an isomorphism between XPD TPDUs and expedited data TSDUs.
13736420Ssklower * XPD tpdus are limited to 16 bytes of data so they fit in one mbuf.
13836420Ssklower * RETURN VALUE:
13936420Ssklower * EINVAL if debugging is on and a disaster has occurred
14036420Ssklower * ENOTCONN if the socket isn't connected
14136420Ssklower * EWOULDBLOCK if the socket is in non-blocking mode and there's no
14236420Ssklower * xpd data in the buffer
14336420Ssklower * E* whatever is returned from the fsm.
14436420Ssklower */
14536420Ssklower tp_rcvoob(tpcb, so, m, outflags, inflags)
14636420Ssklower struct tp_pcb *tpcb;
14736420Ssklower register struct socket *so;
14836420Ssklower register struct mbuf *m;
14936420Ssklower int *outflags;
15036420Ssklower int inflags;
15136420Ssklower {
15236420Ssklower register struct mbuf *n;
15337469Ssklower register struct sockbuf *sb = &so->so_rcv;
15436420Ssklower struct tp_event E;
15536420Ssklower int error = 0;
15637469Ssklower register struct mbuf **nn;
15736420Ssklower
15836420Ssklower IFDEBUG(D_XPD)
15936420Ssklower printf("PRU_RCVOOB, sostate 0x%x\n", so->so_state);
16036420Ssklower ENDDEBUG
16136420Ssklower
16236420Ssklower /* if you use soreceive */
16344310Ssklower if (m == MNULL)
16436420Ssklower return ENOBUFS;
16536420Ssklower
16636420Ssklower restart:
16736420Ssklower if ((((so->so_state & SS_ISCONNECTED) == 0)
16836420Ssklower || (so->so_state & SS_ISDISCONNECTING) != 0) &&
16936420Ssklower (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
17036420Ssklower return ENOTCONN;
17136420Ssklower }
17236420Ssklower
17337469Ssklower /* Take the first mbuf off the chain.
17437469Ssklower * Each XPD TPDU gives you a complete TSDU so the chains don't get
17537469Ssklower * coalesced, but one TSDU may span several mbufs.
17637469Ssklower * Nevertheless, since n should have a most 16 bytes, it
17737469Ssklower * will fit into m. (size was checked in tp_input() )
17837469Ssklower */
17937469Ssklower
18037469Ssklower /*
18137469Ssklower * Code for excision of OOB data should be added to
18237469Ssklower * uipc_socket2.c (like sbappend).
18337469Ssklower */
18437469Ssklower
18552114Ssklower sblock(sb, M_WAITOK);
18637469Ssklower for (nn = &sb->sb_mb; n = *nn; nn = &n->m_act)
18737469Ssklower if (n->m_type == MT_OOBDATA)
18837469Ssklower break;
18937469Ssklower
19037469Ssklower if (n == 0) {
19136420Ssklower IFDEBUG(D_XPD)
19236420Ssklower printf("RCVOOB: empty queue!\n");
19336420Ssklower ENDDEBUG
19438841Ssklower sbunlock(sb);
19536420Ssklower if (so->so_state & SS_NBIO) {
19636420Ssklower return EWOULDBLOCK;
19736420Ssklower }
19836420Ssklower sbwait(sb);
19936420Ssklower goto restart;
20036420Ssklower }
20136420Ssklower m->m_len = 0;
20236420Ssklower
20336420Ssklower /* Assuming at most one xpd tpdu is in the buffer at once */
20444310Ssklower while (n != MNULL) {
20536420Ssklower m->m_len += n->m_len;
20637469Ssklower bcopy(mtod(n, caddr_t), mtod(m, caddr_t), (unsigned)n->m_len);
20737469Ssklower m->m_data += n->m_len; /* so mtod() in bcopy() above gives right addr */
20836420Ssklower n = n->m_next;
20936420Ssklower }
21037469Ssklower m->m_data = m->m_dat;
21137469Ssklower m->m_flags |= M_EOR;
21236420Ssklower
21336420Ssklower IFDEBUG(D_XPD)
21436420Ssklower printf("tp_rcvoob: xpdlen 0x%x\n", m->m_len);
21536420Ssklower dump_mbuf(so->so_rcv.sb_mb, "RCVOOB: Rcv socketbuf");
21636420Ssklower dump_mbuf(sb->sb_mb, "RCVOOB: Xrcv socketbuf");
21736420Ssklower ENDDEBUG
21836420Ssklower
21944310Ssklower if ((inflags & MSG_PEEK) == 0) {
22037469Ssklower n = *nn;
22137469Ssklower *nn = n->m_act;
22263136Ssklower for (; n; n = m_free(n))
22363136Ssklower sbfree(sb, n);
22437469Ssklower }
22536420Ssklower
22636420Ssklower release:
22736420Ssklower sbunlock(sb);
22836420Ssklower
22936420Ssklower IFTRACE(D_XPD)
23036420Ssklower tptraceTPCB(TPPTmisc, "PRU_RCVOOB @ release sb_cc m_len",
23144310Ssklower tpcb->tp_Xrcv.sb_cc, m->m_len, 0, 0);
23236420Ssklower ENDTRACE
23336420Ssklower if (error == 0)
23436420Ssklower error = DoEvent(T_USR_Xrcvd);
23536420Ssklower return error;
23636420Ssklower }
23736420Ssklower
23836420Ssklower /*
23936420Ssklower * CALLED FROM:
24036420Ssklower * tp_usrreq(), PRU_SENDOOB
24136420Ssklower * FUNCTION and ARGUMENTS:
24236420Ssklower * Send what's in the mbuf chain (m) as an XPD TPDU.
24336420Ssklower * The mbuf may not contain more then 16 bytes of data.
24436420Ssklower * XPD TSDUs aren't segmented, so they translate into
24536420Ssklower * exactly one XPD TPDU, with EOT bit set.
24636420Ssklower * RETURN VALUE:
24736420Ssklower * EWOULDBLOCK if socket is in non-blocking mode and the previous
24836420Ssklower * xpd data haven't been acked yet.
24936420Ssklower * EMSGSIZE if trying to send > max-xpd bytes (16)
25036420Ssklower * ENOBUFS if ran out of mbufs
25136420Ssklower */
25236420Ssklower tp_sendoob(tpcb, so, xdata, outflags)
25336420Ssklower struct tp_pcb *tpcb;
25436420Ssklower register struct socket *so;
25536420Ssklower register struct mbuf *xdata;
25636420Ssklower int *outflags; /* not used */
25736420Ssklower {
25836420Ssklower /*
25936420Ssklower * Each mbuf chain represents a sequence # in the XPD seq space.
26036420Ssklower * The first one in the queue has sequence # tp_Xuna.
26136420Ssklower * When we add to the XPD queue, we stuff a zero-length
26236420Ssklower * mbuf (mark) into the DATA queue, with its sequence number in m_next
26336420Ssklower * to be assigned to this XPD tpdu, so data xfer can stop
26436420Ssklower * when it reaches the zero-length mbuf if this XPD TPDU hasn't
26536420Ssklower * yet been acknowledged.
26636420Ssklower */
26736420Ssklower register struct sockbuf *sb = &(tpcb->tp_Xsnd);
26836420Ssklower register struct mbuf *xmark;
26936420Ssklower register int len=0;
27036420Ssklower struct tp_event E;
27136420Ssklower
27236420Ssklower IFDEBUG(D_XPD)
27336420Ssklower printf("tp_sendoob:");
27444310Ssklower if (xdata)
27536420Ssklower printf("xdata len 0x%x\n", xdata->m_len);
27636420Ssklower ENDDEBUG
27736420Ssklower /* DO NOT LOCK the Xsnd buffer!!!! You can have at MOST one
27836420Ssklower * socket buf locked at any time!!! (otherwise you might
27936420Ssklower * sleep() in sblock() w/ a signal pending and cause the
28036420Ssklower * system call to be aborted w/ a locked socketbuf, which
28136420Ssklower * is a problem. So the so_snd buffer lock
28236420Ssklower * (done in sosend()) serves as the lock for Xpd.
28336420Ssklower */
28438841Ssklower if (sb->sb_mb) { /* Anything already in eXpedited data sockbuf? */
28536420Ssklower if (so->so_state & SS_NBIO) {
28636420Ssklower return EWOULDBLOCK;
28736420Ssklower }
28838841Ssklower while (sb->sb_mb) {
28938841Ssklower sbunlock(&so->so_snd); /* already locked by sosend */
29038841Ssklower sbwait(&so->so_snd);
29152114Ssklower sblock(&so->so_snd, M_WAITOK); /* sosend will unlock on return */
29238841Ssklower }
29336420Ssklower }
29436420Ssklower
29536420Ssklower if (xdata == (struct mbuf *)0) {
29636420Ssklower /* empty xpd packet */
29737469Ssklower MGETHDR(xdata, M_WAIT, MT_OOBDATA);
29836420Ssklower if (xdata == NULL) {
29936420Ssklower return ENOBUFS;
30036420Ssklower }
30136420Ssklower xdata->m_len = 0;
30237469Ssklower xdata->m_pkthdr.len = 0;
30336420Ssklower }
30436420Ssklower IFDEBUG(D_XPD)
30536420Ssklower printf("tp_sendoob 1:");
30644310Ssklower if (xdata)
30736420Ssklower printf("xdata len 0x%x\n", xdata->m_len);
30836420Ssklower ENDDEBUG
30936420Ssklower xmark = xdata; /* temporary use of variable xmark */
31036420Ssklower while (xmark) {
31136420Ssklower len += xmark->m_len;
31236420Ssklower xmark = xmark->m_next;
31336420Ssklower }
31436420Ssklower if (len > TP_MAX_XPD_DATA) {
31536420Ssklower return EMSGSIZE;
31636420Ssklower }
31736420Ssklower IFDEBUG(D_XPD)
31836420Ssklower printf("tp_sendoob 2:");
31944310Ssklower if (xdata)
32036420Ssklower printf("xdata len 0x%x\n", len);
32136420Ssklower ENDDEBUG
32236420Ssklower
32336420Ssklower
32436420Ssklower IFTRACE(D_XPD)
32538841Ssklower tptraceTPCB(TPPTmisc, "XPD mark m_next ", xdata->m_next, 0, 0, 0);
32636420Ssklower ENDTRACE
32736420Ssklower
32836420Ssklower sbappendrecord(sb, xdata);
32936420Ssklower
33036420Ssklower IFDEBUG(D_XPD)
33136420Ssklower printf("tp_sendoob len 0x%x\n", len);
33236420Ssklower dump_mbuf(so->so_snd.sb_mb, "XPD request Regular sndbuf:");
33336420Ssklower dump_mbuf(tpcb->tp_Xsnd.sb_mb, "XPD request Xsndbuf:");
33436420Ssklower ENDDEBUG
33536420Ssklower return DoEvent(T_XPD_req);
33636420Ssklower }
33736420Ssklower
33836420Ssklower /*
33936420Ssklower * CALLED FROM:
34036420Ssklower * the socket routines
34136420Ssklower * FUNCTION and ARGUMENTS:
34236420Ssklower * Handles all "user requests" except the [gs]ockopts() requests.
34336420Ssklower * The argument (req) is the request type (PRU*),
34436420Ssklower * (m) is an mbuf chain, generally used for send and
34536420Ssklower * receive type requests only.
34636420Ssklower * (nam) is used for addresses usually, in particular for the bind request.
34736420Ssklower *
34836420Ssklower */
34936420Ssklower /*ARGSUSED*/
35036420Ssklower ProtoHook
tp_usrreq(so,req,m,nam,controlp)35140773Ssklower tp_usrreq(so, req, m, nam, controlp)
35236420Ssklower struct socket *so;
35336420Ssklower u_int req;
35440773Ssklower struct mbuf *m, *nam, *controlp;
35536420Ssklower {
35636420Ssklower register struct tp_pcb *tpcb = sototpcb(so);
35736420Ssklower int s = splnet();
35836420Ssklower int error = 0;
35937469Ssklower 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);
36544310Ssklower 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;
38650648Ssklower } else if ((error = tp_attach(so, (int)nam)) == 0)
38750648Ssklower tpcb = sototpcb(so);
38836420Ssklower break;
38936420Ssklower
39036420Ssklower case PRU_ABORT: /* called from close() */
39136420Ssklower /* called for each incoming connect queued on the
39236420Ssklower * parent (accepting) socket
39336420Ssklower */
39450648Ssklower if (tpcb->tp_state == TP_OPEN || tpcb->tp_state == TP_CONFIRMING) {
39536420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NO_SESSION;
39636420Ssklower error = DoEvent(T_DISC_req); /* pretend it was a close() */
39736420Ssklower break;
39836420Ssklower } /* else DROP THROUGH */
39936420Ssklower
40036420Ssklower case PRU_DETACH: /* called from close() */
40136420Ssklower /* called only after disconnect was called */
40236420Ssklower error = DoEvent(T_DETACH);
40337469Ssklower if (tpcb->tp_state == TP_CLOSED) {
40450940Ssklower if (tpcb->tp_notdetached) {
40550940Ssklower IFDEBUG(D_CONN)
40650940Ssklower printf("PRU_DETACH: not detached\n");
40750940Ssklower ENDDEBUG
40850940Ssklower tp_detach(tpcb);
40950940Ssklower }
41037469Ssklower free((caddr_t)tpcb, M_PCB);
41137469Ssklower tpcb = 0;
41237469Ssklower }
41336420Ssklower break;
41436420Ssklower
41536420Ssklower case PRU_SHUTDOWN:
41636420Ssklower /* recv end may have been released; local credit might be zero */
41736420Ssklower case PRU_DISCONNECT:
41836420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NORMAL_DISC;
41936420Ssklower error = DoEvent(T_DISC_req);
42036420Ssklower break;
42136420Ssklower
42236420Ssklower case PRU_BIND:
42350500Ssklower error = tp_pcbbind(tpcb, nam);
42436420Ssklower break;
42536420Ssklower
42636420Ssklower case PRU_LISTEN:
42750500Ssklower if (tpcb->tp_state != TP_CLOSED || tpcb->tp_lsuffixlen == 0 ||
42850500Ssklower tpcb->tp_next == 0)
42950500Ssklower error = EINVAL;
43050500Ssklower else {
43150902Ssklower register struct tp_pcb **tt;
43250500Ssklower remque(tpcb);
43350902Ssklower tpcb->tp_next = tpcb->tp_prev = tpcb;
43450902Ssklower for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten))
43550902Ssklower if ((*tt)->tp_lsuffixlen)
43650902Ssklower break;
43750902Ssklower tpcb->tp_nextlisten = *tt;
43850902Ssklower *tt = tpcb;
43950500Ssklower error = DoEvent(T_LISTEN_req);
44044424Ssklower }
44136420Ssklower break;
44236420Ssklower
44336420Ssklower case PRU_CONNECT2:
44436420Ssklower error = EOPNOTSUPP; /* for unix domain sockets */
44536420Ssklower break;
44636420Ssklower
44736420Ssklower case PRU_CONNECT:
44836420Ssklower IFTRACE(D_CONN)
44936420Ssklower tptraceTPCB(TPPTmisc,
45037469Ssklower "PRU_CONNECT: so 0x%x *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x",
45136420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen,
45236420Ssklower tpcb->tp_class);
45336420Ssklower ENDTRACE
45436420Ssklower IFDEBUG(D_CONN)
45536420Ssklower printf("PRU_CONNECT: so *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x",
45636420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen,
45736420Ssklower tpcb->tp_class);
45836420Ssklower ENDDEBUG
45944310Ssklower if (tpcb->tp_lsuffixlen == 0) {
46050648Ssklower if (error = tp_pcbbind(tpcb, MNULL)) {
46136420Ssklower IFDEBUG(D_CONN)
46244310Ssklower printf("pcbbind returns error 0x%x\n", error);
46336420Ssklower ENDDEBUG
46436420Ssklower break;
46536420Ssklower }
46637469Ssklower }
46736420Ssklower IFDEBUG(D_CONN)
46836420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb);
46944310Ssklower dump_buf(tpcb->tp_npcb, 16);
47036420Ssklower ENDDEBUG
47144310Ssklower if (error = tp_route_to(nam, tpcb, /* channel */0))
47236420Ssklower break;
47336420Ssklower IFDEBUG(D_CONN)
47436420Ssklower printf(
47536420Ssklower "PRU_CONNECT after tpcb 0x%x so 0x%x npcb 0x%x flags 0x%x\n",
47636420Ssklower tpcb, so, tpcb->tp_npcb, tpcb->tp_flags);
47736420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb);
47844310Ssklower dump_buf(tpcb->tp_npcb, 16);
47936420Ssklower ENDDEBUG
48044310Ssklower if (tpcb->tp_fsuffixlen == 0) {
48136420Ssklower /* didn't set peer extended suffix */
48250435Ssklower (tpcb->tp_nlproto->nlp_getsufx)(tpcb->tp_npcb, &tpcb->tp_fsuffixlen,
48344310Ssklower tpcb->tp_fsuffix, TP_FOREIGN);
48436420Ssklower }
48544310Ssklower if (tpcb->tp_state == TP_CLOSED) {
48636420Ssklower soisconnecting(so);
48736420Ssklower error = DoEvent(T_CONN_req);
48836420Ssklower } else {
48950435Ssklower (tpcb->tp_nlproto->nlp_pcbdisc)(tpcb->tp_npcb);
49036420Ssklower error = EISCONN;
49136420Ssklower }
49236420Ssklower IFPERF(tpcb)
49336420Ssklower u_int lsufx, fsufx;
49439196Ssklower lsufx = *(u_short *)(tpcb->tp_lsuffix);
49539196Ssklower fsufx = *(u_short *)(tpcb->tp_fsuffix);
49636420Ssklower
49744310Ssklower tpmeas(tpcb->tp_lref,
49844310Ssklower TPtime_open | (tpcb->tp_xtd_format << 4),
49936420Ssklower &time, lsufx, fsufx, tpcb->tp_fref);
50036420Ssklower ENDPERF
50136420Ssklower break;
50236420Ssklower
50336420Ssklower case PRU_ACCEPT:
50450435Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(tpcb->tp_npcb, nam, TP_FOREIGN);
50536420Ssklower IFDEBUG(D_REQUEST)
50638841Ssklower printf("ACCEPT PEERADDDR:");
50738841Ssklower dump_buf(mtod(nam, char *), nam->m_len);
50836420Ssklower ENDDEBUG
50936420Ssklower IFPERF(tpcb)
51036420Ssklower u_int lsufx, fsufx;
51139196Ssklower lsufx = *(u_short *)(tpcb->tp_lsuffix);
51239196Ssklower fsufx = *(u_short *)(tpcb->tp_fsuffix);
51336420Ssklower
51444310Ssklower tpmeas(tpcb->tp_lref, TPtime_open,
51536420Ssklower &time, lsufx, fsufx, tpcb->tp_fref);
51636420Ssklower ENDPERF
51736420Ssklower break;
51836420Ssklower
51936420Ssklower case PRU_RCVD:
52038841Ssklower if (so->so_state & SS_ISCONFIRMING) {
52138841Ssklower if (tpcb->tp_state == TP_CONFIRMING)
52238841Ssklower error = tp_confirm(tpcb);
52338841Ssklower break;
52438841Ssklower }
52536420Ssklower IFTRACE(D_DATA)
52636420Ssklower tptraceTPCB(TPPTmisc,
52736420Ssklower "RCVD BF: lcredit sent_lcdt cc hiwat \n",
52836420Ssklower tpcb->tp_lcredit, tpcb->tp_sent_lcdt,
52936420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat);
53036420Ssklower LOCAL_CREDIT(tpcb);
53136420Ssklower tptraceTPCB(TPPTmisc,
53236420Ssklower "PRU_RCVD AF sbspace lcredit hiwat cc",
53336420Ssklower sbspace(&so->so_rcv), tpcb->tp_lcredit,
53436420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat);
53536420Ssklower ENDTRACE
53637469Ssklower IFDEBUG(D_REQUEST)
53737469Ssklower printf("RCVD: cc %d space %d hiwat %d\n",
53837469Ssklower so->so_rcv.sb_cc, sbspace(&so->so_rcv),
53937469Ssklower so->so_rcv.sb_hiwat);
54037469Ssklower ENDDEBUG
54137469Ssklower if (((int)nam) & MSG_OOB)
54237469Ssklower error = DoEvent(T_USR_Xrcvd);
54337469Ssklower else
54437469Ssklower error = DoEvent(T_USR_rcvd);
54536420Ssklower break;
54636420Ssklower
54736420Ssklower case PRU_RCVOOB:
54836420Ssklower if ((so->so_state & SS_ISCONNECTED) == 0) {
54936420Ssklower error = ENOTCONN;
55036420Ssklower break;
55136420Ssklower }
55244310Ssklower if (! tpcb->tp_xpd_service) {
55336420Ssklower error = EOPNOTSUPP;
55436420Ssklower break;
55536420Ssklower }
55636420Ssklower /* kludge - nam is really flags here */
55736420Ssklower error = tp_rcvoob(tpcb, so, m, outflags, (int)nam);
55836420Ssklower break;
55936420Ssklower
56038841Ssklower case PRU_SEND:
56136420Ssklower case PRU_SENDOOB:
56241924Ssklower if (controlp) {
56341924Ssklower error = tp_snd_control(controlp, so, &m);
56441924Ssklower controlp = NULL;
56541924Ssklower if (error)
56641924Ssklower break;
56741924Ssklower }
56848736Ssklower if ((so->so_state & SS_ISCONFIRMING) &&
56948736Ssklower (tpcb->tp_state == TP_CONFIRMING) &&
57048736Ssklower (error = tp_confirm(tpcb)))
57148736Ssklower break;
57248736Ssklower if (req == PRU_SENDOOB) {
57348736Ssklower error = (tpcb->tp_xpd_service == 0) ?
57448736Ssklower EOPNOTSUPP : tp_sendoob(tpcb, so, m, outflags);
57538841Ssklower break;
57638841Ssklower }
57737469Ssklower if (m == 0)
57837469Ssklower break;
57948736Ssklower if (m->m_flags & M_EOR) {
58048736Ssklower eotsdu = 1;
58148736Ssklower m->m_flags &= ~M_EOR;
58248736Ssklower }
58348736Ssklower if (eotsdu == 0 && m->m_pkthdr.len == 0)
58436420Ssklower break;
58548736Ssklower if (tpcb->tp_state != TP_AKWAIT && tpcb->tp_state != TP_OPEN) {
58648736Ssklower error = ENOTCONN;
58748736Ssklower break;
58836420Ssklower }
58936420Ssklower /*
59036420Ssklower * The protocol machine copies mbuf chains,
59136420Ssklower * prepends headers, assigns seq numbers, and
59236420Ssklower * puts the packets on the device.
59336420Ssklower * When they are acked they are removed from the socket buf.
59436420Ssklower *
59536420Ssklower * sosend calls this up until sbspace goes negative.
59636420Ssklower * Sbspace may be made negative by appending this mbuf chain,
59736420Ssklower * possibly by a whole cluster.
59836420Ssklower */
59936420Ssklower {
60037469Ssklower /*
60137469Ssklower * Could have eotsdu and no data.(presently MUST have
60237469Ssklower * an mbuf though, even if its length == 0)
60337469Ssklower */
60450903Ssklower int totlen = m->m_pkthdr.len;
60550903Ssklower struct sockbuf *sb = &so->so_snd;
60636420Ssklower IFPERF(tpcb)
60737469Ssklower PStat(tpcb, Nb_from_sess) += totlen;
60836420Ssklower tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0,
60937469Ssklower PStat(tpcb, Nb_from_sess), totlen);
61036420Ssklower ENDPERF
61136420Ssklower IFDEBUG(D_SYSCALL)
61236420Ssklower printf(
61336420Ssklower "PRU_SEND: eot %d before sbappend 0x%x len 0x%x to sb @ 0x%x\n",
61439937Ssklower eotsdu, m, totlen, sb);
61536420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb");
61636420Ssklower dump_mbuf(m, "m : to be added");
61736420Ssklower ENDDEBUG
61850903Ssklower tp_packetize(tpcb, m, eotsdu);
61936420Ssklower IFDEBUG(D_SYSCALL)
62050903Ssklower printf("PRU_SEND: eot %d after sbappend 0x%x\n", eotsdu, m);
62136420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb");
62236420Ssklower ENDDEBUG
62348736Ssklower if (tpcb->tp_state == TP_OPEN)
62448736Ssklower error = DoEvent(T_DATA_req);
62536420Ssklower IFDEBUG(D_SYSCALL)
62636420Ssklower printf("PRU_SEND: after driver error 0x%x \n",error);
62737469Ssklower printf("so_snd 0x%x cc 0t%d mbcnt 0t%d\n",
62837469Ssklower sb, sb->sb_cc, sb->sb_mbcnt);
62937469Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver");
63036420Ssklower ENDDEBUG
63136420Ssklower }
63236420Ssklower break;
63336420Ssklower
63437469Ssklower case PRU_SOCKADDR:
63550435Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(tpcb->tp_npcb, nam, TP_LOCAL);
63636420Ssklower break;
63736420Ssklower
63836420Ssklower case PRU_PEERADDR:
63950435Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(tpcb->tp_npcb, nam, TP_FOREIGN);
64036420Ssklower break;
64136420Ssklower
64236420Ssklower case PRU_CONTROL:
64336420Ssklower error = EOPNOTSUPP;
64436420Ssklower break;
64536420Ssklower
64636420Ssklower case PRU_PROTOSEND:
64736420Ssklower case PRU_PROTORCV:
64836420Ssklower case PRU_SENSE:
64936420Ssklower case PRU_SLOWTIMO:
65036420Ssklower case PRU_FASTTIMO:
65136420Ssklower error = EOPNOTSUPP;
65236420Ssklower break;
65336420Ssklower
65436420Ssklower default:
65536420Ssklower #ifdef ARGO_DEBUG
65636420Ssklower printf("tp_usrreq UNKNOWN PRU %d\n", req);
65760359Sbostic #endif /* ARGO_DEBUG */
65836420Ssklower error = EOPNOTSUPP;
65936420Ssklower }
66036420Ssklower
66136420Ssklower IFDEBUG(D_REQUEST)
66238841Ssklower printf("%s, so 0x%x, tpcb 0x%x, error %d, state %d\n",
66338841Ssklower "returning from tp_usrreq", so, tpcb, error,
66453402Ssklower tpcb ? tpcb->tp_state : 0);
66536420Ssklower ENDDEBUG
66636420Ssklower IFTRACE(D_REQUEST)
66736420Ssklower tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m,
66853402Ssklower tpcb ? tpcb->tp_state : 0);
66936420Ssklower ENDTRACE
67041924Ssklower if (controlp) {
67141924Ssklower m_freem(controlp);
67241924Ssklower printf("control data unexpectedly retained in tp_usrreq()");
67341924Ssklower }
67436420Ssklower splx(s);
67536420Ssklower return error;
67636420Ssklower }
67739196Ssklower tp_ltrace(so, uio)
67839196Ssklower struct socket *so;
67939196Ssklower struct uio *uio;
68039196Ssklower {
68139196Ssklower IFTRACE(D_DATA)
68239196Ssklower register struct tp_pcb *tpcb = sototpcb(so);
68339196Ssklower if (tpcb) {
68439196Ssklower tptraceTPCB(TPPTmisc, "sosend so resid iovcnt", so,
68539196Ssklower uio->uio_resid, uio->uio_iovcnt, 0);
68639196Ssklower }
68739196Ssklower ENDTRACE
68839196Ssklower }
68937469Ssklower
tp_confirm(tpcb)69038841Ssklower tp_confirm(tpcb)
69138841Ssklower register struct tp_pcb *tpcb;
69237469Ssklower {
69338841Ssklower struct tp_event E;
69438841Ssklower if (tpcb->tp_state == TP_CONFIRMING)
69538841Ssklower return DoEvent(T_ACPT_req);
69638841Ssklower printf("Tp confirm called when not confirming; tpcb 0x%x, state 0x%x\n",
69738841Ssklower tpcb, tpcb->tp_state);
69838841Ssklower return 0;
69937469Ssklower }
70037469Ssklower
70137469Ssklower /*
70237469Ssklower * Process control data sent with sendmsg()
70337469Ssklower */
70441924Ssklower tp_snd_control(m, so, data)
70541924Ssklower struct mbuf *m;
70637469Ssklower struct socket *so;
70737469Ssklower register struct mbuf **data;
70837469Ssklower {
70942468Ssklower register struct cmsghdr *ch;
71037469Ssklower int error = 0;
71137469Ssklower
71241924Ssklower if (m && m->m_len) {
71342468Ssklower ch = mtod(m, struct cmsghdr *);
71441924Ssklower m->m_len -= sizeof (*ch);
71541924Ssklower m->m_data += sizeof (*ch);
71637469Ssklower error = tp_ctloutput(PRCO_SETOPT,
71737469Ssklower so, ch->cmsg_level, ch->cmsg_type, &m);
71837469Ssklower if (ch->cmsg_type == TPOPT_DISC_DATA) {
71937469Ssklower if (data && *data) {
72037469Ssklower m_freem(*data);
72137469Ssklower *data = 0;
72237469Ssklower }
72341924Ssklower error = tp_usrreq(so, PRU_DISCONNECT, (struct mbuf *)0,
72441924Ssklower (caddr_t)0, (struct mbuf *)0);
72537469Ssklower }
72637469Ssklower }
72741924Ssklower if (m)
72841924Ssklower m_freem(m);
72937469Ssklower return error;
73037469Ssklower }
731