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 $ 32*38841Ssklower * @(#)tp_usrreq.c 7.4 (Berkeley) 08/29/89 * 3336420Ssklower * 3436420Ssklower * tp_usrreq(), the fellow that gets called from most of the socket code. 3536420Ssklower * Pretty straighforward. 3636420Ssklower * THe only really awful stuff here is the OOB processing, which is done 3736420Ssklower * wholly here. 3836420Ssklower * tp_rcvoob() and tp_sendoob() are contained here and called by tp_usrreq(). 3936420Ssklower */ 4036420Ssklower 4136420Ssklower #ifndef lint 4236420Ssklower static char *rcsid = "$Header: tp_usrreq.c,v 5.4 88/11/18 17:29:18 nhall Exp $"; 4336420Ssklower #endif lint 4436420Ssklower 4536420Ssklower #include "param.h" 4636420Ssklower #include "systm.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 5537469Ssklower #include "tp_param.h" 5637469Ssklower #include "tp_timer.h" 5737469Ssklower #include "tp_stat.h" 5837469Ssklower #include "tp_seq.h" 5937469Ssklower #include "tp_ip.h" 6037469Ssklower #include "tp_pcb.h" 6137469Ssklower #include "argo_debug.h" 6237469Ssklower #include "tp_trace.h" 6337469Ssklower #include "tp_meas.h" 6437469Ssklower #include "iso.h" 6537469Ssklower #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) { 9437469Ssklower printf("%x : Len %x Data %x A %x Nx %x Tp %x\n", 9537469Ssklower 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; 14637469Ssklower register struct sockbuf *sb = &so->so_rcv; 14736420Ssklower struct tp_event E; 14836420Ssklower int error = 0; 14937469Ssklower 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 if ((((so->so_state & SS_ISCONNECTED) == 0) 16136420Ssklower || (so->so_state & SS_ISDISCONNECTING) != 0) && 16236420Ssklower (so->so_proto->pr_flags & PR_CONNREQUIRED)) { 16336420Ssklower return ENOTCONN; 16436420Ssklower } 16536420Ssklower 16637469Ssklower /* Take the first mbuf off the chain. 16737469Ssklower * Each XPD TPDU gives you a complete TSDU so the chains don't get 16837469Ssklower * coalesced, but one TSDU may span several mbufs. 16937469Ssklower * Nevertheless, since n should have a most 16 bytes, it 17037469Ssklower * will fit into m. (size was checked in tp_input() ) 17137469Ssklower */ 17237469Ssklower 17337469Ssklower /* 17437469Ssklower * Code for excision of OOB data should be added to 17537469Ssklower * uipc_socket2.c (like sbappend). 17637469Ssklower */ 17737469Ssklower 178*38841Ssklower sblock(sb); 17937469Ssklower for (nn = &sb->sb_mb; n = *nn; nn = &n->m_act) 18037469Ssklower if (n->m_type == MT_OOBDATA) 18137469Ssklower break; 18237469Ssklower 18337469Ssklower if (n == 0) { 18436420Ssklower ASSERT( (tpcb->tp_flags & TPF_DISC_DATA_IN) == 0 ); 18536420Ssklower IFDEBUG(D_XPD) 18636420Ssklower printf("RCVOOB: empty queue!\n"); 18736420Ssklower ENDDEBUG 188*38841Ssklower sbunlock(sb); 18936420Ssklower if (so->so_state & SS_NBIO) { 19036420Ssklower return EWOULDBLOCK; 19136420Ssklower } 19236420Ssklower sbwait(sb); 19336420Ssklower goto restart; 19436420Ssklower } 19536420Ssklower m->m_len = 0; 19636420Ssklower 19736420Ssklower /* Assuming at most one xpd tpdu is in the buffer at once */ 19836420Ssklower while ( n != MNULL ) { 19936420Ssklower m->m_len += n->m_len; 20037469Ssklower bcopy(mtod(n, caddr_t), mtod(m, caddr_t), (unsigned)n->m_len); 20137469Ssklower m->m_data += n->m_len; /* so mtod() in bcopy() above gives right addr */ 20236420Ssklower n = n->m_next; 20336420Ssklower } 20437469Ssklower m->m_data = m->m_dat; 20537469Ssklower m->m_flags |= M_EOR; 20636420Ssklower 20736420Ssklower IFDEBUG(D_XPD) 20836420Ssklower printf("tp_rcvoob: xpdlen 0x%x\n", m->m_len); 20936420Ssklower dump_mbuf(so->so_rcv.sb_mb, "RCVOOB: Rcv socketbuf"); 21036420Ssklower dump_mbuf(sb->sb_mb, "RCVOOB: Xrcv socketbuf"); 21136420Ssklower ENDDEBUG 21236420Ssklower 21337469Ssklower if( (inflags & MSG_PEEK) == 0 ) { 21437469Ssklower n = *nn; 21537469Ssklower *nn = n->m_act; 21637469Ssklower sb->sb_cc -= m->m_len; 21737469Ssklower } 21836420Ssklower 21936420Ssklower release: 22036420Ssklower sbunlock(sb); 22136420Ssklower 22236420Ssklower IFTRACE(D_XPD) 22336420Ssklower tptraceTPCB(TPPTmisc, "PRU_RCVOOB @ release sb_cc m_len", 22436420Ssklower tpcb->tp_Xrcv.sb_cc, m->m_len,0,0 ); 22536420Ssklower ENDTRACE 22636420Ssklower if (error == 0) 22736420Ssklower error = DoEvent(T_USR_Xrcvd); 22836420Ssklower return error; 22936420Ssklower } 23036420Ssklower 23136420Ssklower /* 23236420Ssklower * CALLED FROM: 23336420Ssklower * tp_usrreq(), PRU_SENDOOB 23436420Ssklower * FUNCTION and ARGUMENTS: 23536420Ssklower * Send what's in the mbuf chain (m) as an XPD TPDU. 23636420Ssklower * The mbuf may not contain more then 16 bytes of data. 23736420Ssklower * XPD TSDUs aren't segmented, so they translate into 23836420Ssklower * exactly one XPD TPDU, with EOT bit set. 23936420Ssklower * RETURN VALUE: 24036420Ssklower * EWOULDBLOCK if socket is in non-blocking mode and the previous 24136420Ssklower * xpd data haven't been acked yet. 24236420Ssklower * EMSGSIZE if trying to send > max-xpd bytes (16) 24336420Ssklower * ENOBUFS if ran out of mbufs 24436420Ssklower */ 24536420Ssklower tp_sendoob(tpcb, so, xdata, outflags) 24636420Ssklower struct tp_pcb *tpcb; 24736420Ssklower register struct socket *so; 24836420Ssklower register struct mbuf *xdata; 24936420Ssklower int *outflags; /* not used */ 25036420Ssklower { 25136420Ssklower /* 25236420Ssklower * Each mbuf chain represents a sequence # in the XPD seq space. 25336420Ssklower * The first one in the queue has sequence # tp_Xuna. 25436420Ssklower * When we add to the XPD queue, we stuff a zero-length 25536420Ssklower * mbuf (mark) into the DATA queue, with its sequence number in m_next 25636420Ssklower * to be assigned to this XPD tpdu, so data xfer can stop 25736420Ssklower * when it reaches the zero-length mbuf if this XPD TPDU hasn't 25836420Ssklower * yet been acknowledged. 25936420Ssklower */ 26036420Ssklower register struct sockbuf *sb = &(tpcb->tp_Xsnd); 26136420Ssklower register struct mbuf *xmark; 26236420Ssklower register int len=0; 26336420Ssklower struct tp_event E; 26436420Ssklower 26536420Ssklower IFDEBUG(D_XPD) 26636420Ssklower printf("tp_sendoob:"); 26736420Ssklower if(xdata) 26836420Ssklower printf("xdata len 0x%x\n", xdata->m_len); 26936420Ssklower ENDDEBUG 27036420Ssklower /* DO NOT LOCK the Xsnd buffer!!!! You can have at MOST one 27136420Ssklower * socket buf locked at any time!!! (otherwise you might 27236420Ssklower * sleep() in sblock() w/ a signal pending and cause the 27336420Ssklower * system call to be aborted w/ a locked socketbuf, which 27436420Ssklower * is a problem. So the so_snd buffer lock 27536420Ssklower * (done in sosend()) serves as the lock for Xpd. 27636420Ssklower */ 277*38841Ssklower if (sb->sb_mb) { /* Anything already in eXpedited data sockbuf? */ 27836420Ssklower if (so->so_state & SS_NBIO) { 27936420Ssklower return EWOULDBLOCK; 28036420Ssklower } 281*38841Ssklower while (sb->sb_mb) { 282*38841Ssklower sbunlock(&so->so_snd); /* already locked by sosend */ 283*38841Ssklower sbwait(&so->so_snd); 284*38841Ssklower sblock(&so->so_snd); /* sosend will unlock on return */ 285*38841Ssklower } 28636420Ssklower } 28736420Ssklower 28836420Ssklower if (xdata == (struct mbuf *)0) { 28936420Ssklower /* empty xpd packet */ 29037469Ssklower MGETHDR(xdata, M_WAIT, MT_OOBDATA); 29136420Ssklower if (xdata == NULL) { 29236420Ssklower return ENOBUFS; 29336420Ssklower } 29436420Ssklower xdata->m_len = 0; 29537469Ssklower xdata->m_pkthdr.len = 0; 29636420Ssklower } 29736420Ssklower IFDEBUG(D_XPD) 29836420Ssklower printf("tp_sendoob 1:"); 29936420Ssklower if(xdata) 30036420Ssklower printf("xdata len 0x%x\n", xdata->m_len); 30136420Ssklower ENDDEBUG 30236420Ssklower xmark = xdata; /* temporary use of variable xmark */ 30336420Ssklower while (xmark) { 30436420Ssklower len += xmark->m_len; 30536420Ssklower xmark = xmark->m_next; 30636420Ssklower } 30736420Ssklower if (len > TP_MAX_XPD_DATA) { 30836420Ssklower return EMSGSIZE; 30936420Ssklower } 31036420Ssklower IFDEBUG(D_XPD) 31136420Ssklower printf("tp_sendoob 2:"); 31236420Ssklower if(xdata) 31336420Ssklower printf("xdata len 0x%x\n", len); 31436420Ssklower ENDDEBUG 31536420Ssklower 31636420Ssklower 31736420Ssklower IFTRACE(D_XPD) 318*38841Ssklower tptraceTPCB(TPPTmisc, "XPD mark m_next ", xdata->m_next, 0, 0, 0); 31936420Ssklower ENDTRACE 32036420Ssklower 32136420Ssklower sbappendrecord(sb, xdata); 32236420Ssklower 32336420Ssklower IFDEBUG(D_XPD) 32436420Ssklower printf("tp_sendoob len 0x%x\n", len); 32536420Ssklower dump_mbuf(so->so_snd.sb_mb, "XPD request Regular sndbuf:"); 32636420Ssklower dump_mbuf(tpcb->tp_Xsnd.sb_mb, "XPD request Xsndbuf:"); 32736420Ssklower ENDDEBUG 32836420Ssklower return DoEvent(T_XPD_req); 32936420Ssklower } 33036420Ssklower 33136420Ssklower /* 33236420Ssklower * CALLED FROM: 33336420Ssklower * the socket routines 33436420Ssklower * FUNCTION and ARGUMENTS: 33536420Ssklower * Handles all "user requests" except the [gs]ockopts() requests. 33636420Ssklower * The argument (req) is the request type (PRU*), 33736420Ssklower * (m) is an mbuf chain, generally used for send and 33836420Ssklower * receive type requests only. 33936420Ssklower * (nam) is used for addresses usually, in particular for the bind request. 34036420Ssklower * 34136420Ssklower */ 34236420Ssklower /*ARGSUSED*/ 34336420Ssklower ProtoHook 34437469Ssklower tp_usrreq(so, req, m, nam, rightsp, controlp) 34536420Ssklower struct socket *so; 34636420Ssklower u_int req; 34737469Ssklower struct mbuf *m, *nam, *rightsp, *controlp; 34836420Ssklower { 34936420Ssklower register struct tp_pcb *tpcb = sototpcb(so); 35036420Ssklower int s = splnet(); 35136420Ssklower int error = 0; 35237469Ssklower int flags, *outflags = &flags; 35336420Ssklower u_long eotsdu = 0; 35436420Ssklower struct tp_event E; 35536420Ssklower 35636420Ssklower IFDEBUG(D_REQUEST) 35736420Ssklower printf("usrreq(0x%x,%d,0x%x,0x%x,0x%x)\n",so,req,m,nam,outflags); 35836420Ssklower if(so->so_error) 35936420Ssklower printf("WARNING!!! so->so_error is 0x%x\n", so->so_error); 36036420Ssklower ENDDEBUG 36136420Ssklower IFTRACE(D_REQUEST) 36236420Ssklower tptraceTPCB(TPPTusrreq, "req so m state [", req, so, m, 36336420Ssklower tpcb?tpcb->tp_state:0); 36436420Ssklower ENDTRACE 36536420Ssklower 36636420Ssklower if ((u_int)tpcb == 0 && req != PRU_ATTACH) { 36736420Ssklower IFTRACE(D_REQUEST) 36836420Ssklower tptraceTPCB(TPPTusrreq, "req failed NO TPCB[", 0, 0, 0, 0); 36936420Ssklower ENDTRACE 37036420Ssklower splx(s); 37136420Ssklower return ENOTCONN; 37236420Ssklower } 37336420Ssklower 37436420Ssklower switch (req) { 37536420Ssklower 37636420Ssklower case PRU_ATTACH: 37736420Ssklower if (tpcb) { 37836420Ssklower error = EISCONN; 37936420Ssklower break; 38036420Ssklower } 38136420Ssklower if( error = tp_attach(so, so->so_proto->pr_domain->dom_family ) ) 38236420Ssklower break; 38336420Ssklower tpcb = sototpcb(so); 38436420Ssklower break; 38536420Ssklower 38636420Ssklower case PRU_ABORT: /* called from close() */ 38736420Ssklower /* called for each incoming connect queued on the 38836420Ssklower * parent (accepting) socket 38936420Ssklower */ 39036420Ssklower if( tpcb->tp_state == TP_OPEN ) { 39136420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NO_SESSION; 39236420Ssklower error = DoEvent(T_DISC_req); /* pretend it was a close() */ 39336420Ssklower break; 39436420Ssklower } /* else DROP THROUGH */ 39536420Ssklower 39636420Ssklower case PRU_DETACH: /* called from close() */ 39736420Ssklower /* called only after disconnect was called */ 39836420Ssklower error = DoEvent(T_DETACH); 39937469Ssklower if (tpcb->tp_state == TP_CLOSED) { 40037469Ssklower free((caddr_t)tpcb, M_PCB); 40137469Ssklower tpcb = 0; 40237469Ssklower } 40336420Ssklower break; 40436420Ssklower 40536420Ssklower case PRU_SHUTDOWN: 40636420Ssklower /* recv end may have been released; local credit might be zero */ 40736420Ssklower case PRU_DISCONNECT: 40836420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NORMAL_DISC; 40936420Ssklower error = DoEvent(T_DISC_req); 41036420Ssklower break; 41136420Ssklower 41236420Ssklower case PRU_BIND: 41336420Ssklower error = (tpcb->tp_nlproto->nlp_pcbbind)( so->so_pcb, nam ); 41436420Ssklower if (error == 0) { 41537469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 41637469Ssklower tpcb->tp_lsuffix, TP_LOCAL ); 41736420Ssklower } 41836420Ssklower break; 41936420Ssklower 42036420Ssklower case PRU_LISTEN: 421*38841Ssklower if( tpcb->tp_lsuffixlen == 0) { 42236420Ssklower if( error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL) ) 42336420Ssklower break; 42437469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 42537469Ssklower tpcb->tp_lsuffix, TP_LOCAL ); 42636420Ssklower } 42736420Ssklower IFDEBUG(D_TPISO) 42836420Ssklower if(tpcb->tp_state != TP_CLOSED) 42936420Ssklower printf("LISTEN ERROR: state 0x%x\n", tpcb->tp_state); 43036420Ssklower ENDDEBUG 43136420Ssklower error = DoEvent(T_LISTEN_req); 43236420Ssklower break; 43336420Ssklower 43436420Ssklower case PRU_CONNECT2: 43536420Ssklower error = EOPNOTSUPP; /* for unix domain sockets */ 43636420Ssklower break; 43736420Ssklower 43836420Ssklower case PRU_CONNECT: 43936420Ssklower IFTRACE(D_CONN) 44036420Ssklower tptraceTPCB(TPPTmisc, 44137469Ssklower "PRU_CONNECT: so 0x%x *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 44236420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 44336420Ssklower tpcb->tp_class); 44436420Ssklower ENDTRACE 44536420Ssklower IFDEBUG(D_CONN) 44636420Ssklower printf("PRU_CONNECT: so *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 44736420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 44836420Ssklower tpcb->tp_class); 44936420Ssklower ENDDEBUG 450*38841Ssklower if( tpcb->tp_lsuffixlen == 0) { 45136420Ssklower if( error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL) ) { 45236420Ssklower IFDEBUG(D_CONN) 45336420Ssklower printf("pcbbind returns error 0x%x\n", error ); 45436420Ssklower ENDDEBUG 45536420Ssklower break; 45636420Ssklower } 45737469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 45837469Ssklower tpcb->tp_lsuffix, TP_LOCAL ); 45937469Ssklower } 46036420Ssklower 46136420Ssklower IFDEBUG(D_CONN) 46236420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 46336420Ssklower dump_buf( tpcb->tp_npcb, 16); 46436420Ssklower ENDDEBUG 46536420Ssklower if( error = tp_route_to( nam, tpcb, /* channel */0) ) 46636420Ssklower break; 46736420Ssklower IFDEBUG(D_CONN) 46836420Ssklower printf( 46936420Ssklower "PRU_CONNECT after tpcb 0x%x so 0x%x npcb 0x%x flags 0x%x\n", 47036420Ssklower tpcb, so, tpcb->tp_npcb, tpcb->tp_flags); 47136420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 47236420Ssklower dump_buf( tpcb->tp_npcb, 16); 47336420Ssklower ENDDEBUG 47437469Ssklower if( tpcb->tp_fsuffixlen == 0) { 47536420Ssklower /* didn't set peer extended suffix */ 47637469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_fsuffixlen, 47737469Ssklower tpcb->tp_fsuffix, TP_FOREIGN ); 47836420Ssklower } 47936420Ssklower (void) (tpcb->tp_nlproto->nlp_mtu)(so, so->so_pcb, 48036420Ssklower &tpcb->tp_l_tpdusize, &tpcb->tp_tpdusize, 0); 48136420Ssklower if( tpcb->tp_state == TP_CLOSED) { 48236420Ssklower soisconnecting(so); 48336420Ssklower error = DoEvent(T_CONN_req); 48436420Ssklower } else { 48536420Ssklower (tpcb->tp_nlproto->nlp_pcbdisc)(so->so_pcb); 48636420Ssklower error = EISCONN; 48736420Ssklower } 48836420Ssklower IFPERF(tpcb) 48936420Ssklower u_int lsufx, fsufx; 49036420Ssklower lsufx = *(u_int *)(tpcb->tp_lsuffix); 49136420Ssklower fsufx = *(u_int *)(tpcb->tp_fsuffix); 49236420Ssklower 49336420Ssklower tpmeas( tpcb->tp_lref, 49436420Ssklower TPtime_open | (tpcb->tp_xtd_format <<4 ), 49536420Ssklower &time, lsufx, fsufx, tpcb->tp_fref); 49636420Ssklower ENDPERF 49736420Ssklower break; 49836420Ssklower 49936420Ssklower case PRU_ACCEPT: 500*38841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 50136420Ssklower IFDEBUG(D_REQUEST) 502*38841Ssklower printf("ACCEPT PEERADDDR:"); 503*38841Ssklower dump_buf(mtod(nam, char *), nam->m_len); 50436420Ssklower ENDDEBUG 50536420Ssklower IFPERF(tpcb) 50636420Ssklower u_int lsufx, fsufx; 50736420Ssklower lsufx = *(u_int *)(tpcb->tp_lsuffix); 50836420Ssklower fsufx = *(u_int *)(tpcb->tp_fsuffix); 50936420Ssklower 51036420Ssklower tpmeas( tpcb->tp_lref, TPtime_open, 51136420Ssklower &time, lsufx, fsufx, tpcb->tp_fref); 51236420Ssklower ENDPERF 51336420Ssklower break; 51436420Ssklower 51536420Ssklower case PRU_RCVD: 516*38841Ssklower if (so->so_state & SS_ISCONFIRMING) { 517*38841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 518*38841Ssklower error = tp_confirm(tpcb); 519*38841Ssklower break; 520*38841Ssklower } 52136420Ssklower IFTRACE(D_DATA) 52236420Ssklower tptraceTPCB(TPPTmisc, 52336420Ssklower "RCVD BF: lcredit sent_lcdt cc hiwat \n", 52436420Ssklower tpcb->tp_lcredit, tpcb->tp_sent_lcdt, 52536420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 52636420Ssklower LOCAL_CREDIT(tpcb); 52736420Ssklower tptraceTPCB(TPPTmisc, 52836420Ssklower "PRU_RCVD AF sbspace lcredit hiwat cc", 52936420Ssklower sbspace(&so->so_rcv), tpcb->tp_lcredit, 53036420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 53136420Ssklower ENDTRACE 53237469Ssklower IFDEBUG(D_REQUEST) 53337469Ssklower printf("RCVD: cc %d space %d hiwat %d\n", 53437469Ssklower so->so_rcv.sb_cc, sbspace(&so->so_rcv), 53537469Ssklower so->so_rcv.sb_hiwat); 53637469Ssklower ENDDEBUG 53737469Ssklower if (((int)nam) & MSG_OOB) 53837469Ssklower error = DoEvent(T_USR_Xrcvd); 53937469Ssklower else 54037469Ssklower error = DoEvent(T_USR_rcvd); 54136420Ssklower break; 54236420Ssklower 54336420Ssklower case PRU_RCVOOB: 54436420Ssklower if ((so->so_state & SS_ISCONNECTED) == 0) { 54536420Ssklower error = ENOTCONN; 54636420Ssklower break; 54736420Ssklower } 54836420Ssklower if( ! tpcb->tp_xpd_service ) { 54936420Ssklower error = EOPNOTSUPP; 55036420Ssklower break; 55136420Ssklower } 55236420Ssklower /* kludge - nam is really flags here */ 55336420Ssklower error = tp_rcvoob(tpcb, so, m, outflags, (int)nam); 55436420Ssklower break; 55536420Ssklower 556*38841Ssklower case PRU_SEND: 55736420Ssklower case PRU_SENDOOB: 55837469Ssklower if (controlp && (error = tp_snd_control(controlp, so, &m))) 55936420Ssklower break; 560*38841Ssklower if (so->so_state & SS_ISCONFIRMING) { 561*38841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 562*38841Ssklower error = tp_confirm(tpcb); 563*38841Ssklower if (m) { 564*38841Ssklower if (error == 0 && m->m_len != 0) 565*38841Ssklower error = ENOTCONN; 566*38841Ssklower m_freem(m); 567*38841Ssklower m = 0; 568*38841Ssklower } 569*38841Ssklower break; 570*38841Ssklower } 57137469Ssklower if (m == 0) 57237469Ssklower break; 573*38841Ssklower 574*38841Ssklower if (req == PRU_SENDOOB) { 575*38841Ssklower if (tpcb->tp_xpd_service == 0) { 576*38841Ssklower error = EOPNOTSUPP; 577*38841Ssklower break; 578*38841Ssklower } 579*38841Ssklower error = tp_sendoob(tpcb, so, m, outflags); 58036420Ssklower break; 58136420Ssklower } 58236420Ssklower /* 58336420Ssklower * The protocol machine copies mbuf chains, 58436420Ssklower * prepends headers, assigns seq numbers, and 58536420Ssklower * puts the packets on the device. 58636420Ssklower * When they are acked they are removed from the socket buf. 58736420Ssklower * 58836420Ssklower * sosend calls this up until sbspace goes negative. 58936420Ssklower * Sbspace may be made negative by appending this mbuf chain, 59036420Ssklower * possibly by a whole cluster. 59136420Ssklower */ 59236420Ssklower { 59337469Ssklower register struct mbuf *n = m; 59436420Ssklower register int len=0; 59536420Ssklower register struct sockbuf *sb = &so->so_snd; 59637469Ssklower int maxsize = tpcb->tp_l_tpdusize 59737469Ssklower - tp_headersize(DT_TPDU_type, tpcb) 59837469Ssklower - (tpcb->tp_use_checksum?4:0) ; 59937469Ssklower int totlen = n->m_pkthdr.len; 60036420Ssklower 60137469Ssklower /* 60237469Ssklower * Could have eotsdu and no data.(presently MUST have 60337469Ssklower * an mbuf though, even if its length == 0) 60437469Ssklower */ 605*38841Ssklower if (n->m_flags & M_EOR) { 60637469Ssklower eotsdu = 1; 607*38841Ssklower n->m_flags &= ~M_EOR; 608*38841Ssklower } 60936420Ssklower IFPERF(tpcb) 61037469Ssklower PStat(tpcb, Nb_from_sess) += totlen; 61136420Ssklower tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0, 61237469Ssklower PStat(tpcb, Nb_from_sess), totlen); 61336420Ssklower ENDPERF 61436420Ssklower IFDEBUG(D_SYSCALL) 61536420Ssklower printf( 61636420Ssklower "PRU_SEND: eot %d before sbappend 0x%x len 0x%x to sb @ 0x%x\n", 61737469Ssklower eotsdu, m,len, sb); 61836420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 61936420Ssklower dump_mbuf(m, "m : to be added"); 62036420Ssklower ENDDEBUG 62137469Ssklower /* 62237469Ssklower * Pre-packetize the data in the sockbuf 62337469Ssklower * according to negotiated mtu. Do it here 62437469Ssklower * where we can safely wait for mbufs. 62536420Ssklower */ 62637469Ssklower while (n->m_pkthdr.len > maxsize) { 62737469Ssklower struct mbuf *nn 62837469Ssklower = m_copym(n, 0, maxsize, M_WAIT); 62937469Ssklower sbappendrecord(sb, nn); 63037469Ssklower m_adj(n, maxsize); 63137469Ssklower } 63237469Ssklower sbappendrecord(sb, n); 633*38841Ssklower if (eotsdu) /* This presumes knowledge of sbappendrecord() */ 634*38841Ssklower n->m_flags |= M_EOR; 63536420Ssklower IFDEBUG(D_SYSCALL) 63636420Ssklower printf("PRU_SEND: eot %d after sbappend 0x%x len 0x%x\n", 63737469Ssklower eotsdu, n, len); 63836420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 63936420Ssklower ENDDEBUG 64036420Ssklower error = DoEvent(T_DATA_req); 64136420Ssklower IFDEBUG(D_SYSCALL) 64236420Ssklower printf("PRU_SEND: after driver error 0x%x \n",error); 64337469Ssklower printf("so_snd 0x%x cc 0t%d mbcnt 0t%d\n", 64437469Ssklower sb, sb->sb_cc, sb->sb_mbcnt); 64537469Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver"); 64636420Ssklower ENDDEBUG 64736420Ssklower } 64836420Ssklower break; 64936420Ssklower 65037469Ssklower case PRU_SOCKADDR: 65137469Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_LOCAL); 65236420Ssklower break; 65336420Ssklower 65436420Ssklower case PRU_PEERADDR: 655*38841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 65636420Ssklower break; 65736420Ssklower 65836420Ssklower case PRU_CONTROL: 65936420Ssklower error = EOPNOTSUPP; 66036420Ssklower break; 66136420Ssklower 66236420Ssklower case PRU_PROTOSEND: 66336420Ssklower case PRU_PROTORCV: 66436420Ssklower case PRU_SENSE: 66536420Ssklower case PRU_SLOWTIMO: 66636420Ssklower case PRU_FASTTIMO: 66736420Ssklower error = EOPNOTSUPP; 66836420Ssklower break; 66936420Ssklower 67036420Ssklower default: 67136420Ssklower #ifdef ARGO_DEBUG 67236420Ssklower printf("tp_usrreq UNKNOWN PRU %d\n", req); 67336420Ssklower #endif ARGO_DEBUG 67436420Ssklower error = EOPNOTSUPP; 67536420Ssklower } 67636420Ssklower 67736420Ssklower IFDEBUG(D_REQUEST) 678*38841Ssklower printf("%s, so 0x%x, tpcb 0x%x, error %d, state %d\n", 679*38841Ssklower "returning from tp_usrreq", so, tpcb, error, 680*38841Ssklower tpcb ? 0 : tpcb->tp_state); 68136420Ssklower ENDDEBUG 68236420Ssklower IFTRACE(D_REQUEST) 68336420Ssklower tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m, 68436420Ssklower tpcb?0:tpcb->tp_state); 68536420Ssklower ENDTRACE 68636420Ssklower splx(s); 68736420Ssklower return error; 68836420Ssklower } 68937469Ssklower 690*38841Ssklower tp_confirm(tpcb) 691*38841Ssklower register struct tp_pcb *tpcb; 69237469Ssklower { 693*38841Ssklower struct tp_event E; 694*38841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 695*38841Ssklower return DoEvent(T_ACPT_req); 696*38841Ssklower printf("Tp confirm called when not confirming; tpcb 0x%x, state 0x%x\n", 697*38841Ssklower tpcb, tpcb->tp_state); 698*38841Ssklower return 0; 69937469Ssklower } 70037469Ssklower 70137469Ssklower /* 70237469Ssklower * Process control data sent with sendmsg() 70337469Ssklower */ 70437469Ssklower tp_snd_control(m0, so, data) 70537469Ssklower register struct mbuf *m0; 70637469Ssklower struct socket *so; 70737469Ssklower register struct mbuf **data; 70837469Ssklower { 70937469Ssklower register struct tp_control_hdr *ch; 71037469Ssklower struct mbuf *m; 71137469Ssklower int error = 0; 71237469Ssklower 71337469Ssklower if (m0 && m0->m_len) { 71437469Ssklower ch = mtod(m0, struct tp_control_hdr *); 71537469Ssklower m0->m_len -= sizeof (*ch); 71637469Ssklower m0->m_data += sizeof (*ch); 71737469Ssklower m = m_copym(m0, 0, M_COPYALL, M_WAIT); 71837469Ssklower error = tp_ctloutput(PRCO_SETOPT, 71937469Ssklower so, ch->cmsg_level, ch->cmsg_type, &m); 72037469Ssklower if (m) 72137469Ssklower m_freem(m); 72237469Ssklower if (ch->cmsg_type == TPOPT_DISC_DATA) { 72337469Ssklower if (data && *data) { 72437469Ssklower m_freem(*data); 72537469Ssklower *data = 0; 72637469Ssklower } 72737469Ssklower m0 = 0; 72837469Ssklower error = tp_usrreq(so, PRU_DISCONNECT, m0, (caddr_t)0, m0, m0); 72937469Ssklower } 73037469Ssklower } 73137469Ssklower return error; 73237469Ssklower } 733