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*40773Ssklower * @(#)tp_usrreq.c 7.8 (Berkeley) 04/05/90 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(); 6839937Ssklower int TNew; 6939937Ssklower int TPNagle1, TPNagle2; 7036420Ssklower 7136420Ssklower #ifdef ARGO_DEBUG 7236420Ssklower /* 7336420Ssklower * CALLED FROM: 7436420Ssklower * anywhere you want to debug... 7536420Ssklower * FUNCTION and ARGUMENTS: 7636420Ssklower * print (str) followed by the control info in the mbufs of an mbuf chain (n) 7736420Ssklower */ 7836420Ssklower void 7936420Ssklower dump_mbuf(n, str) 8036420Ssklower struct mbuf *n; 8136420Ssklower char *str; 8236420Ssklower { 8336420Ssklower struct mbuf *nextrecord; 8436420Ssklower 8536420Ssklower printf("dump %s\n", str); 8636420Ssklower 8736420Ssklower if( n == MNULL) { 8836420Ssklower printf("EMPTY:\n"); 8936420Ssklower return; 9036420Ssklower } 9136420Ssklower 9236420Ssklower for(;n;) { 9336420Ssklower nextrecord = n->m_act; 9436420Ssklower printf("RECORD:\n"); 9536420Ssklower while (n) { 9637469Ssklower printf("%x : Len %x Data %x A %x Nx %x Tp %x\n", 9737469Ssklower n, n->m_len, n->m_data, n->m_act, n->m_next, n->m_type); 9836420Ssklower #ifdef notdef 9936420Ssklower { 10036420Ssklower register char *p = mtod(n, char *); 10136420Ssklower register int i; 10236420Ssklower 10336420Ssklower printf("data: "); 10436420Ssklower for(i=0; i < n->m_len; i++ ) { 10536420Ssklower if(i%8 == 0) 10636420Ssklower printf("\n"); 10736420Ssklower printf("0x%x ", *(p+i)); 10836420Ssklower } 10936420Ssklower printf("\n"); 11036420Ssklower } 11136420Ssklower #endif notdef 11236420Ssklower if( n->m_next == n ) { 11336420Ssklower printf("LOOP!\n"); 11436420Ssklower return; 11536420Ssklower } 11636420Ssklower n = n->m_next; 11736420Ssklower } 11836420Ssklower n = nextrecord; 11936420Ssklower } 12036420Ssklower printf("\n"); 12136420Ssklower } 12236420Ssklower 12336420Ssklower #endif ARGO_DEBUG 12436420Ssklower 12536420Ssklower /* 12636420Ssklower * CALLED FROM: 12736420Ssklower * tp_usrreq(), PRU_RCVOOB 12836420Ssklower * FUNCTION and ARGUMENTS: 12936420Ssklower * Copy data from the expedited data socket buffer into 13036420Ssklower * the pre-allocated mbuf m. 13136420Ssklower * There is an isomorphism between XPD TPDUs and expedited data TSDUs. 13236420Ssklower * XPD tpdus are limited to 16 bytes of data so they fit in one mbuf. 13336420Ssklower * RETURN VALUE: 13436420Ssklower * EINVAL if debugging is on and a disaster has occurred 13536420Ssklower * ENOTCONN if the socket isn't connected 13636420Ssklower * EWOULDBLOCK if the socket is in non-blocking mode and there's no 13736420Ssklower * xpd data in the buffer 13836420Ssklower * E* whatever is returned from the fsm. 13936420Ssklower */ 14036420Ssklower tp_rcvoob(tpcb, so, m, outflags, inflags) 14136420Ssklower struct tp_pcb *tpcb; 14236420Ssklower register struct socket *so; 14336420Ssklower register struct mbuf *m; 14436420Ssklower int *outflags; 14536420Ssklower int inflags; 14636420Ssklower { 14736420Ssklower register struct mbuf *n; 14837469Ssklower register struct sockbuf *sb = &so->so_rcv; 14936420Ssklower struct tp_event E; 15036420Ssklower int error = 0; 15137469Ssklower register struct mbuf **nn; 15236420Ssklower 15336420Ssklower IFDEBUG(D_XPD) 15436420Ssklower printf("PRU_RCVOOB, sostate 0x%x\n", so->so_state); 15536420Ssklower ENDDEBUG 15636420Ssklower 15736420Ssklower /* if you use soreceive */ 15836420Ssklower if (m==MNULL) 15936420Ssklower return ENOBUFS; 16036420Ssklower 16136420Ssklower restart: 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 16837469Ssklower /* Take the first mbuf off the chain. 16937469Ssklower * Each XPD TPDU gives you a complete TSDU so the chains don't get 17037469Ssklower * coalesced, but one TSDU may span several mbufs. 17137469Ssklower * Nevertheless, since n should have a most 16 bytes, it 17237469Ssklower * will fit into m. (size was checked in tp_input() ) 17337469Ssklower */ 17437469Ssklower 17537469Ssklower /* 17637469Ssklower * Code for excision of OOB data should be added to 17737469Ssklower * uipc_socket2.c (like sbappend). 17837469Ssklower */ 17937469Ssklower 18038841Ssklower sblock(sb); 18137469Ssklower for (nn = &sb->sb_mb; n = *nn; nn = &n->m_act) 18237469Ssklower if (n->m_type == MT_OOBDATA) 18337469Ssklower break; 18437469Ssklower 18537469Ssklower if (n == 0) { 18636420Ssklower ASSERT( (tpcb->tp_flags & TPF_DISC_DATA_IN) == 0 ); 18736420Ssklower IFDEBUG(D_XPD) 18836420Ssklower printf("RCVOOB: empty queue!\n"); 18936420Ssklower ENDDEBUG 19038841Ssklower sbunlock(sb); 19136420Ssklower if (so->so_state & SS_NBIO) { 19236420Ssklower return EWOULDBLOCK; 19336420Ssklower } 19436420Ssklower sbwait(sb); 19536420Ssklower goto restart; 19636420Ssklower } 19736420Ssklower m->m_len = 0; 19836420Ssklower 19936420Ssklower /* Assuming at most one xpd tpdu is in the buffer at once */ 20036420Ssklower while ( n != MNULL ) { 20136420Ssklower m->m_len += n->m_len; 20237469Ssklower bcopy(mtod(n, caddr_t), mtod(m, caddr_t), (unsigned)n->m_len); 20337469Ssklower m->m_data += n->m_len; /* so mtod() in bcopy() above gives right addr */ 20436420Ssklower n = n->m_next; 20536420Ssklower } 20637469Ssklower m->m_data = m->m_dat; 20737469Ssklower m->m_flags |= M_EOR; 20836420Ssklower 20936420Ssklower IFDEBUG(D_XPD) 21036420Ssklower printf("tp_rcvoob: xpdlen 0x%x\n", m->m_len); 21136420Ssklower dump_mbuf(so->so_rcv.sb_mb, "RCVOOB: Rcv socketbuf"); 21236420Ssklower dump_mbuf(sb->sb_mb, "RCVOOB: Xrcv socketbuf"); 21336420Ssklower ENDDEBUG 21436420Ssklower 21537469Ssklower if( (inflags & MSG_PEEK) == 0 ) { 21637469Ssklower n = *nn; 21737469Ssklower *nn = n->m_act; 21837469Ssklower sb->sb_cc -= m->m_len; 21937469Ssklower } 22036420Ssklower 22136420Ssklower release: 22236420Ssklower sbunlock(sb); 22336420Ssklower 22436420Ssklower IFTRACE(D_XPD) 22536420Ssklower tptraceTPCB(TPPTmisc, "PRU_RCVOOB @ release sb_cc m_len", 22636420Ssklower tpcb->tp_Xrcv.sb_cc, m->m_len,0,0 ); 22736420Ssklower ENDTRACE 22836420Ssklower if (error == 0) 22936420Ssklower error = DoEvent(T_USR_Xrcvd); 23036420Ssklower return error; 23136420Ssklower } 23236420Ssklower 23336420Ssklower /* 23436420Ssklower * CALLED FROM: 23536420Ssklower * tp_usrreq(), PRU_SENDOOB 23636420Ssklower * FUNCTION and ARGUMENTS: 23736420Ssklower * Send what's in the mbuf chain (m) as an XPD TPDU. 23836420Ssklower * The mbuf may not contain more then 16 bytes of data. 23936420Ssklower * XPD TSDUs aren't segmented, so they translate into 24036420Ssklower * exactly one XPD TPDU, with EOT bit set. 24136420Ssklower * RETURN VALUE: 24236420Ssklower * EWOULDBLOCK if socket is in non-blocking mode and the previous 24336420Ssklower * xpd data haven't been acked yet. 24436420Ssklower * EMSGSIZE if trying to send > max-xpd bytes (16) 24536420Ssklower * ENOBUFS if ran out of mbufs 24636420Ssklower */ 24736420Ssklower tp_sendoob(tpcb, so, xdata, outflags) 24836420Ssklower struct tp_pcb *tpcb; 24936420Ssklower register struct socket *so; 25036420Ssklower register struct mbuf *xdata; 25136420Ssklower int *outflags; /* not used */ 25236420Ssklower { 25336420Ssklower /* 25436420Ssklower * Each mbuf chain represents a sequence # in the XPD seq space. 25536420Ssklower * The first one in the queue has sequence # tp_Xuna. 25636420Ssklower * When we add to the XPD queue, we stuff a zero-length 25736420Ssklower * mbuf (mark) into the DATA queue, with its sequence number in m_next 25836420Ssklower * to be assigned to this XPD tpdu, so data xfer can stop 25936420Ssklower * when it reaches the zero-length mbuf if this XPD TPDU hasn't 26036420Ssklower * yet been acknowledged. 26136420Ssklower */ 26236420Ssklower register struct sockbuf *sb = &(tpcb->tp_Xsnd); 26336420Ssklower register struct mbuf *xmark; 26436420Ssklower register int len=0; 26536420Ssklower struct tp_event E; 26636420Ssklower 26736420Ssklower IFDEBUG(D_XPD) 26836420Ssklower printf("tp_sendoob:"); 26936420Ssklower if(xdata) 27036420Ssklower printf("xdata len 0x%x\n", xdata->m_len); 27136420Ssklower ENDDEBUG 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 */ 27938841Ssklower if (sb->sb_mb) { /* Anything already in eXpedited data sockbuf? */ 28036420Ssklower if (so->so_state & SS_NBIO) { 28136420Ssklower return EWOULDBLOCK; 28236420Ssklower } 28338841Ssklower while (sb->sb_mb) { 28438841Ssklower sbunlock(&so->so_snd); /* already locked by sosend */ 28538841Ssklower sbwait(&so->so_snd); 28638841Ssklower sblock(&so->so_snd); /* sosend will unlock on return */ 28738841Ssklower } 28836420Ssklower } 28936420Ssklower 29036420Ssklower if (xdata == (struct mbuf *)0) { 29136420Ssklower /* empty xpd packet */ 29237469Ssklower MGETHDR(xdata, M_WAIT, MT_OOBDATA); 29336420Ssklower if (xdata == NULL) { 29436420Ssklower return ENOBUFS; 29536420Ssklower } 29636420Ssklower xdata->m_len = 0; 29737469Ssklower xdata->m_pkthdr.len = 0; 29836420Ssklower } 29936420Ssklower IFDEBUG(D_XPD) 30036420Ssklower printf("tp_sendoob 1:"); 30136420Ssklower if(xdata) 30236420Ssklower printf("xdata len 0x%x\n", xdata->m_len); 30336420Ssklower ENDDEBUG 30436420Ssklower xmark = xdata; /* temporary use of variable xmark */ 30536420Ssklower while (xmark) { 30636420Ssklower len += xmark->m_len; 30736420Ssklower xmark = xmark->m_next; 30836420Ssklower } 30936420Ssklower if (len > TP_MAX_XPD_DATA) { 31036420Ssklower return EMSGSIZE; 31136420Ssklower } 31236420Ssklower IFDEBUG(D_XPD) 31336420Ssklower printf("tp_sendoob 2:"); 31436420Ssklower if(xdata) 31536420Ssklower printf("xdata len 0x%x\n", len); 31636420Ssklower ENDDEBUG 31736420Ssklower 31836420Ssklower 31936420Ssklower IFTRACE(D_XPD) 32038841Ssklower tptraceTPCB(TPPTmisc, "XPD mark m_next ", xdata->m_next, 0, 0, 0); 32136420Ssklower ENDTRACE 32236420Ssklower 32336420Ssklower sbappendrecord(sb, xdata); 32436420Ssklower 32536420Ssklower IFDEBUG(D_XPD) 32636420Ssklower printf("tp_sendoob len 0x%x\n", len); 32736420Ssklower dump_mbuf(so->so_snd.sb_mb, "XPD request Regular sndbuf:"); 32836420Ssklower dump_mbuf(tpcb->tp_Xsnd.sb_mb, "XPD request Xsndbuf:"); 32936420Ssklower ENDDEBUG 33036420Ssklower return DoEvent(T_XPD_req); 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 */ 34436420Ssklower /*ARGSUSED*/ 34536420Ssklower ProtoHook 346*40773Ssklower tp_usrreq(so, req, m, nam, controlp) 34736420Ssklower struct socket *so; 34836420Ssklower u_int req; 349*40773Ssklower struct mbuf *m, *nam, *controlp; 35036420Ssklower { 35136420Ssklower register struct tp_pcb *tpcb = sototpcb(so); 35236420Ssklower int s = splnet(); 35336420Ssklower int error = 0; 35437469Ssklower int flags, *outflags = &flags; 35536420Ssklower u_long eotsdu = 0; 35636420Ssklower struct tp_event E; 35736420Ssklower 35836420Ssklower IFDEBUG(D_REQUEST) 35936420Ssklower printf("usrreq(0x%x,%d,0x%x,0x%x,0x%x)\n",so,req,m,nam,outflags); 36036420Ssklower if(so->so_error) 36136420Ssklower printf("WARNING!!! so->so_error is 0x%x\n", so->so_error); 36236420Ssklower ENDDEBUG 36336420Ssklower IFTRACE(D_REQUEST) 36436420Ssklower tptraceTPCB(TPPTusrreq, "req so m state [", req, so, m, 36536420Ssklower tpcb?tpcb->tp_state:0); 36636420Ssklower ENDTRACE 36736420Ssklower 36836420Ssklower if ((u_int)tpcb == 0 && req != PRU_ATTACH) { 36936420Ssklower IFTRACE(D_REQUEST) 37036420Ssklower tptraceTPCB(TPPTusrreq, "req failed NO TPCB[", 0, 0, 0, 0); 37136420Ssklower ENDTRACE 37236420Ssklower splx(s); 37336420Ssklower return ENOTCONN; 37436420Ssklower } 37536420Ssklower 37636420Ssklower switch (req) { 37736420Ssklower 37836420Ssklower case PRU_ATTACH: 37936420Ssklower if (tpcb) { 38036420Ssklower error = EISCONN; 38136420Ssklower break; 38236420Ssklower } 38336420Ssklower if( error = tp_attach(so, so->so_proto->pr_domain->dom_family ) ) 38436420Ssklower break; 38536420Ssklower tpcb = sototpcb(so); 38636420Ssklower break; 38736420Ssklower 38836420Ssklower case PRU_ABORT: /* called from close() */ 38936420Ssklower /* called for each incoming connect queued on the 39036420Ssklower * parent (accepting) socket 39136420Ssklower */ 39236420Ssklower if( tpcb->tp_state == TP_OPEN ) { 39336420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NO_SESSION; 39436420Ssklower error = DoEvent(T_DISC_req); /* pretend it was a close() */ 39536420Ssklower break; 39636420Ssklower } /* else DROP THROUGH */ 39736420Ssklower 39836420Ssklower case PRU_DETACH: /* called from close() */ 39936420Ssklower /* called only after disconnect was called */ 40036420Ssklower error = DoEvent(T_DETACH); 40137469Ssklower if (tpcb->tp_state == TP_CLOSED) { 40237469Ssklower free((caddr_t)tpcb, M_PCB); 40337469Ssklower tpcb = 0; 40437469Ssklower } 40536420Ssklower break; 40636420Ssklower 40736420Ssklower case PRU_SHUTDOWN: 40836420Ssklower /* recv end may have been released; local credit might be zero */ 40936420Ssklower case PRU_DISCONNECT: 41036420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NORMAL_DISC; 41136420Ssklower error = DoEvent(T_DISC_req); 41236420Ssklower break; 41336420Ssklower 41436420Ssklower case PRU_BIND: 41536420Ssklower error = (tpcb->tp_nlproto->nlp_pcbbind)( so->so_pcb, nam ); 41636420Ssklower if (error == 0) { 41737469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 41837469Ssklower tpcb->tp_lsuffix, TP_LOCAL ); 41936420Ssklower } 42036420Ssklower break; 42136420Ssklower 42236420Ssklower case PRU_LISTEN: 42338841Ssklower if( tpcb->tp_lsuffixlen == 0) { 42436420Ssklower if( error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL) ) 42536420Ssklower break; 42637469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 42737469Ssklower tpcb->tp_lsuffix, TP_LOCAL ); 42836420Ssklower } 42936420Ssklower IFDEBUG(D_TPISO) 43036420Ssklower if(tpcb->tp_state != TP_CLOSED) 43136420Ssklower printf("LISTEN ERROR: state 0x%x\n", tpcb->tp_state); 43236420Ssklower ENDDEBUG 43336420Ssklower error = DoEvent(T_LISTEN_req); 43436420Ssklower break; 43536420Ssklower 43636420Ssklower case PRU_CONNECT2: 43736420Ssklower error = EOPNOTSUPP; /* for unix domain sockets */ 43836420Ssklower break; 43936420Ssklower 44036420Ssklower case PRU_CONNECT: 44136420Ssklower IFTRACE(D_CONN) 44236420Ssklower tptraceTPCB(TPPTmisc, 44337469Ssklower "PRU_CONNECT: so 0x%x *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 44436420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 44536420Ssklower tpcb->tp_class); 44636420Ssklower ENDTRACE 44736420Ssklower IFDEBUG(D_CONN) 44836420Ssklower printf("PRU_CONNECT: so *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 44936420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 45036420Ssklower tpcb->tp_class); 45136420Ssklower ENDDEBUG 45238841Ssklower if( tpcb->tp_lsuffixlen == 0) { 45336420Ssklower if( error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL) ) { 45436420Ssklower IFDEBUG(D_CONN) 45536420Ssklower printf("pcbbind returns error 0x%x\n", error ); 45636420Ssklower ENDDEBUG 45736420Ssklower break; 45836420Ssklower } 45937469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 46037469Ssklower tpcb->tp_lsuffix, TP_LOCAL ); 46137469Ssklower } 46236420Ssklower 46336420Ssklower IFDEBUG(D_CONN) 46436420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 46536420Ssklower dump_buf( tpcb->tp_npcb, 16); 46636420Ssklower ENDDEBUG 46736420Ssklower if( error = tp_route_to( nam, tpcb, /* channel */0) ) 46836420Ssklower break; 46936420Ssklower IFDEBUG(D_CONN) 47036420Ssklower printf( 47136420Ssklower "PRU_CONNECT after tpcb 0x%x so 0x%x npcb 0x%x flags 0x%x\n", 47236420Ssklower tpcb, so, tpcb->tp_npcb, tpcb->tp_flags); 47336420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 47436420Ssklower dump_buf( tpcb->tp_npcb, 16); 47536420Ssklower ENDDEBUG 47637469Ssklower if( tpcb->tp_fsuffixlen == 0) { 47736420Ssklower /* didn't set peer extended suffix */ 47837469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_fsuffixlen, 47937469Ssklower tpcb->tp_fsuffix, TP_FOREIGN ); 48036420Ssklower } 48136420Ssklower (void) (tpcb->tp_nlproto->nlp_mtu)(so, so->so_pcb, 48236420Ssklower &tpcb->tp_l_tpdusize, &tpcb->tp_tpdusize, 0); 48336420Ssklower if( tpcb->tp_state == TP_CLOSED) { 48436420Ssklower soisconnecting(so); 48536420Ssklower error = DoEvent(T_CONN_req); 48636420Ssklower } else { 48736420Ssklower (tpcb->tp_nlproto->nlp_pcbdisc)(so->so_pcb); 48836420Ssklower error = EISCONN; 48936420Ssklower } 49036420Ssklower IFPERF(tpcb) 49136420Ssklower u_int lsufx, fsufx; 49239196Ssklower lsufx = *(u_short *)(tpcb->tp_lsuffix); 49339196Ssklower fsufx = *(u_short *)(tpcb->tp_fsuffix); 49436420Ssklower 49536420Ssklower tpmeas( tpcb->tp_lref, 49636420Ssklower TPtime_open | (tpcb->tp_xtd_format <<4 ), 49736420Ssklower &time, lsufx, fsufx, tpcb->tp_fref); 49836420Ssklower ENDPERF 49936420Ssklower break; 50036420Ssklower 50136420Ssklower case PRU_ACCEPT: 50238841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 50336420Ssklower IFDEBUG(D_REQUEST) 50438841Ssklower printf("ACCEPT PEERADDDR:"); 50538841Ssklower dump_buf(mtod(nam, char *), nam->m_len); 50636420Ssklower ENDDEBUG 50736420Ssklower IFPERF(tpcb) 50836420Ssklower u_int lsufx, fsufx; 50939196Ssklower lsufx = *(u_short *)(tpcb->tp_lsuffix); 51039196Ssklower fsufx = *(u_short *)(tpcb->tp_fsuffix); 51136420Ssklower 51236420Ssklower tpmeas( tpcb->tp_lref, TPtime_open, 51336420Ssklower &time, lsufx, fsufx, tpcb->tp_fref); 51436420Ssklower ENDPERF 51536420Ssklower break; 51636420Ssklower 51736420Ssklower case PRU_RCVD: 51838841Ssklower if (so->so_state & SS_ISCONFIRMING) { 51938841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 52038841Ssklower error = tp_confirm(tpcb); 52138841Ssklower break; 52238841Ssklower } 52336420Ssklower IFTRACE(D_DATA) 52436420Ssklower tptraceTPCB(TPPTmisc, 52536420Ssklower "RCVD BF: lcredit sent_lcdt cc hiwat \n", 52636420Ssklower tpcb->tp_lcredit, tpcb->tp_sent_lcdt, 52736420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 52836420Ssklower LOCAL_CREDIT(tpcb); 52936420Ssklower tptraceTPCB(TPPTmisc, 53036420Ssklower "PRU_RCVD AF sbspace lcredit hiwat cc", 53136420Ssklower sbspace(&so->so_rcv), tpcb->tp_lcredit, 53236420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 53336420Ssklower ENDTRACE 53437469Ssklower IFDEBUG(D_REQUEST) 53537469Ssklower printf("RCVD: cc %d space %d hiwat %d\n", 53637469Ssklower so->so_rcv.sb_cc, sbspace(&so->so_rcv), 53737469Ssklower so->so_rcv.sb_hiwat); 53837469Ssklower ENDDEBUG 53937469Ssklower if (((int)nam) & MSG_OOB) 54037469Ssklower error = DoEvent(T_USR_Xrcvd); 54137469Ssklower else 54237469Ssklower error = DoEvent(T_USR_rcvd); 54336420Ssklower break; 54436420Ssklower 54536420Ssklower case PRU_RCVOOB: 54636420Ssklower if ((so->so_state & SS_ISCONNECTED) == 0) { 54736420Ssklower error = ENOTCONN; 54836420Ssklower break; 54936420Ssklower } 55036420Ssklower if( ! tpcb->tp_xpd_service ) { 55136420Ssklower error = EOPNOTSUPP; 55236420Ssklower break; 55336420Ssklower } 55436420Ssklower /* kludge - nam is really flags here */ 55536420Ssklower error = tp_rcvoob(tpcb, so, m, outflags, (int)nam); 55636420Ssklower break; 55736420Ssklower 55838841Ssklower case PRU_SEND: 55936420Ssklower case PRU_SENDOOB: 56037469Ssklower if (controlp && (error = tp_snd_control(controlp, so, &m))) 56136420Ssklower break; 56238841Ssklower if (so->so_state & SS_ISCONFIRMING) { 56338841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 56438841Ssklower error = tp_confirm(tpcb); 56538841Ssklower if (m) { 56638841Ssklower if (error == 0 && m->m_len != 0) 56738841Ssklower error = ENOTCONN; 56838841Ssklower m_freem(m); 56938841Ssklower m = 0; 57038841Ssklower } 57138841Ssklower break; 57238841Ssklower } 57337469Ssklower if (m == 0) 57437469Ssklower break; 57538841Ssklower 57638841Ssklower if (req == PRU_SENDOOB) { 57738841Ssklower if (tpcb->tp_xpd_service == 0) { 57838841Ssklower error = EOPNOTSUPP; 57938841Ssklower break; 58038841Ssklower } 58138841Ssklower error = tp_sendoob(tpcb, so, m, outflags); 58236420Ssklower break; 58336420Ssklower } 58436420Ssklower /* 58536420Ssklower * The protocol machine copies mbuf chains, 58636420Ssklower * prepends headers, assigns seq numbers, and 58736420Ssklower * puts the packets on the device. 58836420Ssklower * When they are acked they are removed from the socket buf. 58936420Ssklower * 59036420Ssklower * sosend calls this up until sbspace goes negative. 59136420Ssklower * Sbspace may be made negative by appending this mbuf chain, 59236420Ssklower * possibly by a whole cluster. 59336420Ssklower */ 59436420Ssklower { 59537469Ssklower register struct mbuf *n = m; 59636420Ssklower register struct sockbuf *sb = &so->so_snd; 59737469Ssklower int maxsize = tpcb->tp_l_tpdusize 59837469Ssklower - tp_headersize(DT_TPDU_type, tpcb) 59937469Ssklower - (tpcb->tp_use_checksum?4:0) ; 60037469Ssklower int totlen = n->m_pkthdr.len; 60139937Ssklower int mbufcnt = 0; 60239196Ssklower struct mbuf *nn; 60336420Ssklower 60437469Ssklower /* 60537469Ssklower * Could have eotsdu and no data.(presently MUST have 60637469Ssklower * an mbuf though, even if its length == 0) 60737469Ssklower */ 60838841Ssklower if (n->m_flags & M_EOR) { 60937469Ssklower eotsdu = 1; 61038841Ssklower n->m_flags &= ~M_EOR; 61138841Ssklower } 61236420Ssklower IFPERF(tpcb) 61337469Ssklower PStat(tpcb, Nb_from_sess) += totlen; 61436420Ssklower tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0, 61537469Ssklower PStat(tpcb, Nb_from_sess), totlen); 61636420Ssklower ENDPERF 61736420Ssklower IFDEBUG(D_SYSCALL) 61836420Ssklower printf( 61936420Ssklower "PRU_SEND: eot %d before sbappend 0x%x len 0x%x to sb @ 0x%x\n", 62039937Ssklower eotsdu, m, totlen, sb); 62136420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 62236420Ssklower dump_mbuf(m, "m : to be added"); 62336420Ssklower ENDDEBUG 62437469Ssklower /* 62537469Ssklower * Pre-packetize the data in the sockbuf 62637469Ssklower * according to negotiated mtu. Do it here 62737469Ssklower * where we can safely wait for mbufs. 62839196Ssklower * 62939196Ssklower * This presumes knowledge of sockbuf conventions. 63036420Ssklower */ 63139196Ssklower if (n = sb->sb_mb) 63239196Ssklower while (n->m_act) 63339196Ssklower n = n->m_act; 63439647Ssklower if ((nn = n) && n->m_pkthdr.len < maxsize) { 63539937Ssklower u_int space = maxsize - n->m_pkthdr.len; 63639647Ssklower 63739647Ssklower do { 63839647Ssklower if (n->m_flags & M_EOR) 63939647Ssklower goto on1; 64039647Ssklower } while (n->m_next && (n = n->m_next)); 64139937Ssklower if (totlen <= space) { 64239937Ssklower TPNagle1++; 64339196Ssklower n->m_next = m; 64439937Ssklower nn->m_pkthdr.len += totlen; 64539937Ssklower while (n = n->m_next) 64639937Ssklower sballoc(sb, n); 64739196Ssklower if (eotsdu) 64839196Ssklower nn->m_flags |= M_EOR; 64939196Ssklower goto on2; 65039937Ssklower } else { 65139937Ssklower /* 65239937Ssklower * Can't sleep here, because when you wake up 65339937Ssklower * packet you want to attach to may be gone! 65439937Ssklower */ 65539937Ssklower if (TNew && (n->m_next = m_copym(m, 0, space, M_NOWAIT))) { 65639937Ssklower nn->m_pkthdr.len += space; 65739937Ssklower TPNagle2++; 65839937Ssklower while (n = n->m_next) 65939937Ssklower sballoc(sb, n); 66039937Ssklower m_adj(m, space); 66139937Ssklower } 66239196Ssklower } 66339196Ssklower } 66439937Ssklower on1: mbufcnt++; 66539196Ssklower for (n = m; n->m_pkthdr.len > maxsize;) { 66639937Ssklower nn = m_copym(n, 0, maxsize, M_WAIT); 66737469Ssklower sbappendrecord(sb, nn); 66837469Ssklower m_adj(n, maxsize); 66939937Ssklower mbufcnt++; 67037469Ssklower } 67139196Ssklower if (eotsdu) 67239196Ssklower n->m_flags |= M_EOR; 67337469Ssklower sbappendrecord(sb, n); 67439196Ssklower on2: 67539196Ssklower IFTRACE(D_DATA) 67639196Ssklower tptraceTPCB(TPPTmisc, 67739937Ssklower "SEND BF: maxsize totlen mbufcnt eotsdu", 67839937Ssklower maxsize, totlen, mbufcnt, eotsdu); 67939196Ssklower ENDTRACE 68036420Ssklower IFDEBUG(D_SYSCALL) 68139937Ssklower printf("PRU_SEND: eot %d after sbappend 0x%x mbufcnt 0x%x\n", 68239937Ssklower eotsdu, n, mbufcnt); 68336420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 68436420Ssklower ENDDEBUG 68536420Ssklower error = DoEvent(T_DATA_req); 68636420Ssklower IFDEBUG(D_SYSCALL) 68736420Ssklower printf("PRU_SEND: after driver error 0x%x \n",error); 68837469Ssklower printf("so_snd 0x%x cc 0t%d mbcnt 0t%d\n", 68937469Ssklower sb, sb->sb_cc, sb->sb_mbcnt); 69037469Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver"); 69136420Ssklower ENDDEBUG 69236420Ssklower } 69336420Ssklower break; 69436420Ssklower 69537469Ssklower case PRU_SOCKADDR: 69637469Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_LOCAL); 69736420Ssklower break; 69836420Ssklower 69936420Ssklower case PRU_PEERADDR: 70038841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 70136420Ssklower break; 70236420Ssklower 70336420Ssklower case PRU_CONTROL: 70436420Ssklower error = EOPNOTSUPP; 70536420Ssklower break; 70636420Ssklower 70736420Ssklower case PRU_PROTOSEND: 70836420Ssklower case PRU_PROTORCV: 70936420Ssklower case PRU_SENSE: 71036420Ssklower case PRU_SLOWTIMO: 71136420Ssklower case PRU_FASTTIMO: 71236420Ssklower error = EOPNOTSUPP; 71336420Ssklower break; 71436420Ssklower 71536420Ssklower default: 71636420Ssklower #ifdef ARGO_DEBUG 71736420Ssklower printf("tp_usrreq UNKNOWN PRU %d\n", req); 71836420Ssklower #endif ARGO_DEBUG 71936420Ssklower error = EOPNOTSUPP; 72036420Ssklower } 72136420Ssklower 72236420Ssklower IFDEBUG(D_REQUEST) 72338841Ssklower printf("%s, so 0x%x, tpcb 0x%x, error %d, state %d\n", 72438841Ssklower "returning from tp_usrreq", so, tpcb, error, 72538841Ssklower tpcb ? 0 : tpcb->tp_state); 72636420Ssklower ENDDEBUG 72736420Ssklower IFTRACE(D_REQUEST) 72836420Ssklower tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m, 72936420Ssklower tpcb?0:tpcb->tp_state); 73036420Ssklower ENDTRACE 73136420Ssklower splx(s); 73236420Ssklower return error; 73336420Ssklower } 73439196Ssklower tp_ltrace(so, uio) 73539196Ssklower struct socket *so; 73639196Ssklower struct uio *uio; 73739196Ssklower { 73839196Ssklower IFTRACE(D_DATA) 73939196Ssklower register struct tp_pcb *tpcb = sototpcb(so); 74039196Ssklower if (tpcb) { 74139196Ssklower tptraceTPCB(TPPTmisc, "sosend so resid iovcnt", so, 74239196Ssklower uio->uio_resid, uio->uio_iovcnt, 0); 74339196Ssklower } 74439196Ssklower ENDTRACE 74539196Ssklower } 74637469Ssklower 74738841Ssklower tp_confirm(tpcb) 74838841Ssklower register struct tp_pcb *tpcb; 74937469Ssklower { 75038841Ssklower struct tp_event E; 75138841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 75238841Ssklower return DoEvent(T_ACPT_req); 75338841Ssklower printf("Tp confirm called when not confirming; tpcb 0x%x, state 0x%x\n", 75438841Ssklower tpcb, tpcb->tp_state); 75538841Ssklower return 0; 75637469Ssklower } 75737469Ssklower 75837469Ssklower /* 75937469Ssklower * Process control data sent with sendmsg() 76037469Ssklower */ 76137469Ssklower tp_snd_control(m0, so, data) 76237469Ssklower register struct mbuf *m0; 76337469Ssklower struct socket *so; 76437469Ssklower register struct mbuf **data; 76537469Ssklower { 76637469Ssklower register struct tp_control_hdr *ch; 76737469Ssklower struct mbuf *m; 76837469Ssklower int error = 0; 76937469Ssklower 77037469Ssklower if (m0 && m0->m_len) { 77137469Ssklower ch = mtod(m0, struct tp_control_hdr *); 77237469Ssklower m0->m_len -= sizeof (*ch); 77337469Ssklower m0->m_data += sizeof (*ch); 77437469Ssklower m = m_copym(m0, 0, M_COPYALL, M_WAIT); 77537469Ssklower error = tp_ctloutput(PRCO_SETOPT, 77637469Ssklower so, ch->cmsg_level, ch->cmsg_type, &m); 77737469Ssklower if (m) 77837469Ssklower m_freem(m); 77937469Ssklower if (ch->cmsg_type == TPOPT_DISC_DATA) { 78037469Ssklower if (data && *data) { 78137469Ssklower m_freem(*data); 78237469Ssklower *data = 0; 78337469Ssklower } 78437469Ssklower m0 = 0; 785*40773Ssklower error = tp_usrreq(so, PRU_DISCONNECT, m0, (caddr_t)0, m0); 78637469Ssklower } 78737469Ssklower } 78837469Ssklower return error; 78937469Ssklower } 790