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*48736Ssklower * @(#)tp_usrreq.c 7.15 (Berkeley) 04/26/91 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) { 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 */ 20044310Ssklower 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 21544310Ssklower 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", 22644310Ssklower 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:"); 26944310Ssklower 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:"); 30144310Ssklower 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:"); 31444310Ssklower 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); 36044310Ssklower 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 } 38344310Ssklower 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 */ 39244310Ssklower 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 */ 40044424Ssklower if (tpcb->tp_state == TP_LISTENING) { 40144424Ssklower register struct tp_pcb **tt; 40244424Ssklower for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten)) 40344424Ssklower if (*tt == tpcb) 40444424Ssklower break; 40544424Ssklower if (*tt) 40644424Ssklower *tt = tpcb->tp_nextlisten; 40744424Ssklower else { 40844424Ssklower for (tt = &tp_intercepts; *tt; tt = &((*tt)->tp_nextlisten)) 40944424Ssklower if (*tt == tpcb) 41044424Ssklower break; 41144424Ssklower if (*tt) 41244424Ssklower *tt = tpcb->tp_nextlisten; 41344424Ssklower else 41444424Ssklower printf("tp_usrreq - detach: should panic\n"); 41544424Ssklower } 41644424Ssklower } 41744424Ssklower if (tpcb->tp_next) 41844424Ssklower remque(tpcb); 41936420Ssklower error = DoEvent(T_DETACH); 42037469Ssklower if (tpcb->tp_state == TP_CLOSED) { 42137469Ssklower free((caddr_t)tpcb, M_PCB); 42237469Ssklower tpcb = 0; 42337469Ssklower } 42436420Ssklower break; 42536420Ssklower 42636420Ssklower case PRU_SHUTDOWN: 42736420Ssklower /* recv end may have been released; local credit might be zero */ 42836420Ssklower case PRU_DISCONNECT: 42936420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NORMAL_DISC; 43036420Ssklower error = DoEvent(T_DISC_req); 43136420Ssklower break; 43236420Ssklower 43336420Ssklower case PRU_BIND: 43444310Ssklower error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, nam); 43536420Ssklower if (error == 0) { 43637469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 43744310Ssklower tpcb->tp_lsuffix, TP_LOCAL); 43836420Ssklower } 43936420Ssklower break; 44036420Ssklower 44136420Ssklower case PRU_LISTEN: 44244310Ssklower if (tpcb->tp_lsuffixlen == 0) { 44344310Ssklower if (error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL)) 44436420Ssklower break; 44537469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 44644310Ssklower tpcb->tp_lsuffix, TP_LOCAL); 44736420Ssklower } 44844424Ssklower if (tpcb->tp_next == 0) { 44944424Ssklower tpcb->tp_next = tpcb->tp_prev = tpcb; 45044424Ssklower tpcb->tp_nextlisten = tp_listeners; 45144601Ssklower tp_listeners = tpcb; 45244424Ssklower } 45336420Ssklower IFDEBUG(D_TPISO) 45444310Ssklower if (tpcb->tp_state != TP_CLOSED) 45536420Ssklower printf("LISTEN ERROR: state 0x%x\n", tpcb->tp_state); 45636420Ssklower ENDDEBUG 45736420Ssklower error = DoEvent(T_LISTEN_req); 45836420Ssklower break; 45936420Ssklower 46036420Ssklower case PRU_CONNECT2: 46136420Ssklower error = EOPNOTSUPP; /* for unix domain sockets */ 46236420Ssklower break; 46336420Ssklower 46436420Ssklower case PRU_CONNECT: 46536420Ssklower IFTRACE(D_CONN) 46636420Ssklower tptraceTPCB(TPPTmisc, 46737469Ssklower "PRU_CONNECT: so 0x%x *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 46836420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 46936420Ssklower tpcb->tp_class); 47036420Ssklower ENDTRACE 47136420Ssklower IFDEBUG(D_CONN) 47236420Ssklower printf("PRU_CONNECT: so *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 47336420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 47436420Ssklower tpcb->tp_class); 47536420Ssklower ENDDEBUG 47644310Ssklower if (tpcb->tp_lsuffixlen == 0) { 47744310Ssklower if (error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL)) { 47836420Ssklower IFDEBUG(D_CONN) 47944310Ssklower printf("pcbbind returns error 0x%x\n", error); 48036420Ssklower ENDDEBUG 48136420Ssklower break; 48236420Ssklower } 48337469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 48444310Ssklower tpcb->tp_lsuffix, TP_LOCAL); 48537469Ssklower } 48636420Ssklower 48736420Ssklower IFDEBUG(D_CONN) 48836420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 48944310Ssklower dump_buf(tpcb->tp_npcb, 16); 49036420Ssklower ENDDEBUG 49144310Ssklower if (error = tp_route_to(nam, tpcb, /* channel */0)) 49236420Ssklower break; 49336420Ssklower IFDEBUG(D_CONN) 49436420Ssklower printf( 49536420Ssklower "PRU_CONNECT after tpcb 0x%x so 0x%x npcb 0x%x flags 0x%x\n", 49636420Ssklower tpcb, so, tpcb->tp_npcb, tpcb->tp_flags); 49736420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 49844310Ssklower dump_buf(tpcb->tp_npcb, 16); 49936420Ssklower ENDDEBUG 50044310Ssklower if (tpcb->tp_fsuffixlen == 0) { 50136420Ssklower /* didn't set peer extended suffix */ 50237469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_fsuffixlen, 50344310Ssklower tpcb->tp_fsuffix, TP_FOREIGN); 50436420Ssklower } 50536420Ssklower (void) (tpcb->tp_nlproto->nlp_mtu)(so, so->so_pcb, 50636420Ssklower &tpcb->tp_l_tpdusize, &tpcb->tp_tpdusize, 0); 50744310Ssklower if (tpcb->tp_state == TP_CLOSED) { 50836420Ssklower soisconnecting(so); 50936420Ssklower error = DoEvent(T_CONN_req); 51036420Ssklower } else { 51136420Ssklower (tpcb->tp_nlproto->nlp_pcbdisc)(so->so_pcb); 51236420Ssklower error = EISCONN; 51336420Ssklower } 51436420Ssklower IFPERF(tpcb) 51536420Ssklower u_int lsufx, fsufx; 51639196Ssklower lsufx = *(u_short *)(tpcb->tp_lsuffix); 51739196Ssklower fsufx = *(u_short *)(tpcb->tp_fsuffix); 51836420Ssklower 51944310Ssklower tpmeas(tpcb->tp_lref, 52044310Ssklower TPtime_open | (tpcb->tp_xtd_format << 4), 52136420Ssklower &time, lsufx, fsufx, tpcb->tp_fref); 52236420Ssklower ENDPERF 52336420Ssklower break; 52436420Ssklower 52536420Ssklower case PRU_ACCEPT: 52638841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 52736420Ssklower IFDEBUG(D_REQUEST) 52838841Ssklower printf("ACCEPT PEERADDDR:"); 52938841Ssklower dump_buf(mtod(nam, char *), nam->m_len); 53036420Ssklower ENDDEBUG 53136420Ssklower IFPERF(tpcb) 53236420Ssklower u_int lsufx, fsufx; 53339196Ssklower lsufx = *(u_short *)(tpcb->tp_lsuffix); 53439196Ssklower fsufx = *(u_short *)(tpcb->tp_fsuffix); 53536420Ssklower 53644310Ssklower tpmeas(tpcb->tp_lref, TPtime_open, 53736420Ssklower &time, lsufx, fsufx, tpcb->tp_fref); 53836420Ssklower ENDPERF 53936420Ssklower break; 54036420Ssklower 54136420Ssklower case PRU_RCVD: 54238841Ssklower if (so->so_state & SS_ISCONFIRMING) { 54338841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 54438841Ssklower error = tp_confirm(tpcb); 54538841Ssklower break; 54638841Ssklower } 54736420Ssklower IFTRACE(D_DATA) 54836420Ssklower tptraceTPCB(TPPTmisc, 54936420Ssklower "RCVD BF: lcredit sent_lcdt cc hiwat \n", 55036420Ssklower tpcb->tp_lcredit, tpcb->tp_sent_lcdt, 55136420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 55236420Ssklower LOCAL_CREDIT(tpcb); 55336420Ssklower tptraceTPCB(TPPTmisc, 55436420Ssklower "PRU_RCVD AF sbspace lcredit hiwat cc", 55536420Ssklower sbspace(&so->so_rcv), tpcb->tp_lcredit, 55636420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 55736420Ssklower ENDTRACE 55837469Ssklower IFDEBUG(D_REQUEST) 55937469Ssklower printf("RCVD: cc %d space %d hiwat %d\n", 56037469Ssklower so->so_rcv.sb_cc, sbspace(&so->so_rcv), 56137469Ssklower so->so_rcv.sb_hiwat); 56237469Ssklower ENDDEBUG 56337469Ssklower if (((int)nam) & MSG_OOB) 56437469Ssklower error = DoEvent(T_USR_Xrcvd); 56537469Ssklower else 56637469Ssklower error = DoEvent(T_USR_rcvd); 56736420Ssklower break; 56836420Ssklower 56936420Ssklower case PRU_RCVOOB: 57036420Ssklower if ((so->so_state & SS_ISCONNECTED) == 0) { 57136420Ssklower error = ENOTCONN; 57236420Ssklower break; 57336420Ssklower } 57444310Ssklower if (! tpcb->tp_xpd_service) { 57536420Ssklower error = EOPNOTSUPP; 57636420Ssklower break; 57736420Ssklower } 57836420Ssklower /* kludge - nam is really flags here */ 57936420Ssklower error = tp_rcvoob(tpcb, so, m, outflags, (int)nam); 58036420Ssklower break; 58136420Ssklower 58238841Ssklower case PRU_SEND: 58336420Ssklower case PRU_SENDOOB: 58441924Ssklower if (controlp) { 58541924Ssklower error = tp_snd_control(controlp, so, &m); 58641924Ssklower controlp = NULL; 58741924Ssklower if (error) 58841924Ssklower break; 58941924Ssklower } 590*48736Ssklower if ((so->so_state & SS_ISCONFIRMING) && 591*48736Ssklower (tpcb->tp_state == TP_CONFIRMING) && 592*48736Ssklower (error = tp_confirm(tpcb))) 593*48736Ssklower break; 594*48736Ssklower if (req == PRU_SENDOOB) { 595*48736Ssklower error = (tpcb->tp_xpd_service == 0) ? 596*48736Ssklower EOPNOTSUPP : tp_sendoob(tpcb, so, m, outflags); 59738841Ssklower break; 59838841Ssklower } 59937469Ssklower if (m == 0) 60037469Ssklower break; 601*48736Ssklower if (m->m_flags & M_EOR) { 602*48736Ssklower eotsdu = 1; 603*48736Ssklower m->m_flags &= ~M_EOR; 604*48736Ssklower } 605*48736Ssklower if (eotsdu == 0 && m->m_pkthdr.len == 0) 60636420Ssklower break; 607*48736Ssklower if (tpcb->tp_state != TP_AKWAIT && tpcb->tp_state != TP_OPEN) { 608*48736Ssklower error = ENOTCONN; 609*48736Ssklower break; 61036420Ssklower } 61136420Ssklower /* 61236420Ssklower * The protocol machine copies mbuf chains, 61336420Ssklower * prepends headers, assigns seq numbers, and 61436420Ssklower * puts the packets on the device. 61536420Ssklower * When they are acked they are removed from the socket buf. 61636420Ssklower * 61736420Ssklower * sosend calls this up until sbspace goes negative. 61836420Ssklower * Sbspace may be made negative by appending this mbuf chain, 61936420Ssklower * possibly by a whole cluster. 62036420Ssklower */ 62136420Ssklower { 62237469Ssklower register struct mbuf *n = m; 62336420Ssklower register struct sockbuf *sb = &so->so_snd; 62437469Ssklower int maxsize = tpcb->tp_l_tpdusize 62537469Ssklower - tp_headersize(DT_TPDU_type, tpcb) 62637469Ssklower - (tpcb->tp_use_checksum?4:0) ; 62737469Ssklower int totlen = n->m_pkthdr.len; 62839937Ssklower int mbufcnt = 0; 62939196Ssklower struct mbuf *nn; 63036420Ssklower 63137469Ssklower /* 63237469Ssklower * Could have eotsdu and no data.(presently MUST have 63337469Ssklower * an mbuf though, even if its length == 0) 63437469Ssklower */ 63536420Ssklower IFPERF(tpcb) 63637469Ssklower PStat(tpcb, Nb_from_sess) += totlen; 63736420Ssklower tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0, 63837469Ssklower PStat(tpcb, Nb_from_sess), totlen); 63936420Ssklower ENDPERF 64036420Ssklower IFDEBUG(D_SYSCALL) 64136420Ssklower printf( 64236420Ssklower "PRU_SEND: eot %d before sbappend 0x%x len 0x%x to sb @ 0x%x\n", 64339937Ssklower eotsdu, m, totlen, sb); 64436420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 64536420Ssklower dump_mbuf(m, "m : to be added"); 64636420Ssklower ENDDEBUG 64737469Ssklower /* 64837469Ssklower * Pre-packetize the data in the sockbuf 64937469Ssklower * according to negotiated mtu. Do it here 65037469Ssklower * where we can safely wait for mbufs. 65139196Ssklower * 65239196Ssklower * This presumes knowledge of sockbuf conventions. 65336420Ssklower */ 65439196Ssklower if (n = sb->sb_mb) 65539196Ssklower while (n->m_act) 65639196Ssklower n = n->m_act; 65739647Ssklower if ((nn = n) && n->m_pkthdr.len < maxsize) { 65839937Ssklower u_int space = maxsize - n->m_pkthdr.len; 65939647Ssklower 66039647Ssklower do { 66139647Ssklower if (n->m_flags & M_EOR) 66239647Ssklower goto on1; 66339647Ssklower } while (n->m_next && (n = n->m_next)); 66439937Ssklower if (totlen <= space) { 66539937Ssklower TPNagle1++; 66639196Ssklower n->m_next = m; 66739937Ssklower nn->m_pkthdr.len += totlen; 66839937Ssklower while (n = n->m_next) 66939937Ssklower sballoc(sb, n); 67039196Ssklower if (eotsdu) 67139196Ssklower nn->m_flags |= M_EOR; 67239196Ssklower goto on2; 67339937Ssklower } else { 67439937Ssklower /* 67539937Ssklower * Can't sleep here, because when you wake up 67639937Ssklower * packet you want to attach to may be gone! 67739937Ssklower */ 67839937Ssklower if (TNew && (n->m_next = m_copym(m, 0, space, M_NOWAIT))) { 67939937Ssklower nn->m_pkthdr.len += space; 68039937Ssklower TPNagle2++; 68139937Ssklower while (n = n->m_next) 68239937Ssklower sballoc(sb, n); 68339937Ssklower m_adj(m, space); 68439937Ssklower } 68539196Ssklower } 68639196Ssklower } 68739937Ssklower on1: mbufcnt++; 68839196Ssklower for (n = m; n->m_pkthdr.len > maxsize;) { 68939937Ssklower nn = m_copym(n, 0, maxsize, M_WAIT); 69037469Ssklower sbappendrecord(sb, nn); 69137469Ssklower m_adj(n, maxsize); 69239937Ssklower mbufcnt++; 69337469Ssklower } 69439196Ssklower if (eotsdu) 69539196Ssklower n->m_flags |= M_EOR; 69637469Ssklower sbappendrecord(sb, n); 69739196Ssklower on2: 69839196Ssklower IFTRACE(D_DATA) 69939196Ssklower tptraceTPCB(TPPTmisc, 70039937Ssklower "SEND BF: maxsize totlen mbufcnt eotsdu", 70139937Ssklower maxsize, totlen, mbufcnt, eotsdu); 70239196Ssklower ENDTRACE 70336420Ssklower IFDEBUG(D_SYSCALL) 70439937Ssklower printf("PRU_SEND: eot %d after sbappend 0x%x mbufcnt 0x%x\n", 70539937Ssklower eotsdu, n, mbufcnt); 70636420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 70736420Ssklower ENDDEBUG 708*48736Ssklower if (tpcb->tp_state == TP_OPEN) 709*48736Ssklower error = DoEvent(T_DATA_req); 71036420Ssklower IFDEBUG(D_SYSCALL) 71136420Ssklower printf("PRU_SEND: after driver error 0x%x \n",error); 71237469Ssklower printf("so_snd 0x%x cc 0t%d mbcnt 0t%d\n", 71337469Ssklower sb, sb->sb_cc, sb->sb_mbcnt); 71437469Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver"); 71536420Ssklower ENDDEBUG 71636420Ssklower } 71736420Ssklower break; 71836420Ssklower 71937469Ssklower case PRU_SOCKADDR: 72037469Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_LOCAL); 72136420Ssklower break; 72236420Ssklower 72336420Ssklower case PRU_PEERADDR: 72438841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 72536420Ssklower break; 72636420Ssklower 72736420Ssklower case PRU_CONTROL: 72836420Ssklower error = EOPNOTSUPP; 72936420Ssklower break; 73036420Ssklower 73136420Ssklower case PRU_PROTOSEND: 73236420Ssklower case PRU_PROTORCV: 73336420Ssklower case PRU_SENSE: 73436420Ssklower case PRU_SLOWTIMO: 73536420Ssklower case PRU_FASTTIMO: 73636420Ssklower error = EOPNOTSUPP; 73736420Ssklower break; 73836420Ssklower 73936420Ssklower default: 74036420Ssklower #ifdef ARGO_DEBUG 74136420Ssklower printf("tp_usrreq UNKNOWN PRU %d\n", req); 74236420Ssklower #endif ARGO_DEBUG 74336420Ssklower error = EOPNOTSUPP; 74436420Ssklower } 74536420Ssklower 74636420Ssklower IFDEBUG(D_REQUEST) 74738841Ssklower printf("%s, so 0x%x, tpcb 0x%x, error %d, state %d\n", 74838841Ssklower "returning from tp_usrreq", so, tpcb, error, 74938841Ssklower tpcb ? 0 : tpcb->tp_state); 75036420Ssklower ENDDEBUG 75136420Ssklower IFTRACE(D_REQUEST) 75236420Ssklower tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m, 75336420Ssklower tpcb?0:tpcb->tp_state); 75436420Ssklower ENDTRACE 75541924Ssklower if (controlp) { 75641924Ssklower m_freem(controlp); 75741924Ssklower printf("control data unexpectedly retained in tp_usrreq()"); 75841924Ssklower } 75936420Ssklower splx(s); 76036420Ssklower return error; 76136420Ssklower } 76239196Ssklower tp_ltrace(so, uio) 76339196Ssklower struct socket *so; 76439196Ssklower struct uio *uio; 76539196Ssklower { 76639196Ssklower IFTRACE(D_DATA) 76739196Ssklower register struct tp_pcb *tpcb = sototpcb(so); 76839196Ssklower if (tpcb) { 76939196Ssklower tptraceTPCB(TPPTmisc, "sosend so resid iovcnt", so, 77039196Ssklower uio->uio_resid, uio->uio_iovcnt, 0); 77139196Ssklower } 77239196Ssklower ENDTRACE 77339196Ssklower } 77437469Ssklower 77538841Ssklower tp_confirm(tpcb) 77638841Ssklower register struct tp_pcb *tpcb; 77737469Ssklower { 77838841Ssklower struct tp_event E; 77938841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 78038841Ssklower return DoEvent(T_ACPT_req); 78138841Ssklower printf("Tp confirm called when not confirming; tpcb 0x%x, state 0x%x\n", 78238841Ssklower tpcb, tpcb->tp_state); 78338841Ssklower return 0; 78437469Ssklower } 78537469Ssklower 78637469Ssklower /* 78737469Ssklower * Process control data sent with sendmsg() 78837469Ssklower */ 78941924Ssklower tp_snd_control(m, so, data) 79041924Ssklower struct mbuf *m; 79137469Ssklower struct socket *so; 79237469Ssklower register struct mbuf **data; 79337469Ssklower { 79442468Ssklower register struct cmsghdr *ch; 79537469Ssklower int error = 0; 79637469Ssklower 79741924Ssklower if (m && m->m_len) { 79842468Ssklower ch = mtod(m, struct cmsghdr *); 79941924Ssklower m->m_len -= sizeof (*ch); 80041924Ssklower m->m_data += sizeof (*ch); 80137469Ssklower error = tp_ctloutput(PRCO_SETOPT, 80237469Ssklower so, ch->cmsg_level, ch->cmsg_type, &m); 80337469Ssklower if (ch->cmsg_type == TPOPT_DISC_DATA) { 80437469Ssklower if (data && *data) { 80537469Ssklower m_freem(*data); 80637469Ssklower *data = 0; 80737469Ssklower } 80841924Ssklower error = tp_usrreq(so, PRU_DISCONNECT, (struct mbuf *)0, 80941924Ssklower (caddr_t)0, (struct mbuf *)0); 81037469Ssklower } 81137469Ssklower } 81241924Ssklower if (m) 81341924Ssklower m_freem(m); 81437469Ssklower return error; 81537469Ssklower } 816