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