1*36420Ssklower /*********************************************************** 2*36420Ssklower Copyright IBM Corporation 1987 3*36420Ssklower 4*36420Ssklower All Rights Reserved 5*36420Ssklower 6*36420Ssklower Permission to use, copy, modify, and distribute this software and its 7*36420Ssklower documentation for any purpose and without fee is hereby granted, 8*36420Ssklower provided that the above copyright notice appear in all copies and that 9*36420Ssklower both that copyright notice and this permission notice appear in 10*36420Ssklower supporting documentation, and that the name of IBM not be 11*36420Ssklower used in advertising or publicity pertaining to distribution of the 12*36420Ssklower software without specific, written prior permission. 13*36420Ssklower 14*36420Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15*36420Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16*36420Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17*36420Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18*36420Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19*36420Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*36420Ssklower SOFTWARE. 21*36420Ssklower 22*36420Ssklower ******************************************************************/ 23*36420Ssklower 24*36420Ssklower /* 25*36420Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26*36420Ssklower */ 27*36420Ssklower /* 28*36420Ssklower * ARGO TP 29*36420Ssklower * 30*36420Ssklower * $Header: tp_usrreq.c,v 5.4 88/11/18 17:29:18 nhall Exp $ 31*36420Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_usrreq.c,v $ 32*36420Ssklower * 33*36420Ssklower * tp_usrreq(), the fellow that gets called from most of the socket code. 34*36420Ssklower * Pretty straighforward. 35*36420Ssklower * THe only really awful stuff here is the OOB processing, which is done 36*36420Ssklower * wholly here. 37*36420Ssklower * tp_rcvoob() and tp_sendoob() are contained here and called by tp_usrreq(). 38*36420Ssklower */ 39*36420Ssklower 40*36420Ssklower #ifndef lint 41*36420Ssklower static char *rcsid = "$Header: tp_usrreq.c,v 5.4 88/11/18 17:29:18 nhall Exp $"; 42*36420Ssklower #endif lint 43*36420Ssklower 44*36420Ssklower #include "param.h" 45*36420Ssklower #include "systm.h" 46*36420Ssklower #include "dir.h" 47*36420Ssklower #include "user.h" 48*36420Ssklower #include "mbuf.h" 49*36420Ssklower #include "socket.h" 50*36420Ssklower #include "socketvar.h" 51*36420Ssklower #include "domain.h" 52*36420Ssklower #include "protosw.h" 53*36420Ssklower #include "errno.h" 54*36420Ssklower 55*36420Ssklower #include "../netiso/tp_param.h" 56*36420Ssklower #include "../netiso/tp_timer.h" 57*36420Ssklower #include "../netiso/tp_stat.h" 58*36420Ssklower #include "../netiso/tp_seq.h" 59*36420Ssklower #include "../netiso/tp_ip.h" 60*36420Ssklower #include "../netiso/tp_pcb.h" 61*36420Ssklower #include "../netiso/argo_debug.h" 62*36420Ssklower #include "../netiso/tp_trace.h" 63*36420Ssklower #include "../netiso/tp_meas.h" 64*36420Ssklower #include "../netiso/iso.h" 65*36420Ssklower #include "../netiso/iso_errno.h" 66*36420Ssklower 67*36420Ssklower int tp_attach(), tp_driver(); 68*36420Ssklower 69*36420Ssklower #ifdef ARGO_DEBUG 70*36420Ssklower /* 71*36420Ssklower * CALLED FROM: 72*36420Ssklower * anywhere you want to debug... 73*36420Ssklower * FUNCTION and ARGUMENTS: 74*36420Ssklower * print (str) followed by the control info in the mbufs of an mbuf chain (n) 75*36420Ssklower */ 76*36420Ssklower void 77*36420Ssklower dump_mbuf(n, str) 78*36420Ssklower struct mbuf *n; 79*36420Ssklower char *str; 80*36420Ssklower { 81*36420Ssklower struct mbuf *nextrecord; 82*36420Ssklower 83*36420Ssklower printf("dump %s\n", str); 84*36420Ssklower 85*36420Ssklower if( n == MNULL) { 86*36420Ssklower printf("EMPTY:\n"); 87*36420Ssklower return; 88*36420Ssklower } 89*36420Ssklower 90*36420Ssklower for(;n;) { 91*36420Ssklower nextrecord = n->m_act; 92*36420Ssklower printf("RECORD:\n"); 93*36420Ssklower while (n) { 94*36420Ssklower printf("%x : Len %x Of %x A %x Nx %x Tp %x\n", 95*36420Ssklower n, n->m_len, n->m_off, n->m_act, n->m_next, n->m_type); 96*36420Ssklower #ifdef notdef 97*36420Ssklower { 98*36420Ssklower register char *p = mtod(n, char *); 99*36420Ssklower register int i; 100*36420Ssklower 101*36420Ssklower printf("data: "); 102*36420Ssklower for(i=0; i < n->m_len; i++ ) { 103*36420Ssklower if(i%8 == 0) 104*36420Ssklower printf("\n"); 105*36420Ssklower printf("0x%x ", *(p+i)); 106*36420Ssklower } 107*36420Ssklower printf("\n"); 108*36420Ssklower } 109*36420Ssklower #endif notdef 110*36420Ssklower if( n->m_next == n ) { 111*36420Ssklower printf("LOOP!\n"); 112*36420Ssklower return; 113*36420Ssklower } 114*36420Ssklower n = n->m_next; 115*36420Ssklower } 116*36420Ssklower n = nextrecord; 117*36420Ssklower } 118*36420Ssklower printf("\n"); 119*36420Ssklower } 120*36420Ssklower 121*36420Ssklower #endif ARGO_DEBUG 122*36420Ssklower 123*36420Ssklower /* 124*36420Ssklower * CALLED FROM: 125*36420Ssklower * tp_usrreq(), PRU_RCVOOB 126*36420Ssklower * FUNCTION and ARGUMENTS: 127*36420Ssklower * Copy data from the expedited data socket buffer into 128*36420Ssklower * the pre-allocated mbuf m. 129*36420Ssklower * There is an isomorphism between XPD TPDUs and expedited data TSDUs. 130*36420Ssklower * XPD tpdus are limited to 16 bytes of data so they fit in one mbuf. 131*36420Ssklower * RETURN VALUE: 132*36420Ssklower * EINVAL if debugging is on and a disaster has occurred 133*36420Ssklower * ENOTCONN if the socket isn't connected 134*36420Ssklower * EWOULDBLOCK if the socket is in non-blocking mode and there's no 135*36420Ssklower * xpd data in the buffer 136*36420Ssklower * E* whatever is returned from the fsm. 137*36420Ssklower */ 138*36420Ssklower static int 139*36420Ssklower tp_rcvoob(tpcb, so, m, outflags, inflags) 140*36420Ssklower struct tp_pcb *tpcb; 141*36420Ssklower register struct socket *so; 142*36420Ssklower register struct mbuf *m; 143*36420Ssklower int *outflags; 144*36420Ssklower int inflags; 145*36420Ssklower { 146*36420Ssklower register struct mbuf *n; 147*36420Ssklower register struct sockbuf *sb = &tpcb->tp_Xrcv; 148*36420Ssklower struct tp_event E; 149*36420Ssklower int error = 0; 150*36420Ssklower 151*36420Ssklower IFDEBUG(D_XPD) 152*36420Ssklower printf("PRU_RCVOOB, sostate 0x%x\n", so->so_state); 153*36420Ssklower ENDDEBUG 154*36420Ssklower 155*36420Ssklower /* if you use soreceive */ 156*36420Ssklower if (m==MNULL) 157*36420Ssklower return ENOBUFS; 158*36420Ssklower 159*36420Ssklower restart: 160*36420Ssklower sblock(sb); 161*36420Ssklower 162*36420Ssklower if ((((so->so_state & SS_ISCONNECTED) == 0) 163*36420Ssklower || (so->so_state & SS_ISDISCONNECTING) != 0) && 164*36420Ssklower (so->so_proto->pr_flags & PR_CONNREQUIRED)) { 165*36420Ssklower return ENOTCONN; 166*36420Ssklower } 167*36420Ssklower 168*36420Ssklower if ( sb->sb_cc == 0) { 169*36420Ssklower ASSERT( (tpcb->tp_flags & TPF_DISC_DATA_IN) == 0 ); 170*36420Ssklower IFDEBUG(D_XPD) 171*36420Ssklower printf("RCVOOB: empty queue!\n"); 172*36420Ssklower ENDDEBUG 173*36420Ssklower if (so->so_state & SS_NBIO) { 174*36420Ssklower return EWOULDBLOCK; 175*36420Ssklower } 176*36420Ssklower sbunlock(sb); 177*36420Ssklower sbwait(sb); 178*36420Ssklower goto restart; 179*36420Ssklower } 180*36420Ssklower /* Take the first mbuf off the chain. 181*36420Ssklower * Each XPD TPDU gives you a complete TSDU so the chains don't get 182*36420Ssklower * coalesced, but one TSDU may span several mbufs. 183*36420Ssklower * Nevertheless, since n should have a most 16 bytes, it 184*36420Ssklower * will fit into m. (size was checked in tp_input() ) 185*36420Ssklower */ 186*36420Ssklower 187*36420Ssklower n = sb->sb_mb; 188*36420Ssklower ASSERT((n->m_type == TPMT_DATA) || 189*36420Ssklower n->m_type == TPMT_IPHDR || n->m_type == TPMT_TPHDR); 190*36420Ssklower 191*36420Ssklower /* 192*36420Ssklower * mtod doesn't work for cluster-type mbufs, hence this disaster check: 193*36420Ssklower */ 194*36420Ssklower if( n->m_off > MMAXOFF ) 195*36420Ssklower panic("tp_rcvoob: unexpected cluster "); 196*36420Ssklower 197*36420Ssklower m->m_next = MNULL; 198*36420Ssklower m->m_act = MNULL; 199*36420Ssklower m->m_off = MMINOFF; 200*36420Ssklower m->m_len = 0; 201*36420Ssklower 202*36420Ssklower /* Assuming at most one xpd tpdu is in the buffer at once */ 203*36420Ssklower while ( n != MNULL ) { 204*36420Ssklower m->m_len += n->m_len; 205*36420Ssklower bcopy(mtod(n, caddr_t), mtod(m, caddr_t), n->m_len); 206*36420Ssklower m->m_off += n->m_len; /* so mtod() in bcopy() above gives right addr */ 207*36420Ssklower n = n->m_next; 208*36420Ssklower } 209*36420Ssklower m->m_off = MMINOFF; /* restore it to its proper value */ 210*36420Ssklower 211*36420Ssklower IFDEBUG(D_XPD) 212*36420Ssklower printf("tp_rcvoob: xpdlen 0x%x\n", m->m_len); 213*36420Ssklower dump_mbuf(so->so_rcv.sb_mb, "RCVOOB: Rcv socketbuf"); 214*36420Ssklower dump_mbuf(sb->sb_mb, "RCVOOB: Xrcv socketbuf"); 215*36420Ssklower ENDDEBUG 216*36420Ssklower 217*36420Ssklower if( (inflags & MSG_PEEK) == 0 ) 218*36420Ssklower sbdrop(sb, m->m_len); 219*36420Ssklower 220*36420Ssklower release: 221*36420Ssklower sbunlock(sb); 222*36420Ssklower 223*36420Ssklower IFTRACE(D_XPD) 224*36420Ssklower tptraceTPCB(TPPTmisc, "PRU_RCVOOB @ release sb_cc m_len", 225*36420Ssklower tpcb->tp_Xrcv.sb_cc, m->m_len,0,0 ); 226*36420Ssklower ENDTRACE 227*36420Ssklower if(outflags) 228*36420Ssklower *outflags = MSG_OOB | MSG_EOTSDU | inflags; /* always on xpd recv */ 229*36420Ssklower if (error == 0) 230*36420Ssklower error = DoEvent(T_USR_Xrcvd); 231*36420Ssklower return error; 232*36420Ssklower } 233*36420Ssklower 234*36420Ssklower /* 235*36420Ssklower * CALLED FROM: 236*36420Ssklower * tp_usrreq(), PRU_SENDOOB 237*36420Ssklower * FUNCTION and ARGUMENTS: 238*36420Ssklower * Send what's in the mbuf chain (m) as an XPD TPDU. 239*36420Ssklower * The mbuf may not contain more then 16 bytes of data. 240*36420Ssklower * XPD TSDUs aren't segmented, so they translate into 241*36420Ssklower * exactly one XPD TPDU, with EOT bit set. 242*36420Ssklower * RETURN VALUE: 243*36420Ssklower * EWOULDBLOCK if socket is in non-blocking mode and the previous 244*36420Ssklower * xpd data haven't been acked yet. 245*36420Ssklower * EMSGSIZE if trying to send > max-xpd bytes (16) 246*36420Ssklower * ENOBUFS if ran out of mbufs 247*36420Ssklower */ 248*36420Ssklower static int 249*36420Ssklower tp_sendoob(tpcb, so, xdata, outflags) 250*36420Ssklower struct tp_pcb *tpcb; 251*36420Ssklower register struct socket *so; 252*36420Ssklower register struct mbuf *xdata; 253*36420Ssklower int *outflags; /* not used */ 254*36420Ssklower { 255*36420Ssklower /* 256*36420Ssklower * Each mbuf chain represents a sequence # in the XPD seq space. 257*36420Ssklower * The first one in the queue has sequence # tp_Xuna. 258*36420Ssklower * When we add to the XPD queue, we stuff a zero-length 259*36420Ssklower * mbuf (mark) into the DATA queue, with its sequence number in m_next 260*36420Ssklower * to be assigned to this XPD tpdu, so data xfer can stop 261*36420Ssklower * when it reaches the zero-length mbuf if this XPD TPDU hasn't 262*36420Ssklower * yet been acknowledged. 263*36420Ssklower */ 264*36420Ssklower register struct sockbuf *sb = &(tpcb->tp_Xsnd); 265*36420Ssklower register struct mbuf *xmark; 266*36420Ssklower register int len=0; 267*36420Ssklower struct tp_event E; 268*36420Ssklower 269*36420Ssklower IFDEBUG(D_XPD) 270*36420Ssklower printf("tp_sendoob:"); 271*36420Ssklower if(xdata) 272*36420Ssklower printf("xdata len 0x%x\n", xdata->m_len); 273*36420Ssklower ENDDEBUG 274*36420Ssklower oob_again: 275*36420Ssklower /* DO NOT LOCK the Xsnd buffer!!!! You can have at MOST one 276*36420Ssklower * socket buf locked at any time!!! (otherwise you might 277*36420Ssklower * sleep() in sblock() w/ a signal pending and cause the 278*36420Ssklower * system call to be aborted w/ a locked socketbuf, which 279*36420Ssklower * is a problem. So the so_snd buffer lock 280*36420Ssklower * (done in sosend()) serves as the lock for Xpd. 281*36420Ssklower */ 282*36420Ssklower if (sb->sb_mb) { /* anything already in this sockbuf? */ 283*36420Ssklower if (so->so_state & SS_NBIO) { 284*36420Ssklower return EWOULDBLOCK; 285*36420Ssklower } 286*36420Ssklower sbunlock(&so->so_snd); 287*36420Ssklower sbwait(&so->so_snd); 288*36420Ssklower sblock(&so->so_snd); 289*36420Ssklower goto oob_again; 290*36420Ssklower } 291*36420Ssklower 292*36420Ssklower if (xdata == (struct mbuf *)0) { 293*36420Ssklower /* empty xpd packet */ 294*36420Ssklower MGET(xdata, M_WAIT, TPMT_DATA); 295*36420Ssklower if (xdata == NULL) { 296*36420Ssklower return ENOBUFS; 297*36420Ssklower } 298*36420Ssklower xdata->m_len = 0; 299*36420Ssklower xdata->m_act = MNULL; 300*36420Ssklower } 301*36420Ssklower IFDEBUG(D_XPD) 302*36420Ssklower printf("tp_sendoob 1:"); 303*36420Ssklower if(xdata) 304*36420Ssklower printf("xdata len 0x%x\n", xdata->m_len); 305*36420Ssklower ENDDEBUG 306*36420Ssklower xmark = xdata; /* temporary use of variable xmark */ 307*36420Ssklower while (xmark) { 308*36420Ssklower len += xmark->m_len; 309*36420Ssklower xmark = xmark->m_next; 310*36420Ssklower } 311*36420Ssklower if (len > TP_MAX_XPD_DATA) { 312*36420Ssklower return EMSGSIZE; 313*36420Ssklower } 314*36420Ssklower IFDEBUG(D_XPD) 315*36420Ssklower printf("tp_sendoob 2:"); 316*36420Ssklower if(xdata) 317*36420Ssklower printf("xdata len 0x%x\n", len); 318*36420Ssklower ENDDEBUG 319*36420Ssklower 320*36420Ssklower /* stick an xpd mark in the normal data queue 321*36420Ssklower * make sure we have enough mbufs before we stick anything into any queues 322*36420Ssklower */ 323*36420Ssklower MGET(xmark,M_WAIT, TPMT_XPD); 324*36420Ssklower if (xmark == MNULL) { 325*36420Ssklower return ENOBUFS; 326*36420Ssklower } 327*36420Ssklower xmark->m_len = 0; 328*36420Ssklower xmark->m_act = MNULL; 329*36420Ssklower 330*36420Ssklower { /* stash the xpd sequence number in the mark */ 331*36420Ssklower SeqNum *Xuna = mtod(xmark, SeqNum *); 332*36420Ssklower *Xuna = tpcb->tp_Xuna; 333*36420Ssklower } 334*36420Ssklower 335*36420Ssklower IFTRACE(D_XPD) 336*36420Ssklower tptraceTPCB(TPPTmisc, "XPD mark m_next ", xmark->m_next, 0, 0, 0); 337*36420Ssklower ENDTRACE 338*36420Ssklower 339*36420Ssklower sbappendrecord(&so->so_snd, xmark); /* the mark */ 340*36420Ssklower sbappendrecord(sb, xdata); 341*36420Ssklower 342*36420Ssklower IFDEBUG(D_XPD) 343*36420Ssklower printf("tp_sendoob len 0x%x\n", len); 344*36420Ssklower dump_mbuf(so->so_snd.sb_mb, "XPD request Regular sndbuf:"); 345*36420Ssklower dump_mbuf(tpcb->tp_Xsnd.sb_mb, "XPD request Xsndbuf:"); 346*36420Ssklower ENDDEBUG 347*36420Ssklower u.u_r.r_val1 += len; 348*36420Ssklower return DoEvent(T_XPD_req); 349*36420Ssklower 350*36420Ssklower } 351*36420Ssklower 352*36420Ssklower /* 353*36420Ssklower * CALLED FROM: 354*36420Ssklower * the socket routines 355*36420Ssklower * FUNCTION and ARGUMENTS: 356*36420Ssklower * Handles all "user requests" except the [gs]ockopts() requests. 357*36420Ssklower * The argument (req) is the request type (PRU*), 358*36420Ssklower * (m) is an mbuf chain, generally used for send and 359*36420Ssklower * receive type requests only. 360*36420Ssklower * (nam) is used for addresses usually, in particular for the bind request. 361*36420Ssklower * 362*36420Ssklower * The last argument (rights in most usrreq()s) has been stolen for 363*36420Ssklower * returning flags values. Since rights can't be passed around w/ tp, 364*36420Ssklower * this field is used only for RCVOOB user requests, and is assumed 365*36420Ssklower * to be either 0 (as soreceive() would have it) or a ptr to the int flags 366*36420Ssklower * (as recvv()'s version of soreceive() would have it 367*36420Ssklower */ 368*36420Ssklower /*ARGSUSED*/ 369*36420Ssklower ProtoHook 370*36420Ssklower tp_usrreq(so, req, m, nam, rightsp, outflags) 371*36420Ssklower struct socket *so; 372*36420Ssklower u_int req; 373*36420Ssklower struct mbuf *m, *nam, *rightsp /* not used */; 374*36420Ssklower int *outflags; 375*36420Ssklower { 376*36420Ssklower register struct tp_pcb *tpcb = sototpcb(so); 377*36420Ssklower int s = splnet(); 378*36420Ssklower int error = 0; 379*36420Ssklower u_long eotsdu = 0; 380*36420Ssklower struct tp_event E; 381*36420Ssklower 382*36420Ssklower IFDEBUG(D_REQUEST) 383*36420Ssklower printf("usrreq(0x%x,%d,0x%x,0x%x,0x%x)\n",so,req,m,nam,outflags); 384*36420Ssklower if(so->so_error) 385*36420Ssklower printf("WARNING!!! so->so_error is 0x%x\n", so->so_error); 386*36420Ssklower ENDDEBUG 387*36420Ssklower IFTRACE(D_REQUEST) 388*36420Ssklower tptraceTPCB(TPPTusrreq, "req so m state [", req, so, m, 389*36420Ssklower tpcb?tpcb->tp_state:0); 390*36420Ssklower ENDTRACE 391*36420Ssklower 392*36420Ssklower if ((u_int)tpcb == 0 && req != PRU_ATTACH) { 393*36420Ssklower IFTRACE(D_REQUEST) 394*36420Ssklower tptraceTPCB(TPPTusrreq, "req failed NO TPCB[", 0, 0, 0, 0); 395*36420Ssklower ENDTRACE 396*36420Ssklower splx(s); 397*36420Ssklower return ENOTCONN; 398*36420Ssklower } 399*36420Ssklower 400*36420Ssklower 401*36420Ssklower IFDEBUG(D_XPD) 402*36420Ssklower extern struct mbuf *mfree; 403*36420Ssklower struct mbuf *m = mfree, *n=MNULL; 404*36420Ssklower 405*36420Ssklower if ( (u_int) tpcb != 0 ) { 406*36420Ssklower n = tpcb->tp_Xrcv.sb_mb; 407*36420Ssklower if(n) while(m) { 408*36420Ssklower if(m == n) { 409*36420Ssklower printf("enter usrreq %d Xrcv sb_mb 0x%x is on freelist!\n", 410*36420Ssklower req, n); 411*36420Ssklower } 412*36420Ssklower m = m->m_next; 413*36420Ssklower } 414*36420Ssklower } 415*36420Ssklower ENDDEBUG 416*36420Ssklower 417*36420Ssklower switch (req) { 418*36420Ssklower 419*36420Ssklower case PRU_ATTACH: 420*36420Ssklower if (tpcb) { 421*36420Ssklower error = EISCONN; 422*36420Ssklower break; 423*36420Ssklower } 424*36420Ssklower if( error = tp_attach(so, so->so_proto->pr_domain->dom_family ) ) 425*36420Ssklower break; 426*36420Ssklower tpcb = sototpcb(so); 427*36420Ssklower break; 428*36420Ssklower 429*36420Ssklower case PRU_ABORT: /* called from close() */ 430*36420Ssklower /* called for each incoming connect queued on the 431*36420Ssklower * parent (accepting) socket 432*36420Ssklower */ 433*36420Ssklower if( tpcb->tp_state == TP_OPEN ) { 434*36420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NO_SESSION; 435*36420Ssklower error = DoEvent(T_DISC_req); /* pretend it was a close() */ 436*36420Ssklower break; 437*36420Ssklower } /* else DROP THROUGH */ 438*36420Ssklower 439*36420Ssklower case PRU_DETACH: /* called from close() */ 440*36420Ssklower /* called only after disconnect was called */ 441*36420Ssklower error = DoEvent(T_DETACH); 442*36420Ssklower break; 443*36420Ssklower 444*36420Ssklower case PRU_SHUTDOWN: 445*36420Ssklower /* recv end may have been released; local credit might be zero */ 446*36420Ssklower case PRU_DISCONNECT: 447*36420Ssklower E.ATTR(T_DISC_req).e_reason = E_TP_NORMAL_DISC; 448*36420Ssklower error = DoEvent(T_DISC_req); 449*36420Ssklower break; 450*36420Ssklower 451*36420Ssklower case PRU_BIND: 452*36420Ssklower error = (tpcb->tp_nlproto->nlp_pcbbind)( so->so_pcb, nam ); 453*36420Ssklower if (error == 0) { 454*36420Ssklower tpcb->tp_lsuffixlen = sizeof(short); /* default */ 455*36420Ssklower *(u_short *)(tpcb->tp_lsuffix) = (u_short) 456*36420Ssklower (tpcb->tp_nlproto->nlp_getsufx)( so->so_pcb, TP_LOCAL ); 457*36420Ssklower } 458*36420Ssklower break; 459*36420Ssklower 460*36420Ssklower case PRU_LISTEN: 461*36420Ssklower if ( *SHORT_LSUFXP(tpcb) == (short)0 ) { 462*36420Ssklower /* note: this suffix is independent of the extended suffix */ 463*36420Ssklower if( error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL) ) 464*36420Ssklower break; 465*36420Ssklower } 466*36420Ssklower if( tpcb->tp_lsuffixlen == 0) { 467*36420Ssklower tpcb->tp_lsuffixlen = sizeof(short); /* default */ 468*36420Ssklower *SHORT_LSUFXP(tpcb) = (short) 469*36420Ssklower (tpcb->tp_nlproto->nlp_getsufx)( so->so_pcb, TP_LOCAL ); 470*36420Ssklower } 471*36420Ssklower IFDEBUG(D_TPISO) 472*36420Ssklower if(tpcb->tp_state != TP_CLOSED) 473*36420Ssklower printf("LISTEN ERROR: state 0x%x\n", tpcb->tp_state); 474*36420Ssklower ENDDEBUG 475*36420Ssklower error = DoEvent(T_LISTEN_req); 476*36420Ssklower break; 477*36420Ssklower 478*36420Ssklower case PRU_CONNECT2: 479*36420Ssklower error = EOPNOTSUPP; /* for unix domain sockets */ 480*36420Ssklower break; 481*36420Ssklower 482*36420Ssklower case PRU_CONNECT: 483*36420Ssklower IFTRACE(D_CONN) 484*36420Ssklower tptraceTPCB(TPPTmisc, 485*36420Ssklower "PRU_CONNECT: so *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 486*36420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 487*36420Ssklower tpcb->tp_class); 488*36420Ssklower ENDTRACE 489*36420Ssklower IFDEBUG(D_CONN) 490*36420Ssklower printf("PRU_CONNECT: so *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 491*36420Ssklower tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 492*36420Ssklower tpcb->tp_class); 493*36420Ssklower ENDDEBUG 494*36420Ssklower if (*SHORT_LSUFXP(tpcb) == (short)0) { 495*36420Ssklower /* no bind was done */ 496*36420Ssklower /* note: this suffix is independent of the extended suffix */ 497*36420Ssklower if( error = (tpcb->tp_nlproto->nlp_pcbbind)(so->so_pcb, MNULL) ) { 498*36420Ssklower IFDEBUG(D_CONN) 499*36420Ssklower printf("pcbbind returns error 0x%x\n", error ); 500*36420Ssklower ENDDEBUG 501*36420Ssklower break; 502*36420Ssklower } 503*36420Ssklower } 504*36420Ssklower if (tpcb->tp_lsuffixlen == 0) { 505*36420Ssklower /* didn't set an extended suffix */ 506*36420Ssklower tpcb->tp_lsuffixlen = sizeof(short); 507*36420Ssklower *SHORT_LSUFXP(tpcb) = (short) 508*36420Ssklower (tpcb->tp_nlproto->nlp_getsufx)( so->so_pcb, TP_LOCAL ); 509*36420Ssklower } 510*36420Ssklower 511*36420Ssklower IFDEBUG(D_CONN) 512*36420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 513*36420Ssklower dump_buf( tpcb->tp_npcb, 16); 514*36420Ssklower ENDDEBUG 515*36420Ssklower if( error = tp_route_to( nam, tpcb, /* channel */0) ) 516*36420Ssklower break; 517*36420Ssklower IFDEBUG(D_CONN) 518*36420Ssklower printf( 519*36420Ssklower "PRU_CONNECT after tpcb 0x%x so 0x%x npcb 0x%x flags 0x%x\n", 520*36420Ssklower tpcb, so, tpcb->tp_npcb, tpcb->tp_flags); 521*36420Ssklower printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 522*36420Ssklower dump_buf( tpcb->tp_npcb, 16); 523*36420Ssklower ENDDEBUG 524*36420Ssklower if( tpcb->tp_fsuffixlen == 0 ) { 525*36420Ssklower /* didn't set peer extended suffix */ 526*36420Ssklower tpcb->tp_fsuffixlen = sizeof(short); 527*36420Ssklower *SHORT_FSUFXP(tpcb) = (short) 528*36420Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, TP_FOREIGN); 529*36420Ssklower } 530*36420Ssklower (void) (tpcb->tp_nlproto->nlp_mtu)(so, so->so_pcb, 531*36420Ssklower &tpcb->tp_l_tpdusize, &tpcb->tp_tpdusize, 0); 532*36420Ssklower if( tpcb->tp_state == TP_CLOSED) { 533*36420Ssklower soisconnecting(so); 534*36420Ssklower error = DoEvent(T_CONN_req); 535*36420Ssklower } else { 536*36420Ssklower (tpcb->tp_nlproto->nlp_pcbdisc)(so->so_pcb); 537*36420Ssklower error = EISCONN; 538*36420Ssklower } 539*36420Ssklower IFPERF(tpcb) 540*36420Ssklower u_int lsufx, fsufx; 541*36420Ssklower lsufx = *(u_int *)(tpcb->tp_lsuffix); 542*36420Ssklower fsufx = *(u_int *)(tpcb->tp_fsuffix); 543*36420Ssklower 544*36420Ssklower tpmeas( tpcb->tp_lref, 545*36420Ssklower TPtime_open | (tpcb->tp_xtd_format <<4 ), 546*36420Ssklower &time, lsufx, fsufx, tpcb->tp_fref); 547*36420Ssklower ENDPERF 548*36420Ssklower break; 549*36420Ssklower 550*36420Ssklower case PRU_ACCEPT: 551*36420Ssklower /* all this garbage is to keep accept from returning 552*36420Ssklower * before the 3-way handshake is done in class 4. 553*36420Ssklower * it'll have to be modified for other classes 554*36420Ssklower */ 555*36420Ssklower IFDEBUG(D_REQUEST) 556*36420Ssklower printf("PRU_ACCEPT so_error 0x%x\n", so->so_error); 557*36420Ssklower ENDDEBUG 558*36420Ssklower so->so_error = 0; 559*36420Ssklower if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTED)== 0) { 560*36420Ssklower error = EWOULDBLOCK; 561*36420Ssklower break; 562*36420Ssklower } 563*36420Ssklower while ((so->so_state & SS_ISCONNECTED) == 0 && so->so_error == 0) { 564*36420Ssklower sleep((caddr_t)&so->so_timeo, PZERO+1); 565*36420Ssklower } 566*36420Ssklower if (so->so_error) { 567*36420Ssklower error = so->so_error; 568*36420Ssklower } else { 569*36420Ssklower struct sockaddr *sa = mtod(nam, struct sockaddr *); 570*36420Ssklower 571*36420Ssklower nam->m_len = sizeof (struct sockaddr); 572*36420Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, sa, TP_FOREIGN); 573*36420Ssklower 574*36420Ssklower switch(sa->sa_family = sototpcb(so)->tp_domain) { 575*36420Ssklower case AF_INET: 576*36420Ssklower satosin(sa)->sin_port = 577*36420Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, TP_FOREIGN); 578*36420Ssklower break; 579*36420Ssklower case AF_ISO: 580*36420Ssklower satosiso(sa)->siso_tsuffix = 581*36420Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, TP_FOREIGN); 582*36420Ssklower /* doesn't cover the case where the suffix is extended - 583*36420Ssklower * grotesque - the user *has* to do the getsockopt */ 584*36420Ssklower break; 585*36420Ssklower } 586*36420Ssklower IFDEBUG(D_REQUEST) 587*36420Ssklower printf("ACCEPT PEERADDDR:"); 588*36420Ssklower dump_buf(sa, sizeof(struct sockaddr)); 589*36420Ssklower ENDDEBUG 590*36420Ssklower } 591*36420Ssklower IFPERF(tpcb) 592*36420Ssklower u_int lsufx, fsufx; 593*36420Ssklower lsufx = *(u_int *)(tpcb->tp_lsuffix); 594*36420Ssklower fsufx = *(u_int *)(tpcb->tp_fsuffix); 595*36420Ssklower 596*36420Ssklower tpmeas( tpcb->tp_lref, TPtime_open, 597*36420Ssklower &time, lsufx, fsufx, tpcb->tp_fref); 598*36420Ssklower ENDPERF 599*36420Ssklower break; 600*36420Ssklower 601*36420Ssklower case PRU_RCVD: 602*36420Ssklower IFTRACE(D_DATA) 603*36420Ssklower tptraceTPCB(TPPTmisc, 604*36420Ssklower "RCVD BF: lcredit sent_lcdt cc hiwat \n", 605*36420Ssklower tpcb->tp_lcredit, tpcb->tp_sent_lcdt, 606*36420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 607*36420Ssklower LOCAL_CREDIT(tpcb); 608*36420Ssklower tptraceTPCB(TPPTmisc, 609*36420Ssklower "PRU_RCVD AF sbspace lcredit hiwat cc", 610*36420Ssklower sbspace(&so->so_rcv), tpcb->tp_lcredit, 611*36420Ssklower so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 612*36420Ssklower ENDTRACE 613*36420Ssklower error = DoEvent(T_USR_rcvd); 614*36420Ssklower break; 615*36420Ssklower 616*36420Ssklower case PRU_RCVOOB: 617*36420Ssklower if ((so->so_state & SS_ISCONNECTED) == 0) { 618*36420Ssklower error = ENOTCONN; 619*36420Ssklower break; 620*36420Ssklower } 621*36420Ssklower if( ! tpcb->tp_xpd_service ) { 622*36420Ssklower error = EOPNOTSUPP; 623*36420Ssklower break; 624*36420Ssklower } 625*36420Ssklower /* kludge - nam is really flags here */ 626*36420Ssklower error = tp_rcvoob(tpcb, so, m, outflags, (int)nam); 627*36420Ssklower break; 628*36420Ssklower 629*36420Ssklower case PRU_SENDOOB: 630*36420Ssklower if ((so->so_state & SS_ISCONNECTED) == 0) { 631*36420Ssklower error = ENOTCONN; 632*36420Ssklower break; 633*36420Ssklower } 634*36420Ssklower if( ! tpcb->tp_xpd_service ) { 635*36420Ssklower error = EOPNOTSUPP; 636*36420Ssklower break; 637*36420Ssklower } 638*36420Ssklower error = tp_sendoob(tpcb, so, m, outflags); 639*36420Ssklower break; 640*36420Ssklower 641*36420Ssklower case PRU_SENDEOT: 642*36420Ssklower eotsdu = 1; 643*36420Ssklower /* fall through */ 644*36420Ssklower case PRU_SEND: 645*36420Ssklower /* 646*36420Ssklower * The protocol machine copies mbuf chains, 647*36420Ssklower * prepends headers, assigns seq numbers, and 648*36420Ssklower * puts the packets on the device. 649*36420Ssklower * When they are acked they are removed from the socket buf. 650*36420Ssklower * 651*36420Ssklower * sosend calls this up until sbspace goes negative. 652*36420Ssklower * Sbspace may be made negative by appending this mbuf chain, 653*36420Ssklower * possibly by a whole cluster. 654*36420Ssklower */ 655*36420Ssklower if ((so->so_state & SS_ISCONNECTED) == 0) { 656*36420Ssklower error = ENOTCONN; 657*36420Ssklower break; 658*36420Ssklower } 659*36420Ssklower { 660*36420Ssklower register struct mbuf *n; 661*36420Ssklower register int len=0; 662*36420Ssklower register struct sockbuf *sb = &so->so_snd; 663*36420Ssklower 664*36420Ssklower n = m; 665*36420Ssklower while (n) { /* Could have eotsdu and no data.(presently MUST have 666*36420Ssklower * an mbuf though, even if its length == 0) 667*36420Ssklower */ 668*36420Ssklower len += n->m_len; 669*36420Ssklower if( n->m_next == MNULL && eotsdu ) { 670*36420Ssklower CHANGE_MTYPE(n, TPMT_EOT); 671*36420Ssklower } 672*36420Ssklower n = n->m_next; 673*36420Ssklower } 674*36420Ssklower IFPERF(tpcb) 675*36420Ssklower PStat(tpcb, Nb_from_sess) += len; 676*36420Ssklower tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0, 677*36420Ssklower PStat(tpcb, Nb_from_sess), len); 678*36420Ssklower ENDPERF 679*36420Ssklower IFDEBUG(D_SYSCALL) 680*36420Ssklower printf( 681*36420Ssklower "PRU_SEND: eot %d before sbappend 0x%x len 0x%x to sb @ 0x%x\n", 682*36420Ssklower eotsdu, m,len, &sb->sb_mb); 683*36420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 684*36420Ssklower dump_mbuf(m, "m : to be added"); 685*36420Ssklower ENDDEBUG 686*36420Ssklower /* The last mbuf has type TPMT_EOT so it will never be compressed 687*36420Ssklower * with TPMT_DATA mbufs, but if this was an EOTSDU request w/o 688*36420Ssklower * any data, the only way to keep this mbuf from being thrown 689*36420Ssklower * away is to link it through the m_act field 690*36420Ssklower * We are ASSUMING that if there are any data at all with this 691*36420Ssklower * request, the last mbuf will be non-empty!!! 692*36420Ssklower */ 693*36420Ssklower if( m->m_type == TPMT_EOT ) /* first mbuf in chain is EOT? */ 694*36420Ssklower sbappendrecord(sb, m); /* to keep 2 TPMT_EOTs from being 695*36420Ssklower compressed */ 696*36420Ssklower else 697*36420Ssklower sbappend(sb, m); 698*36420Ssklower IFDEBUG(D_SYSCALL) 699*36420Ssklower printf("PRU_SEND: eot %d after sbappend 0x%x len 0x%x\n", 700*36420Ssklower eotsdu, m,len); 701*36420Ssklower dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 702*36420Ssklower ENDDEBUG 703*36420Ssklower u.u_r.r_val1 += len; 704*36420Ssklower error = DoEvent(T_DATA_req); 705*36420Ssklower IFDEBUG(D_SYSCALL) 706*36420Ssklower printf("PRU_SEND: after driver error 0x%x \n",error); 707*36420Ssklower ENDDEBUG 708*36420Ssklower } 709*36420Ssklower break; 710*36420Ssklower 711*36420Ssklower case PRU_SOCKADDR: { 712*36420Ssklower struct sockaddr *sa = mtod(nam, struct sockaddr *); 713*36420Ssklower 714*36420Ssklower nam->m_len = sizeof (struct sockaddr); 715*36420Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, sa, TP_LOCAL); 716*36420Ssklower switch ( sa->sa_family = sototpcb(so)->tp_domain ) { 717*36420Ssklower case AF_INET: 718*36420Ssklower satosin(sa)->sin_port = 719*36420Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, TP_LOCAL); 720*36420Ssklower break; 721*36420Ssklower case AF_ISO: 722*36420Ssklower satosiso(sa)->siso_tsuffix = 723*36420Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, TP_LOCAL); 724*36420Ssklower break; 725*36420Ssklower } 726*36420Ssklower } 727*36420Ssklower break; 728*36420Ssklower 729*36420Ssklower case PRU_PEERADDR: 730*36420Ssklower if( (so->so_state & SS_ISCONNECTED) && 731*36420Ssklower (so->so_state & SS_ISDISCONNECTING) == 0) { 732*36420Ssklower struct sockaddr *sa = mtod(nam, struct sockaddr *); 733*36420Ssklower 734*36420Ssklower nam->m_len = sizeof (struct sockaddr); 735*36420Ssklower 736*36420Ssklower (tpcb->tp_nlproto->nlp_getnetaddr)(so->so_pcb, sa, TP_FOREIGN); 737*36420Ssklower 738*36420Ssklower switch ( sa->sa_family = sototpcb(so)->tp_domain ) { 739*36420Ssklower case AF_INET: 740*36420Ssklower satosin(sa)->sin_port = 741*36420Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, TP_FOREIGN); 742*36420Ssklower break; 743*36420Ssklower case AF_ISO: 744*36420Ssklower satosiso(sa)->siso_tsuffix = 745*36420Ssklower (tpcb->tp_nlproto->nlp_getsufx)(so->so_pcb, TP_FOREIGN); 746*36420Ssklower break; 747*36420Ssklower } 748*36420Ssklower IFDEBUG(D_REQUEST) 749*36420Ssklower printf("PEERADDDR:"); 750*36420Ssklower dump_buf(sa, sizeof(struct sockaddr)); 751*36420Ssklower ENDDEBUG 752*36420Ssklower } else 753*36420Ssklower error = ENOTCONN; 754*36420Ssklower break; 755*36420Ssklower 756*36420Ssklower case PRU_CONTROL: 757*36420Ssklower error = EOPNOTSUPP; 758*36420Ssklower break; 759*36420Ssklower 760*36420Ssklower case PRU_PROTOSEND: 761*36420Ssklower case PRU_PROTORCV: 762*36420Ssklower case PRU_SENSE: 763*36420Ssklower case PRU_SLOWTIMO: 764*36420Ssklower case PRU_FASTTIMO: 765*36420Ssklower error = EOPNOTSUPP; 766*36420Ssklower break; 767*36420Ssklower 768*36420Ssklower default: 769*36420Ssklower #ifdef ARGO_DEBUG 770*36420Ssklower printf("tp_usrreq UNKNOWN PRU %d\n", req); 771*36420Ssklower #endif ARGO_DEBUG 772*36420Ssklower error = EOPNOTSUPP; 773*36420Ssklower } 774*36420Ssklower 775*36420Ssklower IFDEBUG(D_REQUEST) 776*36420Ssklower printf("returning from tp_usrreq(so 0x%x) error 0x%x\n", so, error); 777*36420Ssklower ENDDEBUG 778*36420Ssklower IFTRACE(D_REQUEST) 779*36420Ssklower tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m, 780*36420Ssklower tpcb?0:tpcb->tp_state); 781*36420Ssklower ENDTRACE 782*36420Ssklower splx(s); 783*36420Ssklower return error; 784*36420Ssklower } 785