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*44601Ssklower * @(#)tp_usrreq.c 7.13 (Berkeley) 06/29/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; 7044424Ssklower struct tp_pcb *tp_listeners, *tp_intercepts; 7136420Ssklower 7236420Ssklower #ifdef ARGO_DEBUG 7336420Ssklower /* 7436420Ssklower * CALLED FROM: 7536420Ssklower * anywhere you want to debug... 7636420Ssklower * FUNCTION and ARGUMENTS: 7736420Ssklower * print (str) followed by the control info in the mbufs of an mbuf chain (n) 7836420Ssklower */ 7936420Ssklower void 8036420Ssklower dump_mbuf(n, str) 8136420Ssklower struct mbuf *n; 8236420Ssklower char *str; 8336420Ssklower { 8436420Ssklower struct mbuf *nextrecord; 8536420Ssklower 8636420Ssklower printf("dump %s\n", str); 8736420Ssklower 8844310Ssklower if (n == MNULL) { 8936420Ssklower printf("EMPTY:\n"); 9036420Ssklower return; 9136420Ssklower } 9236420Ssklower 9344310Ssklower while (n) { 9436420Ssklower nextrecord = n->m_act; 9536420Ssklower printf("RECORD:\n"); 9636420Ssklower while (n) { 9737469Ssklower printf("%x : Len %x Data %x A %x Nx %x Tp %x\n", 9837469Ssklower n, n->m_len, n->m_data, n->m_act, n->m_next, n->m_type); 9936420Ssklower #ifdef notdef 10036420Ssklower { 10136420Ssklower register char *p = mtod(n, char *); 10236420Ssklower register int i; 10336420Ssklower 10436420Ssklower printf("data: "); 10544310Ssklower for (i = 0; i < n->m_len; i++) { 10644310Ssklower if (i%8 == 0) 10736420Ssklower printf("\n"); 10836420Ssklower printf("0x%x ", *(p+i)); 10936420Ssklower } 11036420Ssklower printf("\n"); 11136420Ssklower } 11236420Ssklower #endif notdef 11344310Ssklower if (n->m_next == n) { 11436420Ssklower printf("LOOP!\n"); 11536420Ssklower return; 11636420Ssklower } 11736420Ssklower n = n->m_next; 11836420Ssklower } 11936420Ssklower n = nextrecord; 12036420Ssklower } 12136420Ssklower printf("\n"); 12236420Ssklower } 12336420Ssklower 12436420Ssklower #endif ARGO_DEBUG 12536420Ssklower 12636420Ssklower /* 12736420Ssklower * CALLED FROM: 12836420Ssklower * tp_usrreq(), PRU_RCVOOB 12936420Ssklower * FUNCTION and ARGUMENTS: 13036420Ssklower * Copy data from the expedited data socket buffer into 13136420Ssklower * the pre-allocated mbuf m. 13236420Ssklower * There is an isomorphism between XPD TPDUs and expedited data TSDUs. 13336420Ssklower * XPD tpdus are limited to 16 bytes of data so they fit in one mbuf. 13436420Ssklower * RETURN VALUE: 13536420Ssklower * EINVAL if debugging is on and a disaster has occurred 13636420Ssklower * ENOTCONN if the socket isn't connected 13736420Ssklower * EWOULDBLOCK if the socket is in non-blocking mode and there's no 13836420Ssklower * xpd data in the buffer 13936420Ssklower * E* whatever is returned from the fsm. 14036420Ssklower */ 14136420Ssklower tp_rcvoob(tpcb, so, m, outflags, inflags) 14236420Ssklower struct tp_pcb *tpcb; 14336420Ssklower register struct socket *so; 14436420Ssklower register struct mbuf *m; 14536420Ssklower int *outflags; 14636420Ssklower int inflags; 14736420Ssklower { 14836420Ssklower register struct mbuf *n; 14937469Ssklower register struct sockbuf *sb = &so->so_rcv; 15036420Ssklower struct tp_event E; 15136420Ssklower int error = 0; 15237469Ssklower register struct mbuf **nn; 15336420Ssklower 15436420Ssklower IFDEBUG(D_XPD) 15536420Ssklower printf("PRU_RCVOOB, sostate 0x%x\n", so->so_state); 15636420Ssklower ENDDEBUG 15736420Ssklower 15836420Ssklower /* if you use soreceive */ 15944310Ssklower if (m == MNULL) 16036420Ssklower return ENOBUFS; 16136420Ssklower 16236420Ssklower restart: 16336420Ssklower if ((((so->so_state & SS_ISCONNECTED) == 0) 16436420Ssklower || (so->so_state & SS_ISDISCONNECTING) != 0) && 16536420Ssklower (so->so_proto->pr_flags & PR_CONNREQUIRED)) { 16636420Ssklower return ENOTCONN; 16736420Ssklower } 16836420Ssklower 16937469Ssklower /* Take the first mbuf off the chain. 17037469Ssklower * Each XPD TPDU gives you a complete TSDU so the chains don't get 17137469Ssklower * coalesced, but one TSDU may span several mbufs. 17237469Ssklower * Nevertheless, since n should have a most 16 bytes, it 17337469Ssklower * will fit into m. (size was checked in tp_input() ) 17437469Ssklower */ 17537469Ssklower 17637469Ssklower /* 17737469Ssklower * Code for excision of OOB data should be added to 17837469Ssklower * uipc_socket2.c (like sbappend). 17937469Ssklower */ 18037469Ssklower 18138841Ssklower sblock(sb); 18237469Ssklower for (nn = &sb->sb_mb; n = *nn; nn = &n->m_act) 18337469Ssklower if (n->m_type == MT_OOBDATA) 18437469Ssklower break; 18537469Ssklower 18637469Ssklower if (n == 0) { 18744310Ssklower ASSERT((tpcb->tp_flags & TPF_DISC_DATA_IN) == 0); 18836420Ssklower IFDEBUG(D_XPD) 18936420Ssklower printf("RCVOOB: empty queue!\n"); 19036420Ssklower ENDDEBUG 19138841Ssklower sbunlock(sb); 19236420Ssklower if (so->so_state & SS_NBIO) { 19336420Ssklower return EWOULDBLOCK; 19436420Ssklower } 19536420Ssklower sbwait(sb); 19636420Ssklower goto restart; 19736420Ssklower } 19836420Ssklower m->m_len = 0; 19936420Ssklower 20036420Ssklower /* Assuming at most one xpd tpdu is in the buffer at once */ 20144310Ssklower while (n != MNULL) { 20236420Ssklower m->m_len += n->m_len; 20337469Ssklower bcopy(mtod(n, caddr_t), mtod(m, caddr_t), (unsigned)n->m_len); 20437469Ssklower m->m_data += n->m_len; /* so mtod() in bcopy() above gives right addr */ 20536420Ssklower n = n->m_next; 20636420Ssklower } 20737469Ssklower m->m_data = m->m_dat; 20837469Ssklower m->m_flags |= M_EOR; 20936420Ssklower 21036420Ssklower IFDEBUG(D_XPD) 21136420Ssklower printf("tp_rcvoob: xpdlen 0x%x\n", m->m_len); 21236420Ssklower dump_mbuf(so->so_rcv.sb_mb, "RCVOOB: Rcv socketbuf"); 21336420Ssklower dump_mbuf(sb->sb_mb, "RCVOOB: Xrcv socketbuf"); 21436420Ssklower ENDDEBUG 21536420Ssklower 21644310Ssklower if ((inflags & MSG_PEEK) == 0) { 21737469Ssklower n = *nn; 21837469Ssklower *nn = n->m_act; 21937469Ssklower sb->sb_cc -= m->m_len; 22037469Ssklower } 22136420Ssklower 22236420Ssklower release: 22336420Ssklower sbunlock(sb); 22436420Ssklower 22536420Ssklower IFTRACE(D_XPD) 22636420Ssklower tptraceTPCB(TPPTmisc, "PRU_RCVOOB @ release sb_cc m_len", 22744310Ssklower tpcb->tp_Xrcv.sb_cc, m->m_len, 0, 0); 22836420Ssklower ENDTRACE 22936420Ssklower if (error == 0) 23036420Ssklower error = DoEvent(T_USR_Xrcvd); 23136420Ssklower return error; 23236420Ssklower } 23336420Ssklower 23436420Ssklower /* 23536420Ssklower * CALLED FROM: 23636420Ssklower * tp_usrreq(), PRU_SENDOOB 23736420Ssklower * FUNCTION and ARGUMENTS: 23836420Ssklower * Send what's in the mbuf chain (m) as an XPD TPDU. 23936420Ssklower * The mbuf may not contain more then 16 bytes of data. 24036420Ssklower * XPD TSDUs aren't segmented, so they translate into 24136420Ssklower * exactly one XPD TPDU, with EOT bit set. 24236420Ssklower * RETURN VALUE: 24336420Ssklower * EWOULDBLOCK if socket is in non-blocking mode and the previous 24436420Ssklower * xpd data haven't been acked yet. 24536420Ssklower * EMSGSIZE if trying to send > max-xpd bytes (16) 24636420Ssklower * ENOBUFS if ran out of mbufs 24736420Ssklower */ 24836420Ssklower tp_sendoob(tpcb, so, xdata, outflags) 24936420Ssklower struct tp_pcb *tpcb; 25036420Ssklower register struct socket *so; 25136420Ssklower register struct mbuf *xdata; 25236420Ssklower int *outflags; /* not used */ 25336420Ssklower { 25436420Ssklower /* 25536420Ssklower * Each mbuf chain represents a sequence # in the XPD seq space. 25636420Ssklower * The first one in the queue has sequence # tp_Xuna. 25736420Ssklower * When we add to the XPD queue, we stuff a zero-length 25836420Ssklower * mbuf (mark) into the DATA queue, with its sequence number in m_next 25936420Ssklower * to be assigned to this XPD tpdu, so data xfer can stop 26036420Ssklower * when it reaches the zero-length mbuf if this XPD TPDU hasn't 26136420Ssklower * yet been acknowledged. 26236420Ssklower */ 26336420Ssklower register struct sockbuf *sb = &(tpcb->tp_Xsnd); 26436420Ssklower register struct mbuf *xmark; 26536420Ssklower register int len=0; 26636420Ssklower struct tp_event E; 26736420Ssklower 26836420Ssklower IFDEBUG(D_XPD) 26936420Ssklower printf("tp_sendoob:"); 27044310Ssklower if (xdata) 27136420Ssklower printf("xdata len 0x%x\n", xdata->m_len); 27236420Ssklower ENDDEBUG 27336420Ssklower /* DO NOT LOCK the Xsnd buffer!!!! You can have at MOST one 27436420Ssklower * socket buf locked at any time!!! (otherwise you might 27536420Ssklower * sleep() in sblock() w/ a signal pending and cause the 27636420Ssklower * system call to be aborted w/ a locked socketbuf, which 27736420Ssklower * is a problem. So the so_snd buffer lock 27836420Ssklower * (done in sosend()) serves as the lock for Xpd. 27936420Ssklower */ 28038841Ssklower if (sb->sb_mb) { /* Anything already in eXpedited data sockbuf? */ 28136420Ssklower if (so->so_state & SS_NBIO) { 28236420Ssklower return EWOULDBLOCK; 28336420Ssklower } 28438841Ssklower while (sb->sb_mb) { 28538841Ssklower sbunlock(&so->so_snd); /* already locked by sosend */ 28638841Ssklower sbwait(&so->so_snd); 28738841Ssklower sblock(&so->so_snd); /* sosend will unlock on return */ 28838841Ssklower } 28936420Ssklower } 29036420Ssklower 29136420Ssklower if (xdata == (struct mbuf *)0) { 29236420Ssklower /* empty xpd packet */ 29337469Ssklower MGETHDR(xdata, M_WAIT, MT_OOBDATA); 29436420Ssklower if (xdata == NULL) { 29536420Ssklower return ENOBUFS; 29636420Ssklower } 29736420Ssklower xdata->m_len = 0; 29837469Ssklower xdata->m_pkthdr.len = 0; 29936420Ssklower } 30036420Ssklower IFDEBUG(D_XPD) 30136420Ssklower printf("tp_sendoob 1:"); 30244310Ssklower if (xdata) 30336420Ssklower printf("xdata len 0x%x\n", xdata->m_len); 30436420Ssklower ENDDEBUG 30536420Ssklower xmark = xdata; /* temporary use of variable xmark */ 30636420Ssklower while (xmark) { 30736420Ssklower len += xmark->m_len; 30836420Ssklower xmark = xmark->m_next; 30936420Ssklower } 31036420Ssklower if (len > TP_MAX_XPD_DATA) { 31136420Ssklower return EMSGSIZE; 31236420Ssklower } 31336420Ssklower IFDEBUG(D_XPD) 31436420Ssklower printf("tp_sendoob 2:"); 31544310Ssklower if (xdata) 31636420Ssklower printf("xdata len 0x%x\n", len); 31736420Ssklower ENDDEBUG 31836420Ssklower 31936420Ssklower 32036420Ssklower IFTRACE(D_XPD) 32138841Ssklower tptraceTPCB(TPPTmisc, "XPD mark m_next ", xdata->m_next, 0, 0, 0); 32236420Ssklower ENDTRACE 32336420Ssklower 32436420Ssklower sbappendrecord(sb, xdata); 32536420Ssklower 32636420Ssklower IFDEBUG(D_XPD) 32736420Ssklower printf("tp_sendoob len 0x%x\n", len); 32836420Ssklower dump_mbuf(so->so_snd.sb_mb, "XPD request Regular sndbuf:"); 32936420Ssklower dump_mbuf(tpcb->tp_Xsnd.sb_mb, "XPD request Xsndbuf:"); 33036420Ssklower ENDDEBUG 33136420Ssklower return DoEvent(T_XPD_req); 33236420Ssklower } 33336420Ssklower 33436420Ssklower /* 33536420Ssklower * CALLED FROM: 33636420Ssklower * the socket routines 33736420Ssklower * FUNCTION and ARGUMENTS: 33836420Ssklower * Handles all "user requests" except the [gs]ockopts() requests. 33936420Ssklower * The argument (req) is the request type (PRU*), 34036420Ssklower * (m) is an mbuf chain, generally used for send and 34136420Ssklower * receive type requests only. 34236420Ssklower * (nam) is used for addresses usually, in particular for the bind request. 34336420Ssklower * 34436420Ssklower */ 34536420Ssklower /*ARGSUSED*/ 34636420Ssklower ProtoHook 34740773Ssklower tp_usrreq(so, req, m, nam, controlp) 34836420Ssklower struct socket *so; 34936420Ssklower u_int req; 35040773Ssklower struct mbuf *m, *nam, *controlp; 35136420Ssklower { 35236420Ssklower register struct tp_pcb *tpcb = sototpcb(so); 35336420Ssklower int s = splnet(); 35436420Ssklower int error = 0; 35537469Ssklower int flags, *outflags = &flags; 35636420Ssklower u_long eotsdu = 0; 35736420Ssklower struct tp_event E; 35836420Ssklower 35936420Ssklower IFDEBUG(D_REQUEST) 36036420Ssklower printf("usrreq(0x%x,%d,0x%x,0x%x,0x%x)\n",so,req,m,nam,outflags); 36144310Ssklower if (so->so_error) 36236420Ssklower printf("WARNING!!! so->so_error is 0x%x\n", so->so_error); 36336420Ssklower ENDDEBUG 36436420Ssklower IFTRACE(D_REQUEST) 36536420Ssklower tptraceTPCB(TPPTusrreq, "req so m state [", req, so, m, 36636420Ssklower tpcb?tpcb->tp_state:0); 36736420Ssklower ENDTRACE 36836420Ssklower 36936420Ssklower if ((u_int)tpcb == 0 && req != PRU_ATTACH) { 37036420Ssklower IFTRACE(D_REQUEST) 37136420Ssklower tptraceTPCB(TPPTusrreq, "req failed NO TPCB[", 0, 0, 0, 0); 37236420Ssklower ENDTRACE 37336420Ssklower splx(s); 37436420Ssklower return ENOTCONN; 37536420Ssklower } 37636420Ssklower 37736420Ssklower switch (req) { 37836420Ssklower 37936420Ssklower case PRU_ATTACH: 38036420Ssklower if (tpcb) { 38136420Ssklower error = EISCONN; 38236420Ssklower break; 38336420Ssklower } 38444310Ssklower if (error = tp_attach(so, so->so_proto->pr_domain->dom_family)) 38536420Ssklower break; 38636420Ssklower tpcb = sototpcb(so); 38736420Ssklower break; 38836420Ssklower 38936420Ssklower case PRU_ABORT: /* called from close() */ 39036420Ssklower /* called for each incoming connect queued on the 39136420Ssklower * parent (accepting) socket 39236420Ssklower */ 39344310Ssklower if (tpcb->tp_state == TP_OPEN) { 39436420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NO_SESSION; 39536420Ssklower error = DoEvent(T_DISC_req); /* pretend it was a close() */ 39636420Ssklower break; 39736420Ssklower } /* else DROP THROUGH */ 39836420Ssklower 39936420Ssklower case PRU_DETACH: /* called from close() */ 40036420Ssklower /* called only after disconnect was called */ 40144424Ssklower if (tpcb->tp_state == TP_LISTENING) { 40244424Ssklower register struct tp_pcb **tt; 40344424Ssklower for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten)) 40444424Ssklower if (*tt == tpcb) 40544424Ssklower break; 40644424Ssklower if (*tt) 40744424Ssklower *tt = tpcb->tp_nextlisten; 40844424Ssklower else { 40944424Ssklower for (tt = &tp_intercepts; *tt; tt = &((*tt)->tp_nextlisten)) 41044424Ssklower if (*tt == tpcb) 41144424Ssklower break; 41244424Ssklower if (*tt) 41344424Ssklower *tt = tpcb->tp_nextlisten; 41444424Ssklower else 41544424Ssklower printf("tp_usrreq - detach: should panic\n"); 41644424Ssklower } 41744424Ssklower } 41844424Ssklower if (tpcb->tp_next) 41944424Ssklower remque(tpcb); 42036420Ssklower error = DoEvent(T_DETACH); 42137469Ssklower if (tpcb->tp_state == TP_CLOSED) { 42237469Ssklower free((caddr_t)tpcb, M_PCB); 42337469Ssklower tpcb = 0; 42437469Ssklower } 42536420Ssklower break; 42636420Ssklower 42736420Ssklower case PRU_SHUTDOWN: 42836420Ssklower /* recv end may have been released; local credit might be zero */ 42936420Ssklower case PRU_DISCONNECT: 43036420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NORMAL_DISC; 43136420Ssklower error = DoEvent(T_DISC_req); 43236420Ssklower break; 43336420Ssklower 43436420Ssklower case PRU_BIND: 43544310Ssklower error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, nam); 43636420Ssklower if (error == 0) { 43737469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 43844310Ssklower tpcb->tp_lsuffix, TP_LOCAL); 43936420Ssklower } 44036420Ssklower break; 44136420Ssklower 44236420Ssklower case PRU_LISTEN: 44344310Ssklower if (tpcb->tp_lsuffixlen == 0) { 44444310Ssklower if (error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL)) 44536420Ssklower break; 44637469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 44744310Ssklower tpcb->tp_lsuffix, TP_LOCAL); 44836420Ssklower } 44944424Ssklower if (tpcb->tp_next == 0) { 45044424Ssklower tpcb->tp_next = tpcb->tp_prev = tpcb; 45144424Ssklower tpcb->tp_nextlisten = tp_listeners; 452*44601Ssklower tp_listeners = tpcb; 45344424Ssklower } 45436420Ssklower IFDEBUG(D_TPISO) 45544310Ssklower if (tpcb->tp_state != TP_CLOSED) 45636420Ssklower printf("LISTEN ERROR: state 0x%x\n", tpcb->tp_state); 45736420Ssklower ENDDEBUG 45836420Ssklower error = DoEvent(T_LISTEN_req); 45936420Ssklower break; 46036420Ssklower 46136420Ssklower case PRU_CONNECT2: 46236420Ssklower error = EOPNOTSUPP; /* for unix domain sockets */ 46336420Ssklower break; 46436420Ssklower 46536420Ssklower case PRU_CONNECT: 46636420Ssklower IFTRACE(D_CONN) 46736420Ssklower tptraceTPCB(TPPTmisc, 46837469Ssklower "PRU_CONNECT: so 0x%x *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 46936420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 47036420Ssklower tpcb->tp_class); 47136420Ssklower ENDTRACE 47236420Ssklower IFDEBUG(D_CONN) 47336420Ssklower printf("PRU_CONNECT: so *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 47436420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 47536420Ssklower tpcb->tp_class); 47636420Ssklower ENDDEBUG 47744310Ssklower if (tpcb->tp_lsuffixlen == 0) { 47844310Ssklower if (error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL)) { 47936420Ssklower IFDEBUG(D_CONN) 48044310Ssklower printf("pcbbind returns error 0x%x\n", error); 48136420Ssklower ENDDEBUG 48236420Ssklower break; 48336420Ssklower } 48437469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 48544310Ssklower tpcb->tp_lsuffix, TP_LOCAL); 48637469Ssklower } 48736420Ssklower 48836420Ssklower IFDEBUG(D_CONN) 48936420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 49044310Ssklower dump_buf(tpcb->tp_npcb, 16); 49136420Ssklower ENDDEBUG 49244310Ssklower if (error = tp_route_to(nam, tpcb, /* channel */0)) 49336420Ssklower break; 49436420Ssklower IFDEBUG(D_CONN) 49536420Ssklower printf( 49636420Ssklower "PRU_CONNECT after tpcb 0x%x so 0x%x npcb 0x%x flags 0x%x\n", 49736420Ssklower tpcb, so, tpcb->tp_npcb, tpcb->tp_flags); 49836420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 49944310Ssklower dump_buf(tpcb->tp_npcb, 16); 50036420Ssklower ENDDEBUG 50144310Ssklower if (tpcb->tp_fsuffixlen == 0) { 50236420Ssklower /* didn't set peer extended suffix */ 50337469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_fsuffixlen, 50444310Ssklower tpcb->tp_fsuffix, TP_FOREIGN); 50536420Ssklower } 50636420Ssklower (void) (tpcb->tp_nlproto->nlp_mtu)(so, so->so_pcb, 50736420Ssklower &tpcb->tp_l_tpdusize, &tpcb->tp_tpdusize, 0); 50844310Ssklower if (tpcb->tp_state == TP_CLOSED) { 50936420Ssklower soisconnecting(so); 51036420Ssklower error = DoEvent(T_CONN_req); 51136420Ssklower } else { 51236420Ssklower (tpcb->tp_nlproto->nlp_pcbdisc)(so->so_pcb); 51336420Ssklower error = EISCONN; 51436420Ssklower } 51536420Ssklower IFPERF(tpcb) 51636420Ssklower u_int lsufx, fsufx; 51739196Ssklower lsufx = *(u_short *)(tpcb->tp_lsuffix); 51839196Ssklower fsufx = *(u_short *)(tpcb->tp_fsuffix); 51936420Ssklower 52044310Ssklower tpmeas(tpcb->tp_lref, 52144310Ssklower TPtime_open | (tpcb->tp_xtd_format << 4), 52236420Ssklower &time, lsufx, fsufx, tpcb->tp_fref); 52336420Ssklower ENDPERF 52436420Ssklower break; 52536420Ssklower 52636420Ssklower case PRU_ACCEPT: 52738841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 52836420Ssklower IFDEBUG(D_REQUEST) 52938841Ssklower printf("ACCEPT PEERADDDR:"); 53038841Ssklower dump_buf(mtod(nam, char *), nam->m_len); 53136420Ssklower ENDDEBUG 53236420Ssklower IFPERF(tpcb) 53336420Ssklower u_int lsufx, fsufx; 53439196Ssklower lsufx = *(u_short *)(tpcb->tp_lsuffix); 53539196Ssklower fsufx = *(u_short *)(tpcb->tp_fsuffix); 53636420Ssklower 53744310Ssklower tpmeas(tpcb->tp_lref, TPtime_open, 53836420Ssklower &time, lsufx, fsufx, tpcb->tp_fref); 53936420Ssklower ENDPERF 54036420Ssklower break; 54136420Ssklower 54236420Ssklower case PRU_RCVD: 54338841Ssklower if (so->so_state & SS_ISCONFIRMING) { 54438841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 54538841Ssklower error = tp_confirm(tpcb); 54638841Ssklower break; 54738841Ssklower } 54836420Ssklower IFTRACE(D_DATA) 54936420Ssklower tptraceTPCB(TPPTmisc, 55036420Ssklower "RCVD BF: lcredit sent_lcdt cc hiwat \n", 55136420Ssklower tpcb->tp_lcredit, tpcb->tp_sent_lcdt, 55236420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 55336420Ssklower LOCAL_CREDIT(tpcb); 55436420Ssklower tptraceTPCB(TPPTmisc, 55536420Ssklower "PRU_RCVD AF sbspace lcredit hiwat cc", 55636420Ssklower sbspace(&so->so_rcv), tpcb->tp_lcredit, 55736420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 55836420Ssklower ENDTRACE 55937469Ssklower IFDEBUG(D_REQUEST) 56037469Ssklower printf("RCVD: cc %d space %d hiwat %d\n", 56137469Ssklower so->so_rcv.sb_cc, sbspace(&so->so_rcv), 56237469Ssklower so->so_rcv.sb_hiwat); 56337469Ssklower ENDDEBUG 56437469Ssklower if (((int)nam) & MSG_OOB) 56537469Ssklower error = DoEvent(T_USR_Xrcvd); 56637469Ssklower else 56737469Ssklower error = DoEvent(T_USR_rcvd); 56836420Ssklower break; 56936420Ssklower 57036420Ssklower case PRU_RCVOOB: 57136420Ssklower if ((so->so_state & SS_ISCONNECTED) == 0) { 57236420Ssklower error = ENOTCONN; 57336420Ssklower break; 57436420Ssklower } 57544310Ssklower if (! tpcb->tp_xpd_service) { 57636420Ssklower error = EOPNOTSUPP; 57736420Ssklower break; 57836420Ssklower } 57936420Ssklower /* kludge - nam is really flags here */ 58036420Ssklower error = tp_rcvoob(tpcb, so, m, outflags, (int)nam); 58136420Ssklower break; 58236420Ssklower 58338841Ssklower case PRU_SEND: 58436420Ssklower case PRU_SENDOOB: 58541924Ssklower if (controlp) { 58641924Ssklower error = tp_snd_control(controlp, so, &m); 58741924Ssklower controlp = NULL; 58841924Ssklower if (error) 58941924Ssklower break; 59041924Ssklower } 59138841Ssklower if (so->so_state & SS_ISCONFIRMING) { 59238841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 59338841Ssklower error = tp_confirm(tpcb); 59438841Ssklower if (m) { 59538841Ssklower if (error == 0 && m->m_len != 0) 59638841Ssklower error = ENOTCONN; 59738841Ssklower m_freem(m); 59838841Ssklower m = 0; 59938841Ssklower } 60038841Ssklower break; 60138841Ssklower } 60237469Ssklower if (m == 0) 60337469Ssklower break; 60438841Ssklower 60538841Ssklower if (req == PRU_SENDOOB) { 60638841Ssklower if (tpcb->tp_xpd_service == 0) { 60738841Ssklower error = EOPNOTSUPP; 60838841Ssklower break; 60938841Ssklower } 61038841Ssklower error = tp_sendoob(tpcb, so, m, outflags); 61136420Ssklower break; 61236420Ssklower } 61336420Ssklower /* 61436420Ssklower * The protocol machine copies mbuf chains, 61536420Ssklower * prepends headers, assigns seq numbers, and 61636420Ssklower * puts the packets on the device. 61736420Ssklower * When they are acked they are removed from the socket buf. 61836420Ssklower * 61936420Ssklower * sosend calls this up until sbspace goes negative. 62036420Ssklower * Sbspace may be made negative by appending this mbuf chain, 62136420Ssklower * possibly by a whole cluster. 62236420Ssklower */ 62336420Ssklower { 62437469Ssklower register struct mbuf *n = m; 62536420Ssklower register struct sockbuf *sb = &so->so_snd; 62637469Ssklower int maxsize = tpcb->tp_l_tpdusize 62737469Ssklower - tp_headersize(DT_TPDU_type, tpcb) 62837469Ssklower - (tpcb->tp_use_checksum?4:0) ; 62937469Ssklower int totlen = n->m_pkthdr.len; 63039937Ssklower int mbufcnt = 0; 63139196Ssklower struct mbuf *nn; 63236420Ssklower 63337469Ssklower /* 63437469Ssklower * Could have eotsdu and no data.(presently MUST have 63537469Ssklower * an mbuf though, even if its length == 0) 63637469Ssklower */ 63738841Ssklower if (n->m_flags & M_EOR) { 63837469Ssklower eotsdu = 1; 63938841Ssklower n->m_flags &= ~M_EOR; 64038841Ssklower } 64136420Ssklower IFPERF(tpcb) 64237469Ssklower PStat(tpcb, Nb_from_sess) += totlen; 64336420Ssklower tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0, 64437469Ssklower PStat(tpcb, Nb_from_sess), totlen); 64536420Ssklower ENDPERF 64636420Ssklower IFDEBUG(D_SYSCALL) 64736420Ssklower printf( 64836420Ssklower "PRU_SEND: eot %d before sbappend 0x%x len 0x%x to sb @ 0x%x\n", 64939937Ssklower eotsdu, m, totlen, sb); 65036420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 65136420Ssklower dump_mbuf(m, "m : to be added"); 65236420Ssklower ENDDEBUG 65337469Ssklower /* 65437469Ssklower * Pre-packetize the data in the sockbuf 65537469Ssklower * according to negotiated mtu. Do it here 65637469Ssklower * where we can safely wait for mbufs. 65739196Ssklower * 65839196Ssklower * This presumes knowledge of sockbuf conventions. 65936420Ssklower */ 66039196Ssklower if (n = sb->sb_mb) 66139196Ssklower while (n->m_act) 66239196Ssklower n = n->m_act; 66339647Ssklower if ((nn = n) && n->m_pkthdr.len < maxsize) { 66439937Ssklower u_int space = maxsize - n->m_pkthdr.len; 66539647Ssklower 66639647Ssklower do { 66739647Ssklower if (n->m_flags & M_EOR) 66839647Ssklower goto on1; 66939647Ssklower } while (n->m_next && (n = n->m_next)); 67039937Ssklower if (totlen <= space) { 67139937Ssklower TPNagle1++; 67239196Ssklower n->m_next = m; 67339937Ssklower nn->m_pkthdr.len += totlen; 67439937Ssklower while (n = n->m_next) 67539937Ssklower sballoc(sb, n); 67639196Ssklower if (eotsdu) 67739196Ssklower nn->m_flags |= M_EOR; 67839196Ssklower goto on2; 67939937Ssklower } else { 68039937Ssklower /* 68139937Ssklower * Can't sleep here, because when you wake up 68239937Ssklower * packet you want to attach to may be gone! 68339937Ssklower */ 68439937Ssklower if (TNew && (n->m_next = m_copym(m, 0, space, M_NOWAIT))) { 68539937Ssklower nn->m_pkthdr.len += space; 68639937Ssklower TPNagle2++; 68739937Ssklower while (n = n->m_next) 68839937Ssklower sballoc(sb, n); 68939937Ssklower m_adj(m, space); 69039937Ssklower } 69139196Ssklower } 69239196Ssklower } 69339937Ssklower on1: mbufcnt++; 69439196Ssklower for (n = m; n->m_pkthdr.len > maxsize;) { 69539937Ssklower nn = m_copym(n, 0, maxsize, M_WAIT); 69637469Ssklower sbappendrecord(sb, nn); 69737469Ssklower m_adj(n, maxsize); 69839937Ssklower mbufcnt++; 69937469Ssklower } 70039196Ssklower if (eotsdu) 70139196Ssklower n->m_flags |= M_EOR; 70237469Ssklower sbappendrecord(sb, n); 70339196Ssklower on2: 70439196Ssklower IFTRACE(D_DATA) 70539196Ssklower tptraceTPCB(TPPTmisc, 70639937Ssklower "SEND BF: maxsize totlen mbufcnt eotsdu", 70739937Ssklower maxsize, totlen, mbufcnt, eotsdu); 70839196Ssklower ENDTRACE 70936420Ssklower IFDEBUG(D_SYSCALL) 71039937Ssklower printf("PRU_SEND: eot %d after sbappend 0x%x mbufcnt 0x%x\n", 71139937Ssklower eotsdu, n, mbufcnt); 71236420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 71336420Ssklower ENDDEBUG 71436420Ssklower error = DoEvent(T_DATA_req); 71536420Ssklower IFDEBUG(D_SYSCALL) 71636420Ssklower printf("PRU_SEND: after driver error 0x%x \n",error); 71737469Ssklower printf("so_snd 0x%x cc 0t%d mbcnt 0t%d\n", 71837469Ssklower sb, sb->sb_cc, sb->sb_mbcnt); 71937469Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver"); 72036420Ssklower ENDDEBUG 72136420Ssklower } 72236420Ssklower break; 72336420Ssklower 72437469Ssklower case PRU_SOCKADDR: 72537469Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_LOCAL); 72636420Ssklower break; 72736420Ssklower 72836420Ssklower case PRU_PEERADDR: 72938841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 73036420Ssklower break; 73136420Ssklower 73236420Ssklower case PRU_CONTROL: 73336420Ssklower error = EOPNOTSUPP; 73436420Ssklower break; 73536420Ssklower 73636420Ssklower case PRU_PROTOSEND: 73736420Ssklower case PRU_PROTORCV: 73836420Ssklower case PRU_SENSE: 73936420Ssklower case PRU_SLOWTIMO: 74036420Ssklower case PRU_FASTTIMO: 74136420Ssklower error = EOPNOTSUPP; 74236420Ssklower break; 74336420Ssklower 74436420Ssklower default: 74536420Ssklower #ifdef ARGO_DEBUG 74636420Ssklower printf("tp_usrreq UNKNOWN PRU %d\n", req); 74736420Ssklower #endif ARGO_DEBUG 74836420Ssklower error = EOPNOTSUPP; 74936420Ssklower } 75036420Ssklower 75136420Ssklower IFDEBUG(D_REQUEST) 75238841Ssklower printf("%s, so 0x%x, tpcb 0x%x, error %d, state %d\n", 75338841Ssklower "returning from tp_usrreq", so, tpcb, error, 75438841Ssklower tpcb ? 0 : tpcb->tp_state); 75536420Ssklower ENDDEBUG 75636420Ssklower IFTRACE(D_REQUEST) 75736420Ssklower tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m, 75836420Ssklower tpcb?0:tpcb->tp_state); 75936420Ssklower ENDTRACE 76041924Ssklower if (controlp) { 76141924Ssklower m_freem(controlp); 76241924Ssklower printf("control data unexpectedly retained in tp_usrreq()"); 76341924Ssklower } 76436420Ssklower splx(s); 76536420Ssklower return error; 76636420Ssklower } 76739196Ssklower tp_ltrace(so, uio) 76839196Ssklower struct socket *so; 76939196Ssklower struct uio *uio; 77039196Ssklower { 77139196Ssklower IFTRACE(D_DATA) 77239196Ssklower register struct tp_pcb *tpcb = sototpcb(so); 77339196Ssklower if (tpcb) { 77439196Ssklower tptraceTPCB(TPPTmisc, "sosend so resid iovcnt", so, 77539196Ssklower uio->uio_resid, uio->uio_iovcnt, 0); 77639196Ssklower } 77739196Ssklower ENDTRACE 77839196Ssklower } 77937469Ssklower 78038841Ssklower tp_confirm(tpcb) 78138841Ssklower register struct tp_pcb *tpcb; 78237469Ssklower { 78338841Ssklower struct tp_event E; 78438841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 78538841Ssklower return DoEvent(T_ACPT_req); 78638841Ssklower printf("Tp confirm called when not confirming; tpcb 0x%x, state 0x%x\n", 78738841Ssklower tpcb, tpcb->tp_state); 78838841Ssklower return 0; 78937469Ssklower } 79037469Ssklower 79137469Ssklower /* 79237469Ssklower * Process control data sent with sendmsg() 79337469Ssklower */ 79441924Ssklower tp_snd_control(m, so, data) 79541924Ssklower struct mbuf *m; 79637469Ssklower struct socket *so; 79737469Ssklower register struct mbuf **data; 79837469Ssklower { 79942468Ssklower register struct cmsghdr *ch; 80037469Ssklower int error = 0; 80137469Ssklower 80241924Ssklower if (m && m->m_len) { 80342468Ssklower ch = mtod(m, struct cmsghdr *); 80441924Ssklower m->m_len -= sizeof (*ch); 80541924Ssklower m->m_data += sizeof (*ch); 80637469Ssklower error = tp_ctloutput(PRCO_SETOPT, 80737469Ssklower so, ch->cmsg_level, ch->cmsg_type, &m); 80837469Ssklower if (ch->cmsg_type == TPOPT_DISC_DATA) { 80937469Ssklower if (data && *data) { 81037469Ssklower m_freem(*data); 81137469Ssklower *data = 0; 81237469Ssklower } 81341924Ssklower error = tp_usrreq(so, PRU_DISCONNECT, (struct mbuf *)0, 81441924Ssklower (caddr_t)0, (struct mbuf *)0); 81537469Ssklower } 81637469Ssklower } 81741924Ssklower if (m) 81841924Ssklower m_freem(m); 81937469Ssklower return error; 82037469Ssklower } 821