149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*50236Ssklower * @(#)tp_usrreq.c 7.17 (Berkeley) 06/27/91 849268Sbostic */ 949268Sbostic 1036420Ssklower /*********************************************************** 1139196Ssklower Copyright IBM Corporation 1987 1236420Ssklower 1336420Ssklower All Rights Reserved 1436420Ssklower 1536420Ssklower Permission to use, copy, modify, and distribute this software and its 1636420Ssklower documentation for any purpose and without fee is hereby granted, 1736420Ssklower provided that the above copyright notice appear in all copies and that 1836420Ssklower both that copyright notice and this permission notice appear in 1936420Ssklower supporting documentation, and that the name of IBM not be 2036420Ssklower used in advertising or publicity pertaining to distribution of the 2136420Ssklower software without specific, written prior permission. 2236420Ssklower 2336420Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436420Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536420Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636420Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736420Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836420Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936420Ssklower SOFTWARE. 3036420Ssklower 3136420Ssklower ******************************************************************/ 3236420Ssklower 3336420Ssklower /* 3436420Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536420Ssklower */ 3636420Ssklower /* 3736420Ssklower * ARGO TP 3836420Ssklower * 3936420Ssklower * $Header: tp_usrreq.c,v 5.4 88/11/18 17:29:18 nhall Exp $ 4036420Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_usrreq.c,v $ 4136420Ssklower * 4236420Ssklower * tp_usrreq(), the fellow that gets called from most of the socket code. 4336420Ssklower * Pretty straighforward. 4436420Ssklower * THe only really awful stuff here is the OOB processing, which is done 4536420Ssklower * wholly here. 4636420Ssklower * tp_rcvoob() and tp_sendoob() are contained here and called by tp_usrreq(). 4736420Ssklower */ 4836420Ssklower 4936420Ssklower #include "param.h" 5036420Ssklower #include "systm.h" 5136420Ssklower #include "mbuf.h" 5236420Ssklower #include "socket.h" 5336420Ssklower #include "socketvar.h" 5436420Ssklower #include "domain.h" 5536420Ssklower #include "protosw.h" 5636420Ssklower #include "errno.h" 57*50236Ssklower #include "time.h" 5836420Ssklower 5937469Ssklower #include "tp_param.h" 6037469Ssklower #include "tp_timer.h" 6137469Ssklower #include "tp_stat.h" 6237469Ssklower #include "tp_seq.h" 6337469Ssklower #include "tp_ip.h" 6437469Ssklower #include "tp_pcb.h" 6537469Ssklower #include "argo_debug.h" 6637469Ssklower #include "tp_trace.h" 6737469Ssklower #include "tp_meas.h" 6837469Ssklower #include "iso.h" 6937469Ssklower #include "iso_errno.h" 7036420Ssklower 7136420Ssklower int tp_attach(), tp_driver(); 7239937Ssklower int TNew; 7339937Ssklower int TPNagle1, TPNagle2; 7444424Ssklower struct tp_pcb *tp_listeners, *tp_intercepts; 7536420Ssklower 7636420Ssklower #ifdef ARGO_DEBUG 7736420Ssklower /* 7836420Ssklower * CALLED FROM: 7936420Ssklower * anywhere you want to debug... 8036420Ssklower * FUNCTION and ARGUMENTS: 8136420Ssklower * print (str) followed by the control info in the mbufs of an mbuf chain (n) 8236420Ssklower */ 8336420Ssklower void 8436420Ssklower dump_mbuf(n, str) 8536420Ssklower struct mbuf *n; 8636420Ssklower char *str; 8736420Ssklower { 8836420Ssklower struct mbuf *nextrecord; 8936420Ssklower 9036420Ssklower printf("dump %s\n", str); 9136420Ssklower 9244310Ssklower if (n == MNULL) { 9336420Ssklower printf("EMPTY:\n"); 9436420Ssklower return; 9536420Ssklower } 9636420Ssklower 9744310Ssklower while (n) { 9836420Ssklower nextrecord = n->m_act; 9936420Ssklower printf("RECORD:\n"); 10036420Ssklower while (n) { 10137469Ssklower printf("%x : Len %x Data %x A %x Nx %x Tp %x\n", 10237469Ssklower n, n->m_len, n->m_data, n->m_act, n->m_next, n->m_type); 10336420Ssklower #ifdef notdef 10436420Ssklower { 10536420Ssklower register char *p = mtod(n, char *); 10636420Ssklower register int i; 10736420Ssklower 10836420Ssklower printf("data: "); 10944310Ssklower for (i = 0; i < n->m_len; i++) { 11044310Ssklower if (i%8 == 0) 11136420Ssklower printf("\n"); 11236420Ssklower printf("0x%x ", *(p+i)); 11336420Ssklower } 11436420Ssklower printf("\n"); 11536420Ssklower } 11636420Ssklower #endif notdef 11744310Ssklower if (n->m_next == n) { 11836420Ssklower printf("LOOP!\n"); 11936420Ssklower return; 12036420Ssklower } 12136420Ssklower n = n->m_next; 12236420Ssklower } 12336420Ssklower n = nextrecord; 12436420Ssklower } 12536420Ssklower printf("\n"); 12636420Ssklower } 12736420Ssklower 12836420Ssklower #endif ARGO_DEBUG 12936420Ssklower 13036420Ssklower /* 13136420Ssklower * CALLED FROM: 13236420Ssklower * tp_usrreq(), PRU_RCVOOB 13336420Ssklower * FUNCTION and ARGUMENTS: 13436420Ssklower * Copy data from the expedited data socket buffer into 13536420Ssklower * the pre-allocated mbuf m. 13636420Ssklower * There is an isomorphism between XPD TPDUs and expedited data TSDUs. 13736420Ssklower * XPD tpdus are limited to 16 bytes of data so they fit in one mbuf. 13836420Ssklower * RETURN VALUE: 13936420Ssklower * EINVAL if debugging is on and a disaster has occurred 14036420Ssklower * ENOTCONN if the socket isn't connected 14136420Ssklower * EWOULDBLOCK if the socket is in non-blocking mode and there's no 14236420Ssklower * xpd data in the buffer 14336420Ssklower * E* whatever is returned from the fsm. 14436420Ssklower */ 14536420Ssklower tp_rcvoob(tpcb, so, m, outflags, inflags) 14636420Ssklower struct tp_pcb *tpcb; 14736420Ssklower register struct socket *so; 14836420Ssklower register struct mbuf *m; 14936420Ssklower int *outflags; 15036420Ssklower int inflags; 15136420Ssklower { 15236420Ssklower register struct mbuf *n; 15337469Ssklower register struct sockbuf *sb = &so->so_rcv; 15436420Ssklower struct tp_event E; 15536420Ssklower int error = 0; 15637469Ssklower register struct mbuf **nn; 15736420Ssklower 15836420Ssklower IFDEBUG(D_XPD) 15936420Ssklower printf("PRU_RCVOOB, sostate 0x%x\n", so->so_state); 16036420Ssklower ENDDEBUG 16136420Ssklower 16236420Ssklower /* if you use soreceive */ 16344310Ssklower if (m == MNULL) 16436420Ssklower return ENOBUFS; 16536420Ssklower 16636420Ssklower restart: 16736420Ssklower if ((((so->so_state & SS_ISCONNECTED) == 0) 16836420Ssklower || (so->so_state & SS_ISDISCONNECTING) != 0) && 16936420Ssklower (so->so_proto->pr_flags & PR_CONNREQUIRED)) { 17036420Ssklower return ENOTCONN; 17136420Ssklower } 17236420Ssklower 17337469Ssklower /* Take the first mbuf off the chain. 17437469Ssklower * Each XPD TPDU gives you a complete TSDU so the chains don't get 17537469Ssklower * coalesced, but one TSDU may span several mbufs. 17637469Ssklower * Nevertheless, since n should have a most 16 bytes, it 17737469Ssklower * will fit into m. (size was checked in tp_input() ) 17837469Ssklower */ 17937469Ssklower 18037469Ssklower /* 18137469Ssklower * Code for excision of OOB data should be added to 18237469Ssklower * uipc_socket2.c (like sbappend). 18337469Ssklower */ 18437469Ssklower 18538841Ssklower sblock(sb); 18637469Ssklower for (nn = &sb->sb_mb; n = *nn; nn = &n->m_act) 18737469Ssklower if (n->m_type == MT_OOBDATA) 18837469Ssklower break; 18937469Ssklower 19037469Ssklower if (n == 0) { 19136420Ssklower IFDEBUG(D_XPD) 19236420Ssklower printf("RCVOOB: empty queue!\n"); 19336420Ssklower ENDDEBUG 19438841Ssklower sbunlock(sb); 19536420Ssklower if (so->so_state & SS_NBIO) { 19636420Ssklower return EWOULDBLOCK; 19736420Ssklower } 19836420Ssklower sbwait(sb); 19936420Ssklower goto restart; 20036420Ssklower } 20136420Ssklower m->m_len = 0; 20236420Ssklower 20336420Ssklower /* Assuming at most one xpd tpdu is in the buffer at once */ 20444310Ssklower while (n != MNULL) { 20536420Ssklower m->m_len += n->m_len; 20637469Ssklower bcopy(mtod(n, caddr_t), mtod(m, caddr_t), (unsigned)n->m_len); 20737469Ssklower m->m_data += n->m_len; /* so mtod() in bcopy() above gives right addr */ 20836420Ssklower n = n->m_next; 20936420Ssklower } 21037469Ssklower m->m_data = m->m_dat; 21137469Ssklower m->m_flags |= M_EOR; 21236420Ssklower 21336420Ssklower IFDEBUG(D_XPD) 21436420Ssklower printf("tp_rcvoob: xpdlen 0x%x\n", m->m_len); 21536420Ssklower dump_mbuf(so->so_rcv.sb_mb, "RCVOOB: Rcv socketbuf"); 21636420Ssklower dump_mbuf(sb->sb_mb, "RCVOOB: Xrcv socketbuf"); 21736420Ssklower ENDDEBUG 21836420Ssklower 21944310Ssklower if ((inflags & MSG_PEEK) == 0) { 22037469Ssklower n = *nn; 22137469Ssklower *nn = n->m_act; 22237469Ssklower sb->sb_cc -= m->m_len; 22337469Ssklower } 22436420Ssklower 22536420Ssklower release: 22636420Ssklower sbunlock(sb); 22736420Ssklower 22836420Ssklower IFTRACE(D_XPD) 22936420Ssklower tptraceTPCB(TPPTmisc, "PRU_RCVOOB @ release sb_cc m_len", 23044310Ssklower tpcb->tp_Xrcv.sb_cc, m->m_len, 0, 0); 23136420Ssklower ENDTRACE 23236420Ssklower if (error == 0) 23336420Ssklower error = DoEvent(T_USR_Xrcvd); 23436420Ssklower return error; 23536420Ssklower } 23636420Ssklower 23736420Ssklower /* 23836420Ssklower * CALLED FROM: 23936420Ssklower * tp_usrreq(), PRU_SENDOOB 24036420Ssklower * FUNCTION and ARGUMENTS: 24136420Ssklower * Send what's in the mbuf chain (m) as an XPD TPDU. 24236420Ssklower * The mbuf may not contain more then 16 bytes of data. 24336420Ssklower * XPD TSDUs aren't segmented, so they translate into 24436420Ssklower * exactly one XPD TPDU, with EOT bit set. 24536420Ssklower * RETURN VALUE: 24636420Ssklower * EWOULDBLOCK if socket is in non-blocking mode and the previous 24736420Ssklower * xpd data haven't been acked yet. 24836420Ssklower * EMSGSIZE if trying to send > max-xpd bytes (16) 24936420Ssklower * ENOBUFS if ran out of mbufs 25036420Ssklower */ 25136420Ssklower tp_sendoob(tpcb, so, xdata, outflags) 25236420Ssklower struct tp_pcb *tpcb; 25336420Ssklower register struct socket *so; 25436420Ssklower register struct mbuf *xdata; 25536420Ssklower int *outflags; /* not used */ 25636420Ssklower { 25736420Ssklower /* 25836420Ssklower * Each mbuf chain represents a sequence # in the XPD seq space. 25936420Ssklower * The first one in the queue has sequence # tp_Xuna. 26036420Ssklower * When we add to the XPD queue, we stuff a zero-length 26136420Ssklower * mbuf (mark) into the DATA queue, with its sequence number in m_next 26236420Ssklower * to be assigned to this XPD tpdu, so data xfer can stop 26336420Ssklower * when it reaches the zero-length mbuf if this XPD TPDU hasn't 26436420Ssklower * yet been acknowledged. 26536420Ssklower */ 26636420Ssklower register struct sockbuf *sb = &(tpcb->tp_Xsnd); 26736420Ssklower register struct mbuf *xmark; 26836420Ssklower register int len=0; 26936420Ssklower struct tp_event E; 27036420Ssklower 27136420Ssklower IFDEBUG(D_XPD) 27236420Ssklower printf("tp_sendoob:"); 27344310Ssklower if (xdata) 27436420Ssklower printf("xdata len 0x%x\n", xdata->m_len); 27536420Ssklower ENDDEBUG 27636420Ssklower /* DO NOT LOCK the Xsnd buffer!!!! You can have at MOST one 27736420Ssklower * socket buf locked at any time!!! (otherwise you might 27836420Ssklower * sleep() in sblock() w/ a signal pending and cause the 27936420Ssklower * system call to be aborted w/ a locked socketbuf, which 28036420Ssklower * is a problem. So the so_snd buffer lock 28136420Ssklower * (done in sosend()) serves as the lock for Xpd. 28236420Ssklower */ 28338841Ssklower if (sb->sb_mb) { /* Anything already in eXpedited data sockbuf? */ 28436420Ssklower if (so->so_state & SS_NBIO) { 28536420Ssklower return EWOULDBLOCK; 28636420Ssklower } 28738841Ssklower while (sb->sb_mb) { 28838841Ssklower sbunlock(&so->so_snd); /* already locked by sosend */ 28938841Ssklower sbwait(&so->so_snd); 29038841Ssklower sblock(&so->so_snd); /* sosend will unlock on return */ 29138841Ssklower } 29236420Ssklower } 29336420Ssklower 29436420Ssklower if (xdata == (struct mbuf *)0) { 29536420Ssklower /* empty xpd packet */ 29637469Ssklower MGETHDR(xdata, M_WAIT, MT_OOBDATA); 29736420Ssklower if (xdata == NULL) { 29836420Ssklower return ENOBUFS; 29936420Ssklower } 30036420Ssklower xdata->m_len = 0; 30137469Ssklower xdata->m_pkthdr.len = 0; 30236420Ssklower } 30336420Ssklower IFDEBUG(D_XPD) 30436420Ssklower printf("tp_sendoob 1:"); 30544310Ssklower if (xdata) 30636420Ssklower printf("xdata len 0x%x\n", xdata->m_len); 30736420Ssklower ENDDEBUG 30836420Ssklower xmark = xdata; /* temporary use of variable xmark */ 30936420Ssklower while (xmark) { 31036420Ssklower len += xmark->m_len; 31136420Ssklower xmark = xmark->m_next; 31236420Ssklower } 31336420Ssklower if (len > TP_MAX_XPD_DATA) { 31436420Ssklower return EMSGSIZE; 31536420Ssklower } 31636420Ssklower IFDEBUG(D_XPD) 31736420Ssklower printf("tp_sendoob 2:"); 31844310Ssklower if (xdata) 31936420Ssklower printf("xdata len 0x%x\n", len); 32036420Ssklower ENDDEBUG 32136420Ssklower 32236420Ssklower 32336420Ssklower IFTRACE(D_XPD) 32438841Ssklower tptraceTPCB(TPPTmisc, "XPD mark m_next ", xdata->m_next, 0, 0, 0); 32536420Ssklower ENDTRACE 32636420Ssklower 32736420Ssklower sbappendrecord(sb, xdata); 32836420Ssklower 32936420Ssklower IFDEBUG(D_XPD) 33036420Ssklower printf("tp_sendoob len 0x%x\n", len); 33136420Ssklower dump_mbuf(so->so_snd.sb_mb, "XPD request Regular sndbuf:"); 33236420Ssklower dump_mbuf(tpcb->tp_Xsnd.sb_mb, "XPD request Xsndbuf:"); 33336420Ssklower ENDDEBUG 33436420Ssklower return DoEvent(T_XPD_req); 33536420Ssklower } 33636420Ssklower 33736420Ssklower /* 33836420Ssklower * CALLED FROM: 33936420Ssklower * the socket routines 34036420Ssklower * FUNCTION and ARGUMENTS: 34136420Ssklower * Handles all "user requests" except the [gs]ockopts() requests. 34236420Ssklower * The argument (req) is the request type (PRU*), 34336420Ssklower * (m) is an mbuf chain, generally used for send and 34436420Ssklower * receive type requests only. 34536420Ssklower * (nam) is used for addresses usually, in particular for the bind request. 34636420Ssklower * 34736420Ssklower */ 34836420Ssklower /*ARGSUSED*/ 34936420Ssklower ProtoHook 35040773Ssklower tp_usrreq(so, req, m, nam, controlp) 35136420Ssklower struct socket *so; 35236420Ssklower u_int req; 35340773Ssklower struct mbuf *m, *nam, *controlp; 35436420Ssklower { 35536420Ssklower register struct tp_pcb *tpcb = sototpcb(so); 35636420Ssklower int s = splnet(); 35736420Ssklower int error = 0; 35837469Ssklower int flags, *outflags = &flags; 35936420Ssklower u_long eotsdu = 0; 36036420Ssklower struct tp_event E; 36136420Ssklower 36236420Ssklower IFDEBUG(D_REQUEST) 36336420Ssklower printf("usrreq(0x%x,%d,0x%x,0x%x,0x%x)\n",so,req,m,nam,outflags); 36444310Ssklower if (so->so_error) 36536420Ssklower printf("WARNING!!! so->so_error is 0x%x\n", so->so_error); 36636420Ssklower ENDDEBUG 36736420Ssklower IFTRACE(D_REQUEST) 36836420Ssklower tptraceTPCB(TPPTusrreq, "req so m state [", req, so, m, 36936420Ssklower tpcb?tpcb->tp_state:0); 37036420Ssklower ENDTRACE 37136420Ssklower 37236420Ssklower if ((u_int)tpcb == 0 && req != PRU_ATTACH) { 37336420Ssklower IFTRACE(D_REQUEST) 37436420Ssklower tptraceTPCB(TPPTusrreq, "req failed NO TPCB[", 0, 0, 0, 0); 37536420Ssklower ENDTRACE 37636420Ssklower splx(s); 37736420Ssklower return ENOTCONN; 37836420Ssklower } 37936420Ssklower 38036420Ssklower switch (req) { 38136420Ssklower 38236420Ssklower case PRU_ATTACH: 38336420Ssklower if (tpcb) { 38436420Ssklower error = EISCONN; 38536420Ssklower break; 38636420Ssklower } 38744310Ssklower if (error = tp_attach(so, so->so_proto->pr_domain->dom_family)) 38836420Ssklower break; 38936420Ssklower tpcb = sototpcb(so); 39036420Ssklower break; 39136420Ssklower 39236420Ssklower case PRU_ABORT: /* called from close() */ 39336420Ssklower /* called for each incoming connect queued on the 39436420Ssklower * parent (accepting) socket 39536420Ssklower */ 39644310Ssklower if (tpcb->tp_state == TP_OPEN) { 39736420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NO_SESSION; 39836420Ssklower error = DoEvent(T_DISC_req); /* pretend it was a close() */ 39936420Ssklower break; 40036420Ssklower } /* else DROP THROUGH */ 40136420Ssklower 40236420Ssklower case PRU_DETACH: /* called from close() */ 40336420Ssklower /* called only after disconnect was called */ 40444424Ssklower if (tpcb->tp_state == TP_LISTENING) { 40544424Ssklower register struct tp_pcb **tt; 40644424Ssklower for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten)) 40744424Ssklower if (*tt == tpcb) 40844424Ssklower break; 40944424Ssklower if (*tt) 41044424Ssklower *tt = tpcb->tp_nextlisten; 41144424Ssklower else { 41244424Ssklower for (tt = &tp_intercepts; *tt; tt = &((*tt)->tp_nextlisten)) 41344424Ssklower if (*tt == tpcb) 41444424Ssklower break; 41544424Ssklower if (*tt) 41644424Ssklower *tt = tpcb->tp_nextlisten; 41744424Ssklower else 41844424Ssklower printf("tp_usrreq - detach: should panic\n"); 41944424Ssklower } 42044424Ssklower } 42144424Ssklower if (tpcb->tp_next) 42244424Ssklower remque(tpcb); 42336420Ssklower error = DoEvent(T_DETACH); 42437469Ssklower if (tpcb->tp_state == TP_CLOSED) { 42537469Ssklower free((caddr_t)tpcb, M_PCB); 42637469Ssklower tpcb = 0; 42737469Ssklower } 42836420Ssklower break; 42936420Ssklower 43036420Ssklower case PRU_SHUTDOWN: 43136420Ssklower /* recv end may have been released; local credit might be zero */ 43236420Ssklower case PRU_DISCONNECT: 43336420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NORMAL_DISC; 43436420Ssklower error = DoEvent(T_DISC_req); 43536420Ssklower break; 43636420Ssklower 43736420Ssklower case PRU_BIND: 43844310Ssklower error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, nam); 43936420Ssklower if (error == 0) { 44037469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 44144310Ssklower tpcb->tp_lsuffix, TP_LOCAL); 44236420Ssklower } 44336420Ssklower break; 44436420Ssklower 44536420Ssklower case PRU_LISTEN: 44644310Ssklower if (tpcb->tp_lsuffixlen == 0) { 44744310Ssklower if (error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL)) 44836420Ssklower break; 44937469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 45044310Ssklower tpcb->tp_lsuffix, TP_LOCAL); 45136420Ssklower } 45244424Ssklower if (tpcb->tp_next == 0) { 45344424Ssklower tpcb->tp_next = tpcb->tp_prev = tpcb; 45444424Ssklower tpcb->tp_nextlisten = tp_listeners; 45544601Ssklower tp_listeners = tpcb; 45644424Ssklower } 45736420Ssklower IFDEBUG(D_TPISO) 45844310Ssklower if (tpcb->tp_state != TP_CLOSED) 45936420Ssklower printf("LISTEN ERROR: state 0x%x\n", tpcb->tp_state); 46036420Ssklower ENDDEBUG 46136420Ssklower error = DoEvent(T_LISTEN_req); 46236420Ssklower break; 46336420Ssklower 46436420Ssklower case PRU_CONNECT2: 46536420Ssklower error = EOPNOTSUPP; /* for unix domain sockets */ 46636420Ssklower break; 46736420Ssklower 46836420Ssklower case PRU_CONNECT: 46936420Ssklower IFTRACE(D_CONN) 47036420Ssklower tptraceTPCB(TPPTmisc, 47137469Ssklower "PRU_CONNECT: so 0x%x *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 47236420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 47336420Ssklower tpcb->tp_class); 47436420Ssklower ENDTRACE 47536420Ssklower IFDEBUG(D_CONN) 47636420Ssklower printf("PRU_CONNECT: so *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 47736420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 47836420Ssklower tpcb->tp_class); 47936420Ssklower ENDDEBUG 48044310Ssklower if (tpcb->tp_lsuffixlen == 0) { 48144310Ssklower if (error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL)) { 48236420Ssklower IFDEBUG(D_CONN) 48344310Ssklower printf("pcbbind returns error 0x%x\n", error); 48436420Ssklower ENDDEBUG 48536420Ssklower break; 48636420Ssklower } 48737469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_lsuffixlen, 48844310Ssklower tpcb->tp_lsuffix, TP_LOCAL); 48937469Ssklower } 49036420Ssklower 49136420Ssklower IFDEBUG(D_CONN) 49236420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 49344310Ssklower dump_buf(tpcb->tp_npcb, 16); 49436420Ssklower ENDDEBUG 49544310Ssklower if (error = tp_route_to(nam, tpcb, /* channel */0)) 49636420Ssklower break; 49736420Ssklower IFDEBUG(D_CONN) 49836420Ssklower printf( 49936420Ssklower "PRU_CONNECT after tpcb 0x%x so 0x%x npcb 0x%x flags 0x%x\n", 50036420Ssklower tpcb, so, tpcb->tp_npcb, tpcb->tp_flags); 50136420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 50244310Ssklower dump_buf(tpcb->tp_npcb, 16); 50336420Ssklower ENDDEBUG 50444310Ssklower if (tpcb->tp_fsuffixlen == 0) { 50536420Ssklower /* didn't set peer extended suffix */ 50637469Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, &tpcb->tp_fsuffixlen, 50744310Ssklower tpcb->tp_fsuffix, TP_FOREIGN); 50836420Ssklower } 50936420Ssklower (void) (tpcb->tp_nlproto->nlp_mtu)(so, so->so_pcb, 51036420Ssklower &tpcb->tp_l_tpdusize, &tpcb->tp_tpdusize, 0); 51144310Ssklower if (tpcb->tp_state == TP_CLOSED) { 51236420Ssklower soisconnecting(so); 51336420Ssklower error = DoEvent(T_CONN_req); 51436420Ssklower } else { 51536420Ssklower (tpcb->tp_nlproto->nlp_pcbdisc)(so->so_pcb); 51636420Ssklower error = EISCONN; 51736420Ssklower } 51836420Ssklower IFPERF(tpcb) 51936420Ssklower u_int lsufx, fsufx; 52039196Ssklower lsufx = *(u_short *)(tpcb->tp_lsuffix); 52139196Ssklower fsufx = *(u_short *)(tpcb->tp_fsuffix); 52236420Ssklower 52344310Ssklower tpmeas(tpcb->tp_lref, 52444310Ssklower TPtime_open | (tpcb->tp_xtd_format << 4), 52536420Ssklower &time, lsufx, fsufx, tpcb->tp_fref); 52636420Ssklower ENDPERF 52736420Ssklower break; 52836420Ssklower 52936420Ssklower case PRU_ACCEPT: 53038841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 53136420Ssklower IFDEBUG(D_REQUEST) 53238841Ssklower printf("ACCEPT PEERADDDR:"); 53338841Ssklower dump_buf(mtod(nam, char *), nam->m_len); 53436420Ssklower ENDDEBUG 53536420Ssklower IFPERF(tpcb) 53636420Ssklower u_int lsufx, fsufx; 53739196Ssklower lsufx = *(u_short *)(tpcb->tp_lsuffix); 53839196Ssklower fsufx = *(u_short *)(tpcb->tp_fsuffix); 53936420Ssklower 54044310Ssklower tpmeas(tpcb->tp_lref, TPtime_open, 54136420Ssklower &time, lsufx, fsufx, tpcb->tp_fref); 54236420Ssklower ENDPERF 54336420Ssklower break; 54436420Ssklower 54536420Ssklower case PRU_RCVD: 54638841Ssklower if (so->so_state & SS_ISCONFIRMING) { 54738841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 54838841Ssklower error = tp_confirm(tpcb); 54938841Ssklower break; 55038841Ssklower } 55136420Ssklower IFTRACE(D_DATA) 55236420Ssklower tptraceTPCB(TPPTmisc, 55336420Ssklower "RCVD BF: lcredit sent_lcdt cc hiwat \n", 55436420Ssklower tpcb->tp_lcredit, tpcb->tp_sent_lcdt, 55536420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 55636420Ssklower LOCAL_CREDIT(tpcb); 55736420Ssklower tptraceTPCB(TPPTmisc, 55836420Ssklower "PRU_RCVD AF sbspace lcredit hiwat cc", 55936420Ssklower sbspace(&so->so_rcv), tpcb->tp_lcredit, 56036420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 56136420Ssklower ENDTRACE 56237469Ssklower IFDEBUG(D_REQUEST) 56337469Ssklower printf("RCVD: cc %d space %d hiwat %d\n", 56437469Ssklower so->so_rcv.sb_cc, sbspace(&so->so_rcv), 56537469Ssklower so->so_rcv.sb_hiwat); 56637469Ssklower ENDDEBUG 56737469Ssklower if (((int)nam) & MSG_OOB) 56837469Ssklower error = DoEvent(T_USR_Xrcvd); 56937469Ssklower else 57037469Ssklower error = DoEvent(T_USR_rcvd); 57136420Ssklower break; 57236420Ssklower 57336420Ssklower case PRU_RCVOOB: 57436420Ssklower if ((so->so_state & SS_ISCONNECTED) == 0) { 57536420Ssklower error = ENOTCONN; 57636420Ssklower break; 57736420Ssklower } 57844310Ssklower if (! tpcb->tp_xpd_service) { 57936420Ssklower error = EOPNOTSUPP; 58036420Ssklower break; 58136420Ssklower } 58236420Ssklower /* kludge - nam is really flags here */ 58336420Ssklower error = tp_rcvoob(tpcb, so, m, outflags, (int)nam); 58436420Ssklower break; 58536420Ssklower 58638841Ssklower case PRU_SEND: 58736420Ssklower case PRU_SENDOOB: 58841924Ssklower if (controlp) { 58941924Ssklower error = tp_snd_control(controlp, so, &m); 59041924Ssklower controlp = NULL; 59141924Ssklower if (error) 59241924Ssklower break; 59341924Ssklower } 59448736Ssklower if ((so->so_state & SS_ISCONFIRMING) && 59548736Ssklower (tpcb->tp_state == TP_CONFIRMING) && 59648736Ssklower (error = tp_confirm(tpcb))) 59748736Ssklower break; 59848736Ssklower if (req == PRU_SENDOOB) { 59948736Ssklower error = (tpcb->tp_xpd_service == 0) ? 60048736Ssklower EOPNOTSUPP : tp_sendoob(tpcb, so, m, outflags); 60138841Ssklower break; 60238841Ssklower } 60337469Ssklower if (m == 0) 60437469Ssklower break; 60548736Ssklower if (m->m_flags & M_EOR) { 60648736Ssklower eotsdu = 1; 60748736Ssklower m->m_flags &= ~M_EOR; 60848736Ssklower } 60948736Ssklower if (eotsdu == 0 && m->m_pkthdr.len == 0) 61036420Ssklower break; 61148736Ssklower if (tpcb->tp_state != TP_AKWAIT && tpcb->tp_state != TP_OPEN) { 61248736Ssklower error = ENOTCONN; 61348736Ssklower break; 61436420Ssklower } 61536420Ssklower /* 61636420Ssklower * The protocol machine copies mbuf chains, 61736420Ssklower * prepends headers, assigns seq numbers, and 61836420Ssklower * puts the packets on the device. 61936420Ssklower * When they are acked they are removed from the socket buf. 62036420Ssklower * 62136420Ssklower * sosend calls this up until sbspace goes negative. 62236420Ssklower * Sbspace may be made negative by appending this mbuf chain, 62336420Ssklower * possibly by a whole cluster. 62436420Ssklower */ 62536420Ssklower { 62637469Ssklower register struct mbuf *n = m; 62736420Ssklower register struct sockbuf *sb = &so->so_snd; 62837469Ssklower int maxsize = tpcb->tp_l_tpdusize 62937469Ssklower - tp_headersize(DT_TPDU_type, tpcb) 63037469Ssklower - (tpcb->tp_use_checksum?4:0) ; 63137469Ssklower int totlen = n->m_pkthdr.len; 63239937Ssklower int mbufcnt = 0; 63339196Ssklower struct mbuf *nn; 63436420Ssklower 63537469Ssklower /* 63637469Ssklower * Could have eotsdu and no data.(presently MUST have 63737469Ssklower * an mbuf though, even if its length == 0) 63837469Ssklower */ 63936420Ssklower IFPERF(tpcb) 64037469Ssklower PStat(tpcb, Nb_from_sess) += totlen; 64136420Ssklower tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0, 64237469Ssklower PStat(tpcb, Nb_from_sess), totlen); 64336420Ssklower ENDPERF 64436420Ssklower IFDEBUG(D_SYSCALL) 64536420Ssklower printf( 64636420Ssklower "PRU_SEND: eot %d before sbappend 0x%x len 0x%x to sb @ 0x%x\n", 64739937Ssklower eotsdu, m, totlen, sb); 64836420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 64936420Ssklower dump_mbuf(m, "m : to be added"); 65036420Ssklower ENDDEBUG 65137469Ssklower /* 65237469Ssklower * Pre-packetize the data in the sockbuf 65337469Ssklower * according to negotiated mtu. Do it here 65437469Ssklower * where we can safely wait for mbufs. 65539196Ssklower * 65639196Ssklower * This presumes knowledge of sockbuf conventions. 65736420Ssklower */ 65839196Ssklower if (n = sb->sb_mb) 65939196Ssklower while (n->m_act) 66039196Ssklower n = n->m_act; 66139647Ssklower if ((nn = n) && n->m_pkthdr.len < maxsize) { 66239937Ssklower u_int space = maxsize - n->m_pkthdr.len; 66339647Ssklower 66439647Ssklower do { 66539647Ssklower if (n->m_flags & M_EOR) 66639647Ssklower goto on1; 66739647Ssklower } while (n->m_next && (n = n->m_next)); 66839937Ssklower if (totlen <= space) { 66939937Ssklower TPNagle1++; 67039196Ssklower n->m_next = m; 67139937Ssklower nn->m_pkthdr.len += totlen; 67239937Ssklower while (n = n->m_next) 67339937Ssklower sballoc(sb, n); 67439196Ssklower if (eotsdu) 67539196Ssklower nn->m_flags |= M_EOR; 67639196Ssklower goto on2; 67739937Ssklower } else { 67839937Ssklower /* 67939937Ssklower * Can't sleep here, because when you wake up 68039937Ssklower * packet you want to attach to may be gone! 68139937Ssklower */ 68239937Ssklower if (TNew && (n->m_next = m_copym(m, 0, space, M_NOWAIT))) { 68339937Ssklower nn->m_pkthdr.len += space; 68439937Ssklower TPNagle2++; 68539937Ssklower while (n = n->m_next) 68639937Ssklower sballoc(sb, n); 68739937Ssklower m_adj(m, space); 68839937Ssklower } 68939196Ssklower } 69039196Ssklower } 69139937Ssklower on1: mbufcnt++; 69239196Ssklower for (n = m; n->m_pkthdr.len > maxsize;) { 69339937Ssklower nn = m_copym(n, 0, maxsize, M_WAIT); 69437469Ssklower sbappendrecord(sb, nn); 69537469Ssklower m_adj(n, maxsize); 69639937Ssklower mbufcnt++; 69737469Ssklower } 69839196Ssklower if (eotsdu) 69939196Ssklower n->m_flags |= M_EOR; 70037469Ssklower sbappendrecord(sb, n); 70139196Ssklower on2: 70239196Ssklower IFTRACE(D_DATA) 70339196Ssklower tptraceTPCB(TPPTmisc, 70439937Ssklower "SEND BF: maxsize totlen mbufcnt eotsdu", 70539937Ssklower maxsize, totlen, mbufcnt, eotsdu); 70639196Ssklower ENDTRACE 70736420Ssklower IFDEBUG(D_SYSCALL) 70839937Ssklower printf("PRU_SEND: eot %d after sbappend 0x%x mbufcnt 0x%x\n", 70939937Ssklower eotsdu, n, mbufcnt); 71036420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 71136420Ssklower ENDDEBUG 71248736Ssklower if (tpcb->tp_state == TP_OPEN) 71348736Ssklower error = DoEvent(T_DATA_req); 71436420Ssklower IFDEBUG(D_SYSCALL) 71536420Ssklower printf("PRU_SEND: after driver error 0x%x \n",error); 71637469Ssklower printf("so_snd 0x%x cc 0t%d mbcnt 0t%d\n", 71737469Ssklower sb, sb->sb_cc, sb->sb_mbcnt); 71837469Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver"); 71936420Ssklower ENDDEBUG 72036420Ssklower } 72136420Ssklower break; 72236420Ssklower 72337469Ssklower case PRU_SOCKADDR: 72437469Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_LOCAL); 72536420Ssklower break; 72636420Ssklower 72736420Ssklower case PRU_PEERADDR: 72838841Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, nam, TP_FOREIGN); 72936420Ssklower break; 73036420Ssklower 73136420Ssklower case PRU_CONTROL: 73236420Ssklower error = EOPNOTSUPP; 73336420Ssklower break; 73436420Ssklower 73536420Ssklower case PRU_PROTOSEND: 73636420Ssklower case PRU_PROTORCV: 73736420Ssklower case PRU_SENSE: 73836420Ssklower case PRU_SLOWTIMO: 73936420Ssklower case PRU_FASTTIMO: 74036420Ssklower error = EOPNOTSUPP; 74136420Ssklower break; 74236420Ssklower 74336420Ssklower default: 74436420Ssklower #ifdef ARGO_DEBUG 74536420Ssklower printf("tp_usrreq UNKNOWN PRU %d\n", req); 74636420Ssklower #endif ARGO_DEBUG 74736420Ssklower error = EOPNOTSUPP; 74836420Ssklower } 74936420Ssklower 75036420Ssklower IFDEBUG(D_REQUEST) 75138841Ssklower printf("%s, so 0x%x, tpcb 0x%x, error %d, state %d\n", 75238841Ssklower "returning from tp_usrreq", so, tpcb, error, 75338841Ssklower tpcb ? 0 : tpcb->tp_state); 75436420Ssklower ENDDEBUG 75536420Ssklower IFTRACE(D_REQUEST) 75636420Ssklower tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m, 75736420Ssklower tpcb?0:tpcb->tp_state); 75836420Ssklower ENDTRACE 75941924Ssklower if (controlp) { 76041924Ssklower m_freem(controlp); 76141924Ssklower printf("control data unexpectedly retained in tp_usrreq()"); 76241924Ssklower } 76336420Ssklower splx(s); 76436420Ssklower return error; 76536420Ssklower } 76639196Ssklower tp_ltrace(so, uio) 76739196Ssklower struct socket *so; 76839196Ssklower struct uio *uio; 76939196Ssklower { 77039196Ssklower IFTRACE(D_DATA) 77139196Ssklower register struct tp_pcb *tpcb = sototpcb(so); 77239196Ssklower if (tpcb) { 77339196Ssklower tptraceTPCB(TPPTmisc, "sosend so resid iovcnt", so, 77439196Ssklower uio->uio_resid, uio->uio_iovcnt, 0); 77539196Ssklower } 77639196Ssklower ENDTRACE 77739196Ssklower } 77837469Ssklower 77938841Ssklower tp_confirm(tpcb) 78038841Ssklower register struct tp_pcb *tpcb; 78137469Ssklower { 78238841Ssklower struct tp_event E; 78338841Ssklower if (tpcb->tp_state == TP_CONFIRMING) 78438841Ssklower return DoEvent(T_ACPT_req); 78538841Ssklower printf("Tp confirm called when not confirming; tpcb 0x%x, state 0x%x\n", 78638841Ssklower tpcb, tpcb->tp_state); 78738841Ssklower return 0; 78837469Ssklower } 78937469Ssklower 79037469Ssklower /* 79137469Ssklower * Process control data sent with sendmsg() 79237469Ssklower */ 79341924Ssklower tp_snd_control(m, so, data) 79441924Ssklower struct mbuf *m; 79537469Ssklower struct socket *so; 79637469Ssklower register struct mbuf **data; 79737469Ssklower { 79842468Ssklower register struct cmsghdr *ch; 79937469Ssklower int error = 0; 80037469Ssklower 80141924Ssklower if (m && m->m_len) { 80242468Ssklower ch = mtod(m, struct cmsghdr *); 80341924Ssklower m->m_len -= sizeof (*ch); 80441924Ssklower m->m_data += sizeof (*ch); 80537469Ssklower error = tp_ctloutput(PRCO_SETOPT, 80637469Ssklower so, ch->cmsg_level, ch->cmsg_type, &m); 80737469Ssklower if (ch->cmsg_type == TPOPT_DISC_DATA) { 80837469Ssklower if (data && *data) { 80937469Ssklower m_freem(*data); 81037469Ssklower *data = 0; 81137469Ssklower } 81241924Ssklower error = tp_usrreq(so, PRU_DISCONNECT, (struct mbuf *)0, 81341924Ssklower (caddr_t)0, (struct mbuf *)0); 81437469Ssklower } 81537469Ssklower } 81641924Ssklower if (m) 81741924Ssklower m_freem(m); 81837469Ssklower return error; 81937469Ssklower } 820