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