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*42468Ssklower * @(#)tp_usrreq.c 7.10 (Berkeley) 05/30/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 34640773Ssklower tp_usrreq(so, req, m, nam, controlp) 34736420Ssklower struct socket *so; 34836420Ssklower u_int req; 34940773Ssklower 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: 56041924Ssklower if (controlp) { 56141924Ssklower error = tp_snd_control(controlp, so, &m); 56241924Ssklower controlp = NULL; 56341924Ssklower if (error) 56441924Ssklower break; 56541924Ssklower } 56638841Ssklower if (so->so_state & SS_ISCONFIRMING) { 56738841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 56838841Ssklower error = tp_confirm(tpcb); 56938841Ssklower if (m) { 57038841Ssklower if (error == 0 && m->m_len != 0) 57138841Ssklower error = ENOTCONN; 57238841Ssklower m_freem(m); 57338841Ssklower m = 0; 57438841Ssklower } 57538841Ssklower break; 57638841Ssklower } 57737469Ssklower if (m == 0) 57837469Ssklower break; 57938841Ssklower 58038841Ssklower if (req == PRU_SENDOOB) { 58138841Ssklower if (tpcb->tp_xpd_service == 0) { 58238841Ssklower error = EOPNOTSUPP; 58338841Ssklower break; 58438841Ssklower } 58538841Ssklower error = tp_sendoob(tpcb, so, m, outflags); 58636420Ssklower break; 58736420Ssklower } 58836420Ssklower /* 58936420Ssklower * The protocol machine copies mbuf chains, 59036420Ssklower * prepends headers, assigns seq numbers, and 59136420Ssklower * puts the packets on the device. 59236420Ssklower * When they are acked they are removed from the socket buf. 59336420Ssklower * 59436420Ssklower * sosend calls this up until sbspace goes negative. 59536420Ssklower * Sbspace may be made negative by appending this mbuf chain, 59636420Ssklower * possibly by a whole cluster. 59736420Ssklower */ 59836420Ssklower { 59937469Ssklower register struct mbuf *n = m; 60036420Ssklower register struct sockbuf *sb = &so->so_snd; 60137469Ssklower int maxsize = tpcb->tp_l_tpdusize 60237469Ssklower - tp_headersize(DT_TPDU_type, tpcb) 60337469Ssklower - (tpcb->tp_use_checksum?4:0) ; 60437469Ssklower int totlen = n->m_pkthdr.len; 60539937Ssklower int mbufcnt = 0; 60639196Ssklower struct mbuf *nn; 60736420Ssklower 60837469Ssklower /* 60937469Ssklower * Could have eotsdu and no data.(presently MUST have 61037469Ssklower * an mbuf though, even if its length == 0) 61137469Ssklower */ 61238841Ssklower if (n->m_flags & M_EOR) { 61337469Ssklower eotsdu = 1; 61438841Ssklower n->m_flags &= ~M_EOR; 61538841Ssklower } 61636420Ssklower IFPERF(tpcb) 61737469Ssklower PStat(tpcb, Nb_from_sess) += totlen; 61836420Ssklower tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0, 61937469Ssklower PStat(tpcb, Nb_from_sess), totlen); 62036420Ssklower ENDPERF 62136420Ssklower IFDEBUG(D_SYSCALL) 62236420Ssklower printf( 62336420Ssklower "PRU_SEND: eot %d before sbappend 0x%x len 0x%x to sb @ 0x%x\n", 62439937Ssklower eotsdu, m, totlen, sb); 62536420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 62636420Ssklower dump_mbuf(m, "m : to be added"); 62736420Ssklower ENDDEBUG 62837469Ssklower /* 62937469Ssklower * Pre-packetize the data in the sockbuf 63037469Ssklower * according to negotiated mtu. Do it here 63137469Ssklower * where we can safely wait for mbufs. 63239196Ssklower * 63339196Ssklower * This presumes knowledge of sockbuf conventions. 63436420Ssklower */ 63539196Ssklower if (n = sb->sb_mb) 63639196Ssklower while (n->m_act) 63739196Ssklower n = n->m_act; 63839647Ssklower if ((nn = n) && n->m_pkthdr.len < maxsize) { 63939937Ssklower u_int space = maxsize - n->m_pkthdr.len; 64039647Ssklower 64139647Ssklower do { 64239647Ssklower if (n->m_flags & M_EOR) 64339647Ssklower goto on1; 64439647Ssklower } while (n->m_next && (n = n->m_next)); 64539937Ssklower if (totlen <= space) { 64639937Ssklower TPNagle1++; 64739196Ssklower n->m_next = m; 64839937Ssklower nn->m_pkthdr.len += totlen; 64939937Ssklower while (n = n->m_next) 65039937Ssklower sballoc(sb, n); 65139196Ssklower if (eotsdu) 65239196Ssklower nn->m_flags |= M_EOR; 65339196Ssklower goto on2; 65439937Ssklower } else { 65539937Ssklower /* 65639937Ssklower * Can't sleep here, because when you wake up 65739937Ssklower * packet you want to attach to may be gone! 65839937Ssklower */ 65939937Ssklower if (TNew && (n->m_next = m_copym(m, 0, space, M_NOWAIT))) { 66039937Ssklower nn->m_pkthdr.len += space; 66139937Ssklower TPNagle2++; 66239937Ssklower while (n = n->m_next) 66339937Ssklower sballoc(sb, n); 66439937Ssklower m_adj(m, space); 66539937Ssklower } 66639196Ssklower } 66739196Ssklower } 66839937Ssklower on1: mbufcnt++; 66939196Ssklower for (n = m; n->m_pkthdr.len > maxsize;) { 67039937Ssklower nn = m_copym(n, 0, maxsize, M_WAIT); 67137469Ssklower sbappendrecord(sb, nn); 67237469Ssklower m_adj(n, maxsize); 67339937Ssklower mbufcnt++; 67437469Ssklower } 67539196Ssklower if (eotsdu) 67639196Ssklower n->m_flags |= M_EOR; 67737469Ssklower sbappendrecord(sb, n); 67839196Ssklower on2: 67939196Ssklower IFTRACE(D_DATA) 68039196Ssklower tptraceTPCB(TPPTmisc, 68139937Ssklower "SEND BF: maxsize totlen mbufcnt eotsdu", 68239937Ssklower maxsize, totlen, mbufcnt, eotsdu); 68339196Ssklower ENDTRACE 68436420Ssklower IFDEBUG(D_SYSCALL) 68539937Ssklower printf("PRU_SEND: eot %d after sbappend 0x%x mbufcnt 0x%x\n", 68639937Ssklower eotsdu, n, mbufcnt); 68736420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 68836420Ssklower ENDDEBUG 68936420Ssklower error = DoEvent(T_DATA_req); 69036420Ssklower IFDEBUG(D_SYSCALL) 69136420Ssklower printf("PRU_SEND: after driver error 0x%x \n",error); 69237469Ssklower printf("so_snd 0x%x cc 0t%d mbcnt 0t%d\n", 69337469Ssklower sb, sb->sb_cc, sb->sb_mbcnt); 69437469Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver"); 69536420Ssklower ENDDEBUG 69636420Ssklower } 69736420Ssklower break; 69836420Ssklower 69937469Ssklower case PRU_SOCKADDR: 70037469Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_LOCAL); 70136420Ssklower break; 70236420Ssklower 70336420Ssklower case PRU_PEERADDR: 70438841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 70536420Ssklower break; 70636420Ssklower 70736420Ssklower case PRU_CONTROL: 70836420Ssklower error = EOPNOTSUPP; 70936420Ssklower break; 71036420Ssklower 71136420Ssklower case PRU_PROTOSEND: 71236420Ssklower case PRU_PROTORCV: 71336420Ssklower case PRU_SENSE: 71436420Ssklower case PRU_SLOWTIMO: 71536420Ssklower case PRU_FASTTIMO: 71636420Ssklower error = EOPNOTSUPP; 71736420Ssklower break; 71836420Ssklower 71936420Ssklower default: 72036420Ssklower #ifdef ARGO_DEBUG 72136420Ssklower printf("tp_usrreq UNKNOWN PRU %d\n", req); 72236420Ssklower #endif ARGO_DEBUG 72336420Ssklower error = EOPNOTSUPP; 72436420Ssklower } 72536420Ssklower 72636420Ssklower IFDEBUG(D_REQUEST) 72738841Ssklower printf("%s, so 0x%x, tpcb 0x%x, error %d, state %d\n", 72838841Ssklower "returning from tp_usrreq", so, tpcb, error, 72938841Ssklower tpcb ? 0 : tpcb->tp_state); 73036420Ssklower ENDDEBUG 73136420Ssklower IFTRACE(D_REQUEST) 73236420Ssklower tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m, 73336420Ssklower tpcb?0:tpcb->tp_state); 73436420Ssklower ENDTRACE 73541924Ssklower if (controlp) { 73641924Ssklower m_freem(controlp); 73741924Ssklower printf("control data unexpectedly retained in tp_usrreq()"); 73841924Ssklower } 73936420Ssklower splx(s); 74036420Ssklower return error; 74136420Ssklower } 74239196Ssklower tp_ltrace(so, uio) 74339196Ssklower struct socket *so; 74439196Ssklower struct uio *uio; 74539196Ssklower { 74639196Ssklower IFTRACE(D_DATA) 74739196Ssklower register struct tp_pcb *tpcb = sototpcb(so); 74839196Ssklower if (tpcb) { 74939196Ssklower tptraceTPCB(TPPTmisc, "sosend so resid iovcnt", so, 75039196Ssklower uio->uio_resid, uio->uio_iovcnt, 0); 75139196Ssklower } 75239196Ssklower ENDTRACE 75339196Ssklower } 75437469Ssklower 75538841Ssklower tp_confirm(tpcb) 75638841Ssklower register struct tp_pcb *tpcb; 75737469Ssklower { 75838841Ssklower struct tp_event E; 75938841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 76038841Ssklower return DoEvent(T_ACPT_req); 76138841Ssklower printf("Tp confirm called when not confirming; tpcb 0x%x, state 0x%x\n", 76238841Ssklower tpcb, tpcb->tp_state); 76338841Ssklower return 0; 76437469Ssklower } 76537469Ssklower 76637469Ssklower /* 76737469Ssklower * Process control data sent with sendmsg() 76837469Ssklower */ 76941924Ssklower tp_snd_control(m, so, data) 77041924Ssklower struct mbuf *m; 77137469Ssklower struct socket *so; 77237469Ssklower register struct mbuf **data; 77337469Ssklower { 774*42468Ssklower register struct cmsghdr *ch; 77537469Ssklower int error = 0; 77637469Ssklower 77741924Ssklower if (m && m->m_len) { 778*42468Ssklower ch = mtod(m, struct cmsghdr *); 77941924Ssklower m->m_len -= sizeof (*ch); 78041924Ssklower m->m_data += sizeof (*ch); 78137469Ssklower error = tp_ctloutput(PRCO_SETOPT, 78237469Ssklower so, ch->cmsg_level, ch->cmsg_type, &m); 78337469Ssklower if (ch->cmsg_type == TPOPT_DISC_DATA) { 78437469Ssklower if (data && *data) { 78537469Ssklower m_freem(*data); 78637469Ssklower *data = 0; 78737469Ssklower } 78841924Ssklower error = tp_usrreq(so, PRU_DISCONNECT, (struct mbuf *)0, 78941924Ssklower (caddr_t)0, (struct mbuf *)0); 79037469Ssklower } 79137469Ssklower } 79241924Ssklower if (m) 79341924Ssklower m_freem(m); 79437469Ssklower return error; 79537469Ssklower } 796