136420Ssklower /*********************************************************** 239196Ssklower 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*39647Ssklower * @(#)tp_usrreq.c 7.6 (Berkeley) 11/28/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 17838841Ssklower 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 18838841Ssklower 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 */ 27738841Ssklower if (sb->sb_mb) { /* Anything already in eXpedited data sockbuf? */ 27836420Ssklower if (so->so_state & SS_NBIO) { 27936420Ssklower return EWOULDBLOCK; 28036420Ssklower } 28138841Ssklower while (sb->sb_mb) { 28238841Ssklower sbunlock(&so->so_snd); /* already locked by sosend */ 28338841Ssklower sbwait(&so->so_snd); 28438841Ssklower sblock(&so->so_snd); /* sosend will unlock on return */ 28538841Ssklower } 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) 31838841Ssklower 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: 42138841Ssklower 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 45038841Ssklower 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; 49039196Ssklower lsufx = *(u_short *)(tpcb->tp_lsuffix); 49139196Ssklower fsufx = *(u_short *)(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: 50038841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 50136420Ssklower IFDEBUG(D_REQUEST) 50238841Ssklower printf("ACCEPT PEERADDDR:"); 50338841Ssklower dump_buf(mtod(nam, char *), nam->m_len); 50436420Ssklower ENDDEBUG 50536420Ssklower IFPERF(tpcb) 50636420Ssklower u_int lsufx, fsufx; 50739196Ssklower lsufx = *(u_short *)(tpcb->tp_lsuffix); 50839196Ssklower fsufx = *(u_short *)(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: 51638841Ssklower if (so->so_state & SS_ISCONFIRMING) { 51738841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 51838841Ssklower error = tp_confirm(tpcb); 51938841Ssklower break; 52038841Ssklower } 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 55638841Ssklower case PRU_SEND: 55736420Ssklower case PRU_SENDOOB: 55837469Ssklower if (controlp && (error = tp_snd_control(controlp, so, &m))) 55936420Ssklower break; 56038841Ssklower if (so->so_state & SS_ISCONFIRMING) { 56138841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 56238841Ssklower error = tp_confirm(tpcb); 56338841Ssklower if (m) { 56438841Ssklower if (error == 0 && m->m_len != 0) 56538841Ssklower error = ENOTCONN; 56638841Ssklower m_freem(m); 56738841Ssklower m = 0; 56838841Ssklower } 56938841Ssklower break; 57038841Ssklower } 57137469Ssklower if (m == 0) 57237469Ssklower break; 57338841Ssklower 57438841Ssklower if (req == PRU_SENDOOB) { 57538841Ssklower if (tpcb->tp_xpd_service == 0) { 57638841Ssklower error = EOPNOTSUPP; 57738841Ssklower break; 57838841Ssklower } 57938841Ssklower 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; 60039196Ssklower struct mbuf *nn; 60136420Ssklower 60237469Ssklower /* 60337469Ssklower * Could have eotsdu and no data.(presently MUST have 60437469Ssklower * an mbuf though, even if its length == 0) 60537469Ssklower */ 60638841Ssklower if (n->m_flags & M_EOR) { 60737469Ssklower eotsdu = 1; 60838841Ssklower n->m_flags &= ~M_EOR; 60938841Ssklower } 61036420Ssklower IFPERF(tpcb) 61137469Ssklower PStat(tpcb, Nb_from_sess) += totlen; 61236420Ssklower tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0, 61337469Ssklower PStat(tpcb, Nb_from_sess), totlen); 61436420Ssklower ENDPERF 61536420Ssklower IFDEBUG(D_SYSCALL) 61636420Ssklower printf( 61736420Ssklower "PRU_SEND: eot %d before sbappend 0x%x len 0x%x to sb @ 0x%x\n", 61837469Ssklower eotsdu, m,len, sb); 61936420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 62036420Ssklower dump_mbuf(m, "m : to be added"); 62136420Ssklower ENDDEBUG 62237469Ssklower /* 62337469Ssklower * Pre-packetize the data in the sockbuf 62437469Ssklower * according to negotiated mtu. Do it here 62537469Ssklower * where we can safely wait for mbufs. 62639196Ssklower * 62739196Ssklower * This presumes knowledge of sockbuf conventions. 62836420Ssklower */ 62939196Ssklower len = 0; 63039196Ssklower if (n = sb->sb_mb) 63139196Ssklower while (n->m_act) 63239196Ssklower n = n->m_act; 633*39647Ssklower if ((nn = n) && n->m_pkthdr.len < maxsize) { 63439196Ssklower int space = maxsize - n->m_pkthdr.len; 635*39647Ssklower 636*39647Ssklower do { 637*39647Ssklower if (n->m_flags & M_EOR) 638*39647Ssklower goto on1; 639*39647Ssklower } while (n->m_next && (n = n->m_next)); 640*39647Ssklower nn->m_pkthdr.len += space; 64139196Ssklower if (m->m_pkthdr.len <= space) { 64239196Ssklower n->m_next = m; 643*39647Ssklower sballoc(sb, m); 64439196Ssklower if (eotsdu) 64539196Ssklower nn->m_flags |= M_EOR; 64639196Ssklower goto on2; 64739196Ssklower } else { 648*39647Ssklower nn->m_next = m_copym(m, 0, space, M_WAIT); 649*39647Ssklower sballoc(sb, nn->m_next); 650*39647Ssklower m_adj(m, space); 65139196Ssklower } 65239196Ssklower } 65339196Ssklower on1: len++; 65439196Ssklower for (n = m; n->m_pkthdr.len > maxsize;) { 65539196Ssklower nn = m_copym(n, 0, len, M_WAIT); 65637469Ssklower sbappendrecord(sb, nn); 65737469Ssklower m_adj(n, maxsize); 65839196Ssklower len++; 65937469Ssklower } 66039196Ssklower if (eotsdu) 66139196Ssklower n->m_flags |= M_EOR; 66237469Ssklower sbappendrecord(sb, n); 66339196Ssklower on2: 66439196Ssklower IFTRACE(D_DATA) 66539196Ssklower tptraceTPCB(TPPTmisc, 66639196Ssklower "SEND BF: maxsize totlen frags eotsdu", 66739196Ssklower maxsize, totlen, len, eotsdu); 66839196Ssklower ENDTRACE 66936420Ssklower IFDEBUG(D_SYSCALL) 67036420Ssklower printf("PRU_SEND: eot %d after sbappend 0x%x len 0x%x\n", 67137469Ssklower eotsdu, n, len); 67236420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 67336420Ssklower ENDDEBUG 67436420Ssklower error = DoEvent(T_DATA_req); 67536420Ssklower IFDEBUG(D_SYSCALL) 67636420Ssklower printf("PRU_SEND: after driver error 0x%x \n",error); 67737469Ssklower printf("so_snd 0x%x cc 0t%d mbcnt 0t%d\n", 67837469Ssklower sb, sb->sb_cc, sb->sb_mbcnt); 67937469Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver"); 68036420Ssklower ENDDEBUG 68136420Ssklower } 68236420Ssklower break; 68336420Ssklower 68437469Ssklower case PRU_SOCKADDR: 68537469Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_LOCAL); 68636420Ssklower break; 68736420Ssklower 68836420Ssklower case PRU_PEERADDR: 68938841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 69036420Ssklower break; 69136420Ssklower 69236420Ssklower case PRU_CONTROL: 69336420Ssklower error = EOPNOTSUPP; 69436420Ssklower break; 69536420Ssklower 69636420Ssklower case PRU_PROTOSEND: 69736420Ssklower case PRU_PROTORCV: 69836420Ssklower case PRU_SENSE: 69936420Ssklower case PRU_SLOWTIMO: 70036420Ssklower case PRU_FASTTIMO: 70136420Ssklower error = EOPNOTSUPP; 70236420Ssklower break; 70336420Ssklower 70436420Ssklower default: 70536420Ssklower #ifdef ARGO_DEBUG 70636420Ssklower printf("tp_usrreq UNKNOWN PRU %d\n", req); 70736420Ssklower #endif ARGO_DEBUG 70836420Ssklower error = EOPNOTSUPP; 70936420Ssklower } 71036420Ssklower 71136420Ssklower IFDEBUG(D_REQUEST) 71238841Ssklower printf("%s, so 0x%x, tpcb 0x%x, error %d, state %d\n", 71338841Ssklower "returning from tp_usrreq", so, tpcb, error, 71438841Ssklower tpcb ? 0 : tpcb->tp_state); 71536420Ssklower ENDDEBUG 71636420Ssklower IFTRACE(D_REQUEST) 71736420Ssklower tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m, 71836420Ssklower tpcb?0:tpcb->tp_state); 71936420Ssklower ENDTRACE 72036420Ssklower splx(s); 72136420Ssklower return error; 72236420Ssklower } 72339196Ssklower tp_ltrace(so, uio) 72439196Ssklower struct socket *so; 72539196Ssklower struct uio *uio; 72639196Ssklower { 72739196Ssklower IFTRACE(D_DATA) 72839196Ssklower register struct tp_pcb *tpcb = sototpcb(so); 72939196Ssklower if (tpcb) { 73039196Ssklower tptraceTPCB(TPPTmisc, "sosend so resid iovcnt", so, 73139196Ssklower uio->uio_resid, uio->uio_iovcnt, 0); 73239196Ssklower } 73339196Ssklower ENDTRACE 73439196Ssklower } 73537469Ssklower 73638841Ssklower tp_confirm(tpcb) 73738841Ssklower register struct tp_pcb *tpcb; 73837469Ssklower { 73938841Ssklower struct tp_event E; 74038841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 74138841Ssklower return DoEvent(T_ACPT_req); 74238841Ssklower printf("Tp confirm called when not confirming; tpcb 0x%x, state 0x%x\n", 74338841Ssklower tpcb, tpcb->tp_state); 74438841Ssklower return 0; 74537469Ssklower } 74637469Ssklower 74737469Ssklower /* 74837469Ssklower * Process control data sent with sendmsg() 74937469Ssklower */ 75037469Ssklower tp_snd_control(m0, so, data) 75137469Ssklower register struct mbuf *m0; 75237469Ssklower struct socket *so; 75337469Ssklower register struct mbuf **data; 75437469Ssklower { 75537469Ssklower register struct tp_control_hdr *ch; 75637469Ssklower struct mbuf *m; 75737469Ssklower int error = 0; 75837469Ssklower 75937469Ssklower if (m0 && m0->m_len) { 76037469Ssklower ch = mtod(m0, struct tp_control_hdr *); 76137469Ssklower m0->m_len -= sizeof (*ch); 76237469Ssklower m0->m_data += sizeof (*ch); 76337469Ssklower m = m_copym(m0, 0, M_COPYALL, M_WAIT); 76437469Ssklower error = tp_ctloutput(PRCO_SETOPT, 76537469Ssklower so, ch->cmsg_level, ch->cmsg_type, &m); 76637469Ssklower if (m) 76737469Ssklower m_freem(m); 76837469Ssklower if (ch->cmsg_type == TPOPT_DISC_DATA) { 76937469Ssklower if (data && *data) { 77037469Ssklower m_freem(*data); 77137469Ssklower *data = 0; 77237469Ssklower } 77337469Ssklower m0 = 0; 77437469Ssklower error = tp_usrreq(so, PRU_DISCONNECT, m0, (caddr_t)0, m0, m0); 77537469Ssklower } 77637469Ssklower } 77737469Ssklower return error; 77837469Ssklower } 779