|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1988, 1990 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: * @(#)uipc_socket2.c 7.17 (Berkeley) 5/4/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "systm.h" ! 38: #include "proc.h" ! 39: #include "file.h" ! 40: #include "buf.h" ! 41: #include "malloc.h" ! 42: #include "mbuf.h" ! 43: #include "protosw.h" ! 44: #include "socket.h" ! 45: #include "socketvar.h" ! 46: ! 47: /* ! 48: * Primitive routines for operating on sockets and socket buffers ! 49: */ ! 50: ! 51: /* strings for sleep message: */ ! 52: char netio[] = "netio"; ! 53: char netcon[] = "netcon"; ! 54: char netcls[] = "netcls"; ! 55: ! 56: u_long sb_max = SB_MAX; /* patchable */ ! 57: ! 58: /* ! 59: * Procedures to manipulate state flags of socket ! 60: * and do appropriate wakeups. Normal sequence from the ! 61: * active (originating) side is that soisconnecting() is ! 62: * called during processing of connect() call, ! 63: * resulting in an eventual call to soisconnected() if/when the ! 64: * connection is established. When the connection is torn down ! 65: * soisdisconnecting() is called during processing of disconnect() call, ! 66: * and soisdisconnected() is called when the connection to the peer ! 67: * is totally severed. The semantics of these routines are such that ! 68: * connectionless protocols can call soisconnected() and soisdisconnected() ! 69: * only, bypassing the in-progress calls when setting up a ``connection'' ! 70: * takes no time. ! 71: * ! 72: * From the passive side, a socket is created with ! 73: * two queues of sockets: so_q0 for connections in progress ! 74: * and so_q for connections already made and awaiting user acceptance. ! 75: * As a protocol is preparing incoming connections, it creates a socket ! 76: * structure queued on so_q0 by calling sonewconn(). When the connection ! 77: * is established, soisconnected() is called, and transfers the ! 78: * socket structure to so_q, making it available to accept(). ! 79: * ! 80: * If a socket is closed with sockets on either ! 81: * so_q0 or so_q, these sockets are dropped. ! 82: * ! 83: * If higher level protocols are implemented in ! 84: * the kernel, the wakeups done here will sometimes ! 85: * cause software-interrupt process scheduling. ! 86: */ ! 87: ! 88: soisconnecting(so) ! 89: register struct socket *so; ! 90: { ! 91: ! 92: so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); ! 93: so->so_state |= SS_ISCONNECTING; ! 94: } ! 95: ! 96: soisconnected(so) ! 97: register struct socket *so; ! 98: { ! 99: register struct socket *head = so->so_head; ! 100: ! 101: so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING); ! 102: so->so_state |= SS_ISCONNECTED; ! 103: if (head && soqremque(so, 0)) { ! 104: soqinsque(head, so, 1); ! 105: sorwakeup(head); ! 106: wakeup((caddr_t)&head->so_timeo); ! 107: } else { ! 108: wakeup((caddr_t)&so->so_timeo); ! 109: sorwakeup(so); ! 110: sowwakeup(so); ! 111: } ! 112: } ! 113: ! 114: soisdisconnecting(so) ! 115: register struct socket *so; ! 116: { ! 117: ! 118: so->so_state &= ~SS_ISCONNECTING; ! 119: so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); ! 120: wakeup((caddr_t)&so->so_timeo); ! 121: sowwakeup(so); ! 122: sorwakeup(so); ! 123: } ! 124: ! 125: soisdisconnected(so) ! 126: register struct socket *so; ! 127: { ! 128: ! 129: so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); ! 130: so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); ! 131: wakeup((caddr_t)&so->so_timeo); ! 132: sowwakeup(so); ! 133: sorwakeup(so); ! 134: } ! 135: ! 136: /* ! 137: * When an attempt at a new connection is noted on a socket ! 138: * which accepts connections, sonewconn is called. If the ! 139: * connection is possible (subject to space constraints, etc.) ! 140: * then we allocate a new structure, propoerly linked into the ! 141: * data structure of the original socket, and return this. ! 142: * Connstatus may be 0, or SO_ISCONFIRMING, or SO_ISCONNECTED. ! 143: * ! 144: * Currently, sonewconn() is defined as sonewconn1() in socketvar.h ! 145: * to catch calls that are missing the (new) second parameter. ! 146: */ ! 147: struct socket * ! 148: sonewconn1(head, connstatus) ! 149: register struct socket *head; ! 150: int connstatus; ! 151: { ! 152: register struct socket *so; ! 153: int soqueue = connstatus ? 1 : 0; ! 154: ! 155: if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2) ! 156: return ((struct socket *)0); ! 157: MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_DONTWAIT); ! 158: if (so == NULL) ! 159: return ((struct socket *)0); ! 160: bzero((caddr_t)so, sizeof(*so)); ! 161: so->so_type = head->so_type; ! 162: so->so_options = head->so_options &~ SO_ACCEPTCONN; ! 163: so->so_linger = head->so_linger; ! 164: so->so_state = head->so_state | SS_NOFDREF; ! 165: so->so_proto = head->so_proto; ! 166: so->so_timeo = head->so_timeo; ! 167: so->so_pgid = head->so_pgid; ! 168: (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat); ! 169: soqinsque(head, so, soqueue); ! 170: if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, ! 171: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) { ! 172: (void) soqremque(so, soqueue); ! 173: (void) free((caddr_t)so, M_SOCKET); ! 174: return ((struct socket *)0); ! 175: } ! 176: if (connstatus) { ! 177: sorwakeup(head); ! 178: wakeup((caddr_t)&head->so_timeo); ! 179: so->so_state |= connstatus; ! 180: } ! 181: return (so); ! 182: } ! 183: ! 184: soqinsque(head, so, q) ! 185: register struct socket *head, *so; ! 186: int q; ! 187: { ! 188: ! 189: register struct socket **prev; ! 190: so->so_head = head; ! 191: if (q == 0) { ! 192: head->so_q0len++; ! 193: so->so_q0 = 0; ! 194: for (prev = &(head->so_q0); *prev; ) ! 195: prev = &((*prev)->so_q0); ! 196: } else { ! 197: head->so_qlen++; ! 198: so->so_q = 0; ! 199: for (prev = &(head->so_q); *prev; ) ! 200: prev = &((*prev)->so_q); ! 201: } ! 202: *prev = so; ! 203: } ! 204: ! 205: soqremque(so, q) ! 206: register struct socket *so; ! 207: int q; ! 208: { ! 209: register struct socket *head, *prev, *next; ! 210: ! 211: head = so->so_head; ! 212: prev = head; ! 213: for (;;) { ! 214: next = q ? prev->so_q : prev->so_q0; ! 215: if (next == so) ! 216: break; ! 217: if (next == 0) ! 218: return (0); ! 219: prev = next; ! 220: } ! 221: if (q == 0) { ! 222: prev->so_q0 = next->so_q0; ! 223: head->so_q0len--; ! 224: } else { ! 225: prev->so_q = next->so_q; ! 226: head->so_qlen--; ! 227: } ! 228: next->so_q0 = next->so_q = 0; ! 229: next->so_head = 0; ! 230: return (1); ! 231: } ! 232: ! 233: /* ! 234: * Socantsendmore indicates that no more data will be sent on the ! 235: * socket; it would normally be applied to a socket when the user ! 236: * informs the system that no more data is to be sent, by the protocol ! 237: * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data ! 238: * will be received, and will normally be applied to the socket by a ! 239: * protocol when it detects that the peer will send no more data. ! 240: * Data queued for reading in the socket may yet be read. ! 241: */ ! 242: ! 243: socantsendmore(so) ! 244: struct socket *so; ! 245: { ! 246: ! 247: so->so_state |= SS_CANTSENDMORE; ! 248: sowwakeup(so); ! 249: } ! 250: ! 251: socantrcvmore(so) ! 252: struct socket *so; ! 253: { ! 254: ! 255: so->so_state |= SS_CANTRCVMORE; ! 256: sorwakeup(so); ! 257: } ! 258: ! 259: /* ! 260: * Socket select/wakeup routines. ! 261: */ ! 262: ! 263: /* ! 264: * Queue a process for a select on a socket buffer. ! 265: */ ! 266: sbselqueue(sb, cp) ! 267: struct sockbuf *sb; ! 268: struct proc *cp; ! 269: { ! 270: struct proc *p; ! 271: ! 272: if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait) ! 273: sb->sb_flags |= SB_COLL; ! 274: else { ! 275: sb->sb_sel = cp; ! 276: sb->sb_flags |= SB_SEL; ! 277: } ! 278: } ! 279: ! 280: /* ! 281: * Wait for data to arrive at/drain from a socket buffer. ! 282: */ ! 283: sbwait(sb) ! 284: struct sockbuf *sb; ! 285: { ! 286: ! 287: sb->sb_flags |= SB_WAIT; ! 288: return (tsleep((caddr_t)&sb->sb_cc, ! 289: (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, netio, ! 290: sb->sb_timeo)); ! 291: } ! 292: ! 293: /* ! 294: * Lock a sockbuf already known to be locked; ! 295: * return any error returned from sleep (EINTR). ! 296: */ ! 297: sb_lock(sb) ! 298: register struct sockbuf *sb; ! 299: { ! 300: int error; ! 301: ! 302: while (sb->sb_flags & SB_LOCK) { ! 303: sb->sb_flags |= SB_WANT; ! 304: if (error = tsleep((caddr_t)&sb->sb_flags, ! 305: (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK|PCATCH, ! 306: netio, 0)) ! 307: return (error); ! 308: } ! 309: sb->sb_flags |= SB_LOCK; ! 310: return (0); ! 311: } ! 312: ! 313: /* ! 314: * Wakeup processes waiting on a socket buffer. ! 315: * Do asynchronous notification via SIGIO ! 316: * if the socket has the SS_ASYNC flag set. ! 317: */ ! 318: sowakeup(so, sb) ! 319: register struct socket *so; ! 320: register struct sockbuf *sb; ! 321: { ! 322: struct proc *p; ! 323: ! 324: if (sb->sb_sel) { ! 325: selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); ! 326: sb->sb_sel = 0; ! 327: sb->sb_flags &= ~(SB_SEL|SB_COLL); ! 328: } ! 329: if (sb->sb_flags & SB_WAIT) { ! 330: sb->sb_flags &= ~SB_WAIT; ! 331: wakeup((caddr_t)&sb->sb_cc); ! 332: } ! 333: if (so->so_state & SS_ASYNC) { ! 334: if (so->so_pgid < 0) ! 335: gsignal(-so->so_pgid, SIGIO); ! 336: else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0) ! 337: psignal(p, SIGIO); ! 338: } ! 339: } ! 340: ! 341: /* ! 342: * Socket buffer (struct sockbuf) utility routines. ! 343: * ! 344: * Each socket contains two socket buffers: one for sending data and ! 345: * one for receiving data. Each buffer contains a queue of mbufs, ! 346: * information about the number of mbufs and amount of data in the ! 347: * queue, and other fields allowing select() statements and notification ! 348: * on data availability to be implemented. ! 349: * ! 350: * Data stored in a socket buffer is maintained as a list of records. ! 351: * Each record is a list of mbufs chained together with the m_next ! 352: * field. Records are chained together with the m_nextpkt field. The upper ! 353: * level routine soreceive() expects the following conventions to be ! 354: * observed when placing information in the receive buffer: ! 355: * ! 356: * 1. If the protocol requires each message be preceded by the sender's ! 357: * name, then a record containing that name must be present before ! 358: * any associated data (mbuf's must be of type MT_SONAME). ! 359: * 2. If the protocol supports the exchange of ``access rights'' (really ! 360: * just additional data associated with the message), and there are ! 361: * ``rights'' to be received, then a record containing this data ! 362: * should be present (mbuf's must be of type MT_RIGHTS). ! 363: * 3. If a name or rights record exists, then it must be followed by ! 364: * a data record, perhaps of zero length. ! 365: * ! 366: * Before using a new socket structure it is first necessary to reserve ! 367: * buffer space to the socket, by calling sbreserve(). This should commit ! 368: * some of the available buffer space in the system buffer pool for the ! 369: * socket (currently, it does nothing but enforce limits). The space ! 370: * should be released by calling sbrelease() when the socket is destroyed. ! 371: */ ! 372: ! 373: soreserve(so, sndcc, rcvcc) ! 374: register struct socket *so; ! 375: u_long sndcc, rcvcc; ! 376: { ! 377: ! 378: if (sbreserve(&so->so_snd, sndcc) == 0) ! 379: goto bad; ! 380: if (sbreserve(&so->so_rcv, rcvcc) == 0) ! 381: goto bad2; ! 382: if (so->so_rcv.sb_lowat == 0) ! 383: so->so_rcv.sb_lowat = 1; ! 384: if (so->so_snd.sb_lowat == 0) ! 385: so->so_snd.sb_lowat = MCLBYTES; ! 386: if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) ! 387: so->so_snd.sb_lowat = so->so_snd.sb_hiwat; ! 388: return (0); ! 389: bad2: ! 390: sbrelease(&so->so_snd); ! 391: bad: ! 392: return (ENOBUFS); ! 393: } ! 394: ! 395: /* ! 396: * Allot mbufs to a sockbuf. ! 397: * Attempt to scale mbmax so that mbcnt doesn't become limiting ! 398: * if buffering efficiency is near the normal case. ! 399: */ ! 400: sbreserve(sb, cc) ! 401: struct sockbuf *sb; ! 402: u_long cc; ! 403: { ! 404: ! 405: if (cc > sb_max * MCLBYTES / (MSIZE + MCLBYTES)) ! 406: return (0); ! 407: sb->sb_hiwat = cc; ! 408: sb->sb_mbmax = min(cc * 2, sb_max); ! 409: if (sb->sb_lowat > sb->sb_hiwat) ! 410: sb->sb_lowat = sb->sb_hiwat; ! 411: return (1); ! 412: } ! 413: ! 414: /* ! 415: * Free mbufs held by a socket, and reserved mbuf space. ! 416: */ ! 417: sbrelease(sb) ! 418: struct sockbuf *sb; ! 419: { ! 420: ! 421: sbflush(sb); ! 422: sb->sb_hiwat = sb->sb_mbmax = 0; ! 423: } ! 424: ! 425: /* ! 426: * Routines to add and remove ! 427: * data from an mbuf queue. ! 428: * ! 429: * The routines sbappend() or sbappendrecord() are normally called to ! 430: * append new mbufs to a socket buffer, after checking that adequate ! 431: * space is available, comparing the function sbspace() with the amount ! 432: * of data to be added. sbappendrecord() differs from sbappend() in ! 433: * that data supplied is treated as the beginning of a new record. ! 434: * To place a sender's address, optional access rights, and data in a ! 435: * socket receive buffer, sbappendaddr() should be used. To place ! 436: * access rights and data in a socket receive buffer, sbappendrights() ! 437: * should be used. In either case, the new data begins a new record. ! 438: * Note that unlike sbappend() and sbappendrecord(), these routines check ! 439: * for the caller that there will be enough space to store the data. ! 440: * Each fails if there is not enough space, or if it cannot find mbufs ! 441: * to store additional information in. ! 442: * ! 443: * Reliable protocols may use the socket send buffer to hold data ! 444: * awaiting acknowledgement. Data is normally copied from a socket ! 445: * send buffer in a protocol with m_copy for output to a peer, ! 446: * and then removing the data from the socket buffer with sbdrop() ! 447: * or sbdroprecord() when the data is acknowledged by the peer. ! 448: */ ! 449: ! 450: /* ! 451: * Append mbuf chain m to the last record in the ! 452: * socket buffer sb. The additional space associated ! 453: * the mbuf chain is recorded in sb. Empty mbufs are ! 454: * discarded and mbufs are compacted where possible. ! 455: */ ! 456: sbappend(sb, m) ! 457: struct sockbuf *sb; ! 458: struct mbuf *m; ! 459: { ! 460: register struct mbuf *n; ! 461: ! 462: if (m == 0) ! 463: return; ! 464: if (n = sb->sb_mb) { ! 465: while (n->m_nextpkt) ! 466: n = n->m_nextpkt; ! 467: do { ! 468: if (n->m_flags & M_EOR) { ! 469: sbappendrecord(sb, m); /* XXXXXX!!!! */ ! 470: return; ! 471: } ! 472: } while (n->m_next && (n = n->m_next)); ! 473: } ! 474: sbcompress(sb, m, n); ! 475: } ! 476: ! 477: #ifdef SOCKBUF_DEBUG ! 478: sbcheck(sb) ! 479: register struct sockbuf *sb; ! 480: { ! 481: register struct mbuf *m; ! 482: register int len = 0, mbcnt = 0; ! 483: ! 484: for (m = sb->sb_mb; m; m = m->m_next) { ! 485: len += m->m_len; ! 486: mbcnt += MSIZE; ! 487: if (m->m_flags & M_EXT) ! 488: mbcnt += m->m_ext.ext_size; ! 489: if (m->m_nextpkt) ! 490: panic("sbcheck nextpkt"); ! 491: } ! 492: if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) { ! 493: printf("cc %d != %d || mbcnt %d != %d\n", len, sb->sb_cc, ! 494: mbcnt, sb->sb_mbcnt); ! 495: panic("sbcheck"); ! 496: } ! 497: } ! 498: #endif ! 499: ! 500: /* ! 501: * As above, except the mbuf chain ! 502: * begins a new record. ! 503: */ ! 504: sbappendrecord(sb, m0) ! 505: register struct sockbuf *sb; ! 506: register struct mbuf *m0; ! 507: { ! 508: register struct mbuf *m; ! 509: ! 510: if (m0 == 0) ! 511: return; ! 512: if (m = sb->sb_mb) ! 513: while (m->m_nextpkt) ! 514: m = m->m_nextpkt; ! 515: /* ! 516: * Put the first mbuf on the queue. ! 517: * Note this permits zero length records. ! 518: */ ! 519: sballoc(sb, m0); ! 520: if (m) ! 521: m->m_nextpkt = m0; ! 522: else ! 523: sb->sb_mb = m0; ! 524: m = m0->m_next; ! 525: m0->m_next = 0; ! 526: if (m && (m0->m_flags & M_EOR)) { ! 527: m0->m_flags &= ~M_EOR; ! 528: m->m_flags |= M_EOR; ! 529: } ! 530: sbcompress(sb, m, m0); ! 531: } ! 532: ! 533: /* ! 534: * As above except that OOB data ! 535: * is inserted at the beginning of the sockbuf, ! 536: * but after any other OOB data. ! 537: */ ! 538: sbinsertoob(sb, m0) ! 539: register struct sockbuf *sb; ! 540: register struct mbuf *m0; ! 541: { ! 542: register struct mbuf *m; ! 543: register struct mbuf **mp; ! 544: ! 545: if (m0 == 0) ! 546: return; ! 547: for (mp = &sb->sb_mb; m = *mp; mp = &((*mp)->m_nextpkt)) { ! 548: again: ! 549: switch (m->m_type) { ! 550: ! 551: case MT_OOBDATA: ! 552: continue; /* WANT next train */ ! 553: ! 554: case MT_CONTROL: ! 555: if (m = m->m_next) ! 556: goto again; /* inspect THIS train further */ ! 557: } ! 558: break; ! 559: } ! 560: /* ! 561: * Put the first mbuf on the queue. ! 562: * Note this permits zero length records. ! 563: */ ! 564: sballoc(sb, m0); ! 565: m0->m_nextpkt = *mp; ! 566: *mp = m0; ! 567: m = m0->m_next; ! 568: m0->m_next = 0; ! 569: if (m && (m0->m_flags & M_EOR)) { ! 570: m0->m_flags &= ~M_EOR; ! 571: m->m_flags |= M_EOR; ! 572: } ! 573: sbcompress(sb, m, m0); ! 574: } ! 575: ! 576: /* ! 577: * Append address and data, and optionally, control (ancillary) data ! 578: * to the receive queue of a socket. If present, ! 579: * m0 must include a packet header with total length. ! 580: * Returns 0 if no space in sockbuf or insufficient mbufs. ! 581: */ ! 582: sbappendaddr(sb, asa, m0, control) ! 583: register struct sockbuf *sb; ! 584: struct sockaddr *asa; ! 585: struct mbuf *m0, *control; ! 586: { ! 587: register struct mbuf *m, *n; ! 588: int space = asa->sa_len; ! 589: ! 590: if (m0 && (m0->m_flags & M_PKTHDR) == 0) ! 591: panic("sbappendaddr"); ! 592: if (m0) ! 593: space += m0->m_pkthdr.len; ! 594: for (n = control; n; n = n->m_next) { ! 595: space += n->m_len; ! 596: if (n->m_next == 0) /* keep pointer to last control buf */ ! 597: break; ! 598: } ! 599: if (space > sbspace(sb)) ! 600: return (0); ! 601: if (asa->sa_len > MLEN) ! 602: return (0); ! 603: MGET(m, M_DONTWAIT, MT_SONAME); ! 604: if (m == 0) ! 605: return (0); ! 606: m->m_len = asa->sa_len; ! 607: bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len); ! 608: if (n) ! 609: n->m_next = m0; /* concatenate data to control */ ! 610: else ! 611: control = m0; ! 612: m->m_next = control; ! 613: for (n = m; n; n = n->m_next) ! 614: sballoc(sb, n); ! 615: if (n = sb->sb_mb) { ! 616: while (n->m_nextpkt) ! 617: n = n->m_nextpkt; ! 618: n->m_nextpkt = m; ! 619: } else ! 620: sb->sb_mb = m; ! 621: return (1); ! 622: } ! 623: ! 624: sbappendcontrol(sb, m0, control) ! 625: struct sockbuf *sb; ! 626: struct mbuf *control, *m0; ! 627: { ! 628: register struct mbuf *m, *n; ! 629: int space = 0; ! 630: ! 631: if (control == 0) ! 632: panic("sbappendcontrol"); ! 633: for (m = control; ; m = m->m_next) { ! 634: space += m->m_len; ! 635: if (m->m_next == 0) ! 636: break; ! 637: } ! 638: n = m; /* save pointer to last control buffer */ ! 639: for (m = m0; m; m = m->m_next) ! 640: space += m->m_len; ! 641: if (space > sbspace(sb)) ! 642: return (0); ! 643: n->m_next = m0; /* concatenate data to control */ ! 644: for (m = control; m; m = m->m_next) ! 645: sballoc(sb, m); ! 646: if (n = sb->sb_mb) { ! 647: while (n->m_nextpkt) ! 648: n = n->m_nextpkt; ! 649: n->m_nextpkt = control; ! 650: } else ! 651: sb->sb_mb = control; ! 652: return (1); ! 653: } ! 654: ! 655: /* ! 656: * Compress mbuf chain m into the socket ! 657: * buffer sb following mbuf n. If n ! 658: * is null, the buffer is presumed empty. ! 659: */ ! 660: sbcompress(sb, m, n) ! 661: register struct sockbuf *sb; ! 662: register struct mbuf *m, *n; ! 663: { ! 664: register int eor = 0; ! 665: register struct mbuf *o; ! 666: ! 667: while (m) { ! 668: eor |= m->m_flags & M_EOR; ! 669: if (m->m_len == 0 && ! 670: (eor == 0 || ! 671: (((o = m->m_next) || (o = n)) && ! 672: o->m_type == m->m_type))) { ! 673: m = m_free(m); ! 674: continue; ! 675: } ! 676: if (n && (n->m_flags & (M_EXT | M_EOR)) == 0 && ! 677: (n->m_data + n->m_len + m->m_len) < &n->m_dat[MLEN] && ! 678: n->m_type == m->m_type) { ! 679: bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, ! 680: (unsigned)m->m_len); ! 681: n->m_len += m->m_len; ! 682: sb->sb_cc += m->m_len; ! 683: m = m_free(m); ! 684: continue; ! 685: } ! 686: if (n) ! 687: n->m_next = m; ! 688: else ! 689: sb->sb_mb = m; ! 690: sballoc(sb, m); ! 691: n = m; ! 692: m->m_flags &= ~M_EOR; ! 693: m = m->m_next; ! 694: n->m_next = 0; ! 695: } ! 696: if (eor) { ! 697: if (n) ! 698: n->m_flags |= eor; ! 699: else ! 700: printf("semi-panic: sbcompress\n"); ! 701: } ! 702: } ! 703: ! 704: /* ! 705: * Free all mbufs in a sockbuf. ! 706: * Check that all resources are reclaimed. ! 707: */ ! 708: sbflush(sb) ! 709: register struct sockbuf *sb; ! 710: { ! 711: ! 712: if (sb->sb_flags & SB_LOCK) ! 713: panic("sbflush"); ! 714: while (sb->sb_mbcnt) ! 715: sbdrop(sb, (int)sb->sb_cc); ! 716: if (sb->sb_cc || sb->sb_mb) ! 717: panic("sbflush 2"); ! 718: } ! 719: ! 720: /* ! 721: * Drop data from (the front of) a sockbuf. ! 722: */ ! 723: sbdrop(sb, len) ! 724: register struct sockbuf *sb; ! 725: register int len; ! 726: { ! 727: register struct mbuf *m, *mn; ! 728: struct mbuf *next; ! 729: ! 730: next = (m = sb->sb_mb) ? m->m_nextpkt : 0; ! 731: while (len > 0) { ! 732: if (m == 0) { ! 733: if (next == 0) ! 734: panic("sbdrop"); ! 735: m = next; ! 736: next = m->m_nextpkt; ! 737: continue; ! 738: } ! 739: if (m->m_len > len) { ! 740: m->m_len -= len; ! 741: m->m_data += len; ! 742: sb->sb_cc -= len; ! 743: break; ! 744: } ! 745: len -= m->m_len; ! 746: sbfree(sb, m); ! 747: MFREE(m, mn); ! 748: m = mn; ! 749: } ! 750: while (m && m->m_len == 0) { ! 751: sbfree(sb, m); ! 752: MFREE(m, mn); ! 753: m = mn; ! 754: } ! 755: if (m) { ! 756: sb->sb_mb = m; ! 757: m->m_nextpkt = next; ! 758: } else ! 759: sb->sb_mb = next; ! 760: } ! 761: ! 762: /* ! 763: * Drop a record off the front of a sockbuf ! 764: * and move the next record to the front. ! 765: */ ! 766: sbdroprecord(sb) ! 767: register struct sockbuf *sb; ! 768: { ! 769: register struct mbuf *m, *mn; ! 770: ! 771: m = sb->sb_mb; ! 772: if (m) { ! 773: sb->sb_mb = m->m_nextpkt; ! 774: do { ! 775: sbfree(sb, m); ! 776: MFREE(m, mn); ! 777: } while (m = mn); ! 778: } ! 779: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.