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