root/kern/uipc_socket2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. soisconnecting
  2. soisconnected
  3. soisdisconnecting
  4. soisdisconnected
  5. sonewconn
  6. soqinsque
  7. soqremque
  8. socantsendmore
  9. socantrcvmore
  10. sbwait
  11. sb_lock
  12. sowakeup
  13. soreserve
  14. sbreserve
  15. sbcheckreserve
  16. sbrelease
  17. sblastrecordchk
  18. sblastmbufchk
  19. sbappend
  20. sbappendstream
  21. sbcheck
  22. sbappendrecord
  23. sbinsertoob
  24. sbappendaddr
  25. sbappendcontrol
  26. sbcompress
  27. sbflush
  28. sbdrop
  29. sbdroprecord
  30. sbcreatecontrol

    1 /*      $OpenBSD: uipc_socket2.c,v 1.42 2007/02/26 23:53:33 kurt Exp $  */
    2 /*      $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $       */
    3 
    4 /*
    5  * Copyright (c) 1982, 1986, 1988, 1990, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  *      @(#)uipc_socket2.c      8.1 (Berkeley) 6/10/93
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/proc.h>
   38 #include <sys/file.h>
   39 #include <sys/buf.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mbuf.h>
   42 #include <sys/protosw.h>
   43 #include <sys/socket.h>
   44 #include <sys/socketvar.h>
   45 #include <sys/signalvar.h>
   46 #include <sys/event.h>
   47 
   48 /*
   49  * Primitive routines for operating on sockets and socket buffers
   50  */
   51 
   52 /* strings for sleep message: */
   53 const char      netcon[] = "netcon";
   54 const char      netcls[] = "netcls";
   55 const char      netio[] = "netio";
   56 const char      netlck[] = "netlck";
   57 
   58 u_long  sb_max = SB_MAX;                /* patchable */
   59 
   60 /*
   61  * Procedures to manipulate state flags of socket
   62  * and do appropriate wakeups.  Normal sequence from the
   63  * active (originating) side is that soisconnecting() is
   64  * called during processing of connect() call,
   65  * resulting in an eventual call to soisconnected() if/when the
   66  * connection is established.  When the connection is torn down
   67  * soisdisconnecting() is called during processing of disconnect() call,
   68  * and soisdisconnected() is called when the connection to the peer
   69  * is totally severed.  The semantics of these routines are such that
   70  * connectionless protocols can call soisconnected() and soisdisconnected()
   71  * only, bypassing the in-progress calls when setting up a ``connection''
   72  * takes no time.
   73  *
   74  * From the passive side, a socket is created with
   75  * two queues of sockets: so_q0 for connections in progress
   76  * and so_q for connections already made and awaiting user acceptance.
   77  * As a protocol is preparing incoming connections, it creates a socket
   78  * structure queued on so_q0 by calling sonewconn().  When the connection
   79  * is established, soisconnected() is called, and transfers the
   80  * socket structure to so_q, making it available to accept().
   81  *
   82  * If a socket is closed with sockets on either
   83  * so_q0 or so_q, these sockets are dropped.
   84  *
   85  * If higher level protocols are implemented in
   86  * the kernel, the wakeups done here will sometimes
   87  * cause software-interrupt process scheduling.
   88  */
   89 
   90 void
   91 soisconnecting(struct socket *so)
   92 {
   93 
   94         so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
   95         so->so_state |= SS_ISCONNECTING;
   96 }
   97 
   98 void
   99 soisconnected(struct socket *so)
  100 {
  101         struct socket *head = so->so_head;
  102 
  103         so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
  104         so->so_state |= SS_ISCONNECTED;
  105         if (head && soqremque(so, 0)) {
  106                 soqinsque(head, so, 1);
  107                 sorwakeup(head);
  108                 wakeup_one(&head->so_timeo);
  109         } else {
  110                 wakeup(&so->so_timeo);
  111                 sorwakeup(so);
  112                 sowwakeup(so);
  113         }
  114 }
  115 
  116 void
  117 soisdisconnecting(struct socket *so)
  118 {
  119 
  120         so->so_state &= ~SS_ISCONNECTING;
  121         so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
  122         wakeup(&so->so_timeo);
  123         sowwakeup(so);
  124         sorwakeup(so);
  125 }
  126 
  127 void
  128 soisdisconnected(struct socket *so)
  129 {
  130 
  131         so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
  132         so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED);
  133         wakeup(&so->so_timeo);
  134         sowwakeup(so);
  135         sorwakeup(so);
  136 }
  137 
  138 /*
  139  * When an attempt at a new connection is noted on a socket
  140  * which accepts connections, sonewconn is called.  If the
  141  * connection is possible (subject to space constraints, etc.)
  142  * then we allocate a new structure, properly linked into the
  143  * data structure of the original socket, and return this.
  144  * Connstatus may be 0, or SS_ISCONFIRMING, or SS_ISCONNECTED.
  145  *
  146  * Must be called at splsoftnet()
  147  */
  148 struct socket *
  149 sonewconn(struct socket *head, int connstatus)
  150 {
  151         struct socket *so;
  152         int soqueue = connstatus ? 1 : 0;
  153         extern u_long unpst_sendspace, unpst_recvspace;
  154         u_long snd_sb_hiwat, rcv_sb_hiwat;
  155 
  156         splassert(IPL_SOFTNET);
  157 
  158         if (mclpool.pr_nout > mclpool.pr_hardlimit * 95 / 100)
  159                 return ((struct socket *)0);
  160         if (head->so_qlen + head->so_q0len > head->so_qlimit * 3)
  161                 return ((struct socket *)0);
  162         so = pool_get(&socket_pool, PR_NOWAIT);
  163         if (so == NULL)
  164                 return ((struct socket *)0);
  165         bzero(so, sizeof(*so));
  166         so->so_type = head->so_type;
  167         so->so_options = head->so_options &~ SO_ACCEPTCONN;
  168         so->so_linger = head->so_linger;
  169         so->so_state = head->so_state | SS_NOFDREF;
  170         so->so_proto = head->so_proto;
  171         so->so_timeo = head->so_timeo;
  172         so->so_pgid = head->so_pgid;
  173         so->so_euid = head->so_euid;
  174         so->so_ruid = head->so_ruid;
  175         so->so_egid = head->so_egid;
  176         so->so_rgid = head->so_rgid;
  177         so->so_cpid = head->so_cpid;
  178         so->so_siguid = head->so_siguid;
  179         so->so_sigeuid = head->so_sigeuid;
  180 
  181         /*
  182          * If we are tight on mbuf clusters, create the new socket
  183          * with the minimum.  Sorry, you lose.
  184          */
  185         snd_sb_hiwat = head->so_snd.sb_hiwat;
  186         if (sbcheckreserve(snd_sb_hiwat, unpst_sendspace))
  187                 snd_sb_hiwat = unpst_sendspace;         /* and udp? */
  188         rcv_sb_hiwat = head->so_rcv.sb_hiwat;
  189         if (sbcheckreserve(rcv_sb_hiwat, unpst_recvspace))
  190                 rcv_sb_hiwat = unpst_recvspace;         /* and udp? */
  191 
  192         (void) soreserve(so, snd_sb_hiwat, rcv_sb_hiwat);
  193         soqinsque(head, so, soqueue);
  194         if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH,
  195             (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) {
  196                 (void) soqremque(so, soqueue);
  197                 pool_put(&socket_pool, so);
  198                 return ((struct socket *)0);
  199         }
  200         if (connstatus) {
  201                 sorwakeup(head);
  202                 wakeup(&head->so_timeo);
  203                 so->so_state |= connstatus;
  204         }
  205         return (so);
  206 }
  207 
  208 void
  209 soqinsque(struct socket *head, struct socket *so, int q)
  210 {
  211 
  212 #ifdef DIAGNOSTIC
  213         if (so->so_onq != NULL)
  214                 panic("soqinsque");
  215 #endif
  216 
  217         so->so_head = head;
  218         if (q == 0) {
  219                 head->so_q0len++;
  220                 so->so_onq = &head->so_q0;
  221         } else {
  222                 head->so_qlen++;
  223                 so->so_onq = &head->so_q;
  224         }
  225         TAILQ_INSERT_TAIL(so->so_onq, so, so_qe);
  226 }
  227 
  228 int
  229 soqremque(struct socket *so, int q)
  230 {
  231         struct socket *head;
  232 
  233         head = so->so_head;
  234         if (q == 0) {
  235                 if (so->so_onq != &head->so_q0)
  236                         return (0);
  237                 head->so_q0len--;
  238         } else {
  239                 if (so->so_onq != &head->so_q)
  240                         return (0);
  241                 head->so_qlen--;
  242         }
  243         TAILQ_REMOVE(so->so_onq, so, so_qe);
  244         so->so_onq = NULL;
  245         so->so_head = NULL;
  246         return (1);
  247 }
  248 
  249 /*
  250  * Socantsendmore indicates that no more data will be sent on the
  251  * socket; it would normally be applied to a socket when the user
  252  * informs the system that no more data is to be sent, by the protocol
  253  * code (in case PRU_SHUTDOWN).  Socantrcvmore indicates that no more data
  254  * will be received, and will normally be applied to the socket by a
  255  * protocol when it detects that the peer will send no more data.
  256  * Data queued for reading in the socket may yet be read.
  257  */
  258 
  259 void
  260 socantsendmore(struct socket *so)
  261 {
  262 
  263         so->so_state |= SS_CANTSENDMORE;
  264         sowwakeup(so);
  265 }
  266 
  267 void
  268 socantrcvmore(struct socket *so)
  269 {
  270 
  271         so->so_state |= SS_CANTRCVMORE;
  272         sorwakeup(so);
  273 }
  274 
  275 /*
  276  * Wait for data to arrive at/drain from a socket buffer.
  277  */
  278 int
  279 sbwait(struct sockbuf *sb)
  280 {
  281 
  282         sb->sb_flags |= SB_WAIT;
  283         return (tsleep(&sb->sb_cc,
  284             (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, netio,
  285             sb->sb_timeo));
  286 }
  287 
  288 /*
  289  * Lock a sockbuf already known to be locked;
  290  * return any error returned from sleep (EINTR).
  291  */
  292 int
  293 sb_lock(struct sockbuf *sb)
  294 {
  295         int error;
  296 
  297         while (sb->sb_flags & SB_LOCK) {
  298                 sb->sb_flags |= SB_WANT;
  299                 error = tsleep(&sb->sb_flags,
  300                     (sb->sb_flags & SB_NOINTR) ?
  301                     PSOCK : PSOCK|PCATCH, netlck, 0);
  302                 if (error)
  303                         return (error);
  304         }
  305         sb->sb_flags |= SB_LOCK;
  306         return (0);
  307 }
  308 
  309 /*
  310  * Wakeup processes waiting on a socket buffer.
  311  * Do asynchronous notification via SIGIO
  312  * if the socket has the SS_ASYNC flag set.
  313  */
  314 void
  315 sowakeup(struct socket *so, struct sockbuf *sb)
  316 {
  317         selwakeup(&sb->sb_sel);
  318         sb->sb_flags &= ~SB_SEL;
  319         if (sb->sb_flags & SB_WAIT) {
  320                 sb->sb_flags &= ~SB_WAIT;
  321                 wakeup(&sb->sb_cc);
  322         }
  323         if (so->so_state & SS_ASYNC)
  324                 csignal(so->so_pgid, SIGIO, so->so_siguid, so->so_sigeuid);
  325         KNOTE(&sb->sb_sel.si_note, 0);
  326 }
  327 
  328 /*
  329  * Socket buffer (struct sockbuf) utility routines.
  330  *
  331  * Each socket contains two socket buffers: one for sending data and
  332  * one for receiving data.  Each buffer contains a queue of mbufs,
  333  * information about the number of mbufs and amount of data in the
  334  * queue, and other fields allowing select() statements and notification
  335  * on data availability to be implemented.
  336  *
  337  * Data stored in a socket buffer is maintained as a list of records.
  338  * Each record is a list of mbufs chained together with the m_next
  339  * field.  Records are chained together with the m_nextpkt field. The upper
  340  * level routine soreceive() expects the following conventions to be
  341  * observed when placing information in the receive buffer:
  342  *
  343  * 1. If the protocol requires each message be preceded by the sender's
  344  *    name, then a record containing that name must be present before
  345  *    any associated data (mbuf's must be of type MT_SONAME).
  346  * 2. If the protocol supports the exchange of ``access rights'' (really
  347  *    just additional data associated with the message), and there are
  348  *    ``rights'' to be received, then a record containing this data
  349  *    should be present (mbuf's must be of type MT_CONTROL).
  350  * 3. If a name or rights record exists, then it must be followed by
  351  *    a data record, perhaps of zero length.
  352  *
  353  * Before using a new socket structure it is first necessary to reserve
  354  * buffer space to the socket, by calling sbreserve().  This should commit
  355  * some of the available buffer space in the system buffer pool for the
  356  * socket (currently, it does nothing but enforce limits).  The space
  357  * should be released by calling sbrelease() when the socket is destroyed.
  358  */
  359 
  360 int
  361 soreserve(struct socket *so, u_long sndcc, u_long rcvcc)
  362 {
  363 
  364         if (sbreserve(&so->so_snd, sndcc) == 0)
  365                 goto bad;
  366         if (sbreserve(&so->so_rcv, rcvcc) == 0)
  367                 goto bad2;
  368         if (so->so_rcv.sb_lowat == 0)
  369                 so->so_rcv.sb_lowat = 1;
  370         if (so->so_snd.sb_lowat == 0)
  371                 so->so_snd.sb_lowat = MCLBYTES;
  372         if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat)
  373                 so->so_snd.sb_lowat = so->so_snd.sb_hiwat;
  374         return (0);
  375 bad2:
  376         sbrelease(&so->so_snd);
  377 bad:
  378         return (ENOBUFS);
  379 }
  380 
  381 /*
  382  * Allot mbufs to a sockbuf.
  383  * Attempt to scale mbmax so that mbcnt doesn't become limiting
  384  * if buffering efficiency is near the normal case.
  385  */
  386 int
  387 sbreserve(struct sockbuf *sb, u_long cc)
  388 {
  389 
  390         if (cc == 0 || cc > sb_max)
  391                 return (0);
  392         sb->sb_hiwat = cc;
  393         sb->sb_mbmax = min(cc * 2, sb_max + (sb_max / MCLBYTES) * MSIZE);
  394         if (sb->sb_lowat > sb->sb_hiwat)
  395                 sb->sb_lowat = sb->sb_hiwat;
  396         return (1);
  397 }
  398 
  399 /*
  400  * If over 50% of mbuf clusters in use, do not accept any
  401  * greater than normal request.
  402  */
  403 int
  404 sbcheckreserve(u_long cnt, u_long defcnt)
  405 {
  406         if (cnt > defcnt &&
  407             mclpool.pr_nout> mclpool.pr_hardlimit / 2)
  408                 return (ENOBUFS);
  409         return (0);
  410 }
  411 
  412 /*
  413  * Free mbufs held by a socket, and reserved mbuf space.
  414  */
  415 void
  416 sbrelease(struct sockbuf *sb)
  417 {
  418 
  419         sbflush(sb);
  420         sb->sb_hiwat = sb->sb_mbmax = 0;
  421 }
  422 
  423 /*
  424  * Routines to add and remove
  425  * data from an mbuf queue.
  426  *
  427  * The routines sbappend() or sbappendrecord() are normally called to
  428  * append new mbufs to a socket buffer, after checking that adequate
  429  * space is available, comparing the function sbspace() with the amount
  430  * of data to be added.  sbappendrecord() differs from sbappend() in
  431  * that data supplied is treated as the beginning of a new record.
  432  * To place a sender's address, optional access rights, and data in a
  433  * socket receive buffer, sbappendaddr() should be used.  To place
  434  * access rights and data in a socket receive buffer, sbappendrights()
  435  * should be used.  In either case, the new data begins a new record.
  436  * Note that unlike sbappend() and sbappendrecord(), these routines check
  437  * for the caller that there will be enough space to store the data.
  438  * Each fails if there is not enough space, or if it cannot find mbufs
  439  * to store additional information in.
  440  *
  441  * Reliable protocols may use the socket send buffer to hold data
  442  * awaiting acknowledgement.  Data is normally copied from a socket
  443  * send buffer in a protocol with m_copy for output to a peer,
  444  * and then removing the data from the socket buffer with sbdrop()
  445  * or sbdroprecord() when the data is acknowledged by the peer.
  446  */
  447 
  448 #ifdef SOCKBUF_DEBUG
  449 void
  450 sblastrecordchk(struct sockbuf *sb, const char *where)
  451 {
  452         struct mbuf *m = sb->sb_mb;
  453 
  454         while (m && m->m_nextpkt)
  455                 m = m->m_nextpkt;
  456 
  457         if (m != sb->sb_lastrecord) {
  458                 printf("sblastrecordchk: sb_mb %p sb_lastrecord %p last %p\n",
  459                     sb->sb_mb, sb->sb_lastrecord, m);
  460                 printf("packet chain:\n");
  461                 for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt)
  462                         printf("\t%p\n", m);
  463                 panic("sblastrecordchk from %s", where);
  464         }
  465 }
  466 
  467 void
  468 sblastmbufchk(struct sockbuf *sb, const char *where)
  469 {
  470         struct mbuf *m = sb->sb_mb;
  471         struct mbuf *n;
  472 
  473         while (m && m->m_nextpkt)
  474                 m = m->m_nextpkt;
  475 
  476         while (m && m->m_next)
  477                 m = m->m_next;
  478 
  479         if (m != sb->sb_mbtail) {
  480                 printf("sblastmbufchk: sb_mb %p sb_mbtail %p last %p\n",
  481                     sb->sb_mb, sb->sb_mbtail, m);
  482                 printf("packet tree:\n");
  483                 for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) {
  484                         printf("\t");
  485                         for (n = m; n != NULL; n = n->m_next)
  486                                 printf("%p ", n);
  487                         printf("\n");
  488                 }
  489                 panic("sblastmbufchk from %s", where);
  490         }
  491 }
  492 #endif /* SOCKBUF_DEBUG */
  493 
  494 #define SBLINKRECORD(sb, m0)                                            \
  495 do {                                                                    \
  496         if ((sb)->sb_lastrecord != NULL)                                \
  497                 (sb)->sb_lastrecord->m_nextpkt = (m0);                  \
  498         else                                                            \
  499                 (sb)->sb_mb = (m0);                                     \
  500         (sb)->sb_lastrecord = (m0);                                     \
  501 } while (/*CONSTCOND*/0)
  502 
  503 /*
  504  * Append mbuf chain m to the last record in the
  505  * socket buffer sb.  The additional space associated
  506  * the mbuf chain is recorded in sb.  Empty mbufs are
  507  * discarded and mbufs are compacted where possible.
  508  */
  509 void
  510 sbappend(struct sockbuf *sb, struct mbuf *m)
  511 {
  512         struct mbuf *n;
  513 
  514         if (m == NULL)
  515                 return;
  516 
  517         SBLASTRECORDCHK(sb, "sbappend 1");
  518 
  519         if ((n = sb->sb_lastrecord) != NULL) {
  520                 /*
  521                  * XXX Would like to simply use sb_mbtail here, but
  522                  * XXX I need to verify that I won't miss an EOR that
  523                  * XXX way.
  524                  */
  525                 do {
  526                         if (n->m_flags & M_EOR) {
  527                                 sbappendrecord(sb, m); /* XXXXXX!!!! */
  528                                 return;
  529                         }
  530                 } while (n->m_next && (n = n->m_next));
  531         } else {
  532                 /*
  533                  * If this is the first record in the socket buffer, it's
  534                  * also the last record.
  535                  */
  536                 sb->sb_lastrecord = m;
  537         }
  538         sbcompress(sb, m, n);
  539         SBLASTRECORDCHK(sb, "sbappend 2");
  540 }
  541 
  542 /*
  543  * This version of sbappend() should only be used when the caller
  544  * absolutely knows that there will never be more than one record
  545  * in the socket buffer, that is, a stream protocol (such as TCP).
  546  */
  547 void
  548 sbappendstream(struct sockbuf *sb, struct mbuf *m)
  549 {
  550 
  551         KDASSERT(m->m_nextpkt == NULL);
  552         KASSERT(sb->sb_mb == sb->sb_lastrecord);
  553 
  554         SBLASTMBUFCHK(sb, __func__);
  555 
  556         sbcompress(sb, m, sb->sb_mbtail);
  557 
  558         sb->sb_lastrecord = sb->sb_mb;
  559         SBLASTRECORDCHK(sb, __func__);
  560 }
  561 
  562 #ifdef SOCKBUF_DEBUG
  563 void
  564 sbcheck(struct sockbuf *sb)
  565 {
  566         struct mbuf *m;
  567         u_long len = 0, mbcnt = 0;
  568 
  569         for (m = sb->sb_mb; m; m = m->m_next) {
  570                 len += m->m_len;
  571                 mbcnt += MSIZE;
  572                 if (m->m_flags & M_EXT)
  573                         mbcnt += m->m_ext.ext_size;
  574                 if (m->m_nextpkt)
  575                         panic("sbcheck nextpkt");
  576         }
  577         if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) {
  578                 printf("cc %lu != %lu || mbcnt %lu != %lu\n", len, sb->sb_cc,
  579                     mbcnt, sb->sb_mbcnt);
  580                 panic("sbcheck");
  581         }
  582 }
  583 #endif
  584 
  585 /*
  586  * As above, except the mbuf chain
  587  * begins a new record.
  588  */
  589 void
  590 sbappendrecord(struct sockbuf *sb, struct mbuf *m0)
  591 {
  592         struct mbuf *m;
  593 
  594         if (m0 == NULL)
  595                 return;
  596 
  597         /*
  598          * Put the first mbuf on the queue.
  599          * Note this permits zero length records.
  600          */
  601         sballoc(sb, m0);
  602         SBLASTRECORDCHK(sb, "sbappendrecord 1");
  603         SBLINKRECORD(sb, m0);
  604         m = m0->m_next;
  605         m0->m_next = NULL;
  606         if (m && (m0->m_flags & M_EOR)) {
  607                 m0->m_flags &= ~M_EOR;
  608                 m->m_flags |= M_EOR;
  609         }
  610         sbcompress(sb, m, m0);
  611         SBLASTRECORDCHK(sb, "sbappendrecord 2");
  612 }
  613 
  614 /*
  615  * As above except that OOB data
  616  * is inserted at the beginning of the sockbuf,
  617  * but after any other OOB data.
  618  */
  619 void
  620 sbinsertoob(struct sockbuf *sb, struct mbuf *m0)
  621 {
  622         struct mbuf *m, **mp;
  623 
  624         if (m0 == NULL)
  625                 return;
  626 
  627         SBLASTRECORDCHK(sb, "sbinsertoob 1");
  628 
  629         for (mp = &sb->sb_mb; (m = *mp) != NULL; mp = &((*mp)->m_nextpkt)) {
  630             again:
  631                 switch (m->m_type) {
  632 
  633                 case MT_OOBDATA:
  634                         continue;               /* WANT next train */
  635 
  636                 case MT_CONTROL:
  637                         if ((m = m->m_next) != NULL)
  638                                 goto again;     /* inspect THIS train further */
  639                 }
  640                 break;
  641         }
  642         /*
  643          * Put the first mbuf on the queue.
  644          * Note this permits zero length records.
  645          */
  646         sballoc(sb, m0);
  647         m0->m_nextpkt = *mp;
  648         if (*mp == NULL) {
  649                 /* m0 is actually the new tail */
  650                 sb->sb_lastrecord = m0;
  651         }
  652         *mp = m0;
  653         m = m0->m_next;
  654         m0->m_next = NULL;
  655         if (m && (m0->m_flags & M_EOR)) {
  656                 m0->m_flags &= ~M_EOR;
  657                 m->m_flags |= M_EOR;
  658         }
  659         sbcompress(sb, m, m0);
  660         SBLASTRECORDCHK(sb, "sbinsertoob 2");
  661 }
  662 
  663 /*
  664  * Append address and data, and optionally, control (ancillary) data
  665  * to the receive queue of a socket.  If present,
  666  * m0 must include a packet header with total length.
  667  * Returns 0 if no space in sockbuf or insufficient mbufs.
  668  */
  669 int
  670 sbappendaddr(struct sockbuf *sb, struct sockaddr *asa, struct mbuf *m0,
  671     struct mbuf *control)
  672 {
  673         struct mbuf *m, *n, *nlast;
  674         int space = asa->sa_len;
  675 
  676         if (m0 && (m0->m_flags & M_PKTHDR) == 0)
  677                 panic("sbappendaddr");
  678         if (m0)
  679                 space += m0->m_pkthdr.len;
  680         for (n = control; n; n = n->m_next) {
  681                 space += n->m_len;
  682                 if (n->m_next == NULL)  /* keep pointer to last control buf */
  683                         break;
  684         }
  685         if (space > sbspace(sb))
  686                 return (0);
  687         if (asa->sa_len > MLEN)
  688                 return (0);
  689         MGET(m, M_DONTWAIT, MT_SONAME);
  690         if (m == NULL)
  691                 return (0);
  692         m->m_len = asa->sa_len;
  693         bcopy(asa, mtod(m, caddr_t), asa->sa_len);
  694         if (n)
  695                 n->m_next = m0;         /* concatenate data to control */
  696         else
  697                 control = m0;
  698         m->m_next = control;
  699 
  700         SBLASTRECORDCHK(sb, "sbappendaddr 1");
  701 
  702         for (n = m; n->m_next != NULL; n = n->m_next)
  703                 sballoc(sb, n);
  704         sballoc(sb, n);
  705         nlast = n;
  706         SBLINKRECORD(sb, m);
  707 
  708         sb->sb_mbtail = nlast;
  709         SBLASTMBUFCHK(sb, "sbappendaddr");
  710 
  711         SBLASTRECORDCHK(sb, "sbappendaddr 2");
  712 
  713         return (1);
  714 }
  715 
  716 int
  717 sbappendcontrol(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control)
  718 {
  719         struct mbuf *m, *mlast, *n;
  720         int space = 0;
  721 
  722         if (control == NULL)
  723                 panic("sbappendcontrol");
  724         for (m = control; ; m = m->m_next) {
  725                 space += m->m_len;
  726                 if (m->m_next == NULL)
  727                         break;
  728         }
  729         n = m;                  /* save pointer to last control buffer */
  730         for (m = m0; m; m = m->m_next)
  731                 space += m->m_len;
  732         if (space > sbspace(sb))
  733                 return (0);
  734         n->m_next = m0;                 /* concatenate data to control */
  735 
  736         SBLASTRECORDCHK(sb, "sbappendcontrol 1");
  737 
  738         for (m = control; m->m_next != NULL; m = m->m_next)
  739                 sballoc(sb, m);
  740         sballoc(sb, m);
  741         mlast = m;
  742         SBLINKRECORD(sb, control);
  743 
  744         sb->sb_mbtail = mlast;
  745         SBLASTMBUFCHK(sb, "sbappendcontrol");
  746 
  747         SBLASTRECORDCHK(sb, "sbappendcontrol 2");
  748 
  749         return (1);
  750 }
  751 
  752 /*
  753  * Compress mbuf chain m into the socket
  754  * buffer sb following mbuf n.  If n
  755  * is null, the buffer is presumed empty.
  756  */
  757 void
  758 sbcompress(struct sockbuf *sb, struct mbuf *m, struct mbuf *n)
  759 {
  760         int eor = 0;
  761         struct mbuf *o;
  762 
  763         while (m) {
  764                 eor |= m->m_flags & M_EOR;
  765                 if (m->m_len == 0 &&
  766                     (eor == 0 ||
  767                     (((o = m->m_next) || (o = n)) &&
  768                     o->m_type == m->m_type))) {
  769                         if (sb->sb_lastrecord == m)
  770                                 sb->sb_lastrecord = m->m_next;
  771                         m = m_free(m);
  772                         continue;
  773                 }
  774                 if (n && (n->m_flags & M_EOR) == 0 &&
  775                     /* M_TRAILINGSPACE() checks buffer writeability */
  776                     m->m_len <= MCLBYTES / 4 && /* XXX Don't copy too much */
  777                     m->m_len <= M_TRAILINGSPACE(n) &&
  778                     n->m_type == m->m_type) {
  779                         bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
  780                             (unsigned)m->m_len);
  781                         n->m_len += m->m_len;
  782                         sb->sb_cc += m->m_len;
  783                         if (m->m_type != MT_CONTROL && m->m_type != MT_SONAME)
  784                                 sb->sb_datacc += m->m_len;
  785                         m = m_free(m);
  786                         continue;
  787                 }
  788                 if (n)
  789                         n->m_next = m;
  790                 else
  791                         sb->sb_mb = m;
  792                 sb->sb_mbtail = m;
  793                 sballoc(sb, m);
  794                 n = m;
  795                 m->m_flags &= ~M_EOR;
  796                 m = m->m_next;
  797                 n->m_next = NULL;
  798         }
  799         if (eor) {
  800                 if (n)
  801                         n->m_flags |= eor;
  802                 else
  803                         printf("semi-panic: sbcompress");
  804         }
  805         SBLASTMBUFCHK(sb, __func__);
  806 }
  807 
  808 /*
  809  * Free all mbufs in a sockbuf.
  810  * Check that all resources are reclaimed.
  811  */
  812 void
  813 sbflush(struct sockbuf *sb)
  814 {
  815 
  816         KASSERT((sb->sb_flags & SB_LOCK) == 0);
  817 
  818         while (sb->sb_mbcnt)
  819                 sbdrop(sb, (int)sb->sb_cc);
  820 
  821         KASSERT(sb->sb_cc == 0);
  822         KASSERT(sb->sb_datacc == 0);
  823         KASSERT(sb->sb_mb == NULL);
  824         KASSERT(sb->sb_mbtail == NULL);
  825         KASSERT(sb->sb_lastrecord == NULL);
  826 }
  827 
  828 /*
  829  * Drop data from (the front of) a sockbuf.
  830  */
  831 void
  832 sbdrop(struct sockbuf *sb, int len)
  833 {
  834         struct mbuf *m, *mn;
  835         struct mbuf *next;
  836 
  837         next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
  838         while (len > 0) {
  839                 if (m == NULL) {
  840                         if (next == NULL)
  841                                 panic("sbdrop");
  842                         m = next;
  843                         next = m->m_nextpkt;
  844                         continue;
  845                 }
  846                 if (m->m_len > len) {
  847                         m->m_len -= len;
  848                         m->m_data += len;
  849                         sb->sb_cc -= len;
  850                         if (m->m_type != MT_CONTROL && m->m_type != MT_SONAME)
  851                                 sb->sb_datacc -= len;
  852                         break;
  853                 }
  854                 len -= m->m_len;
  855                 sbfree(sb, m);
  856                 MFREE(m, mn);
  857                 m = mn;
  858         }
  859         while (m && m->m_len == 0) {
  860                 sbfree(sb, m);
  861                 MFREE(m, mn);
  862                 m = mn;
  863         }
  864         if (m) {
  865                 sb->sb_mb = m;
  866                 m->m_nextpkt = next;
  867         } else
  868                 sb->sb_mb = next;
  869         /*
  870          * First part is an inline SB_EMPTY_FIXUP().  Second part
  871          * makes sure sb_lastrecord is up-to-date if we dropped
  872          * part of the last record.
  873          */
  874         m = sb->sb_mb;
  875         if (m == NULL) {
  876                 sb->sb_mbtail = NULL;
  877                 sb->sb_lastrecord = NULL;
  878         } else if (m->m_nextpkt == NULL)
  879                 sb->sb_lastrecord = m;
  880 }
  881 
  882 /*
  883  * Drop a record off the front of a sockbuf
  884  * and move the next record to the front.
  885  */
  886 void
  887 sbdroprecord(struct sockbuf *sb)
  888 {
  889         struct mbuf *m, *mn;
  890 
  891         m = sb->sb_mb;
  892         if (m) {
  893                 sb->sb_mb = m->m_nextpkt;
  894                 do {
  895                         sbfree(sb, m);
  896                         MFREE(m, mn);
  897                 } while ((m = mn) != NULL);
  898         }
  899         SB_EMPTY_FIXUP(sb);
  900 }
  901 
  902 /*
  903  * Create a "control" mbuf containing the specified data
  904  * with the specified type for presentation on a socket buffer.
  905  */
  906 struct mbuf *
  907 sbcreatecontrol(caddr_t p, int size, int type, int level)
  908 {
  909         struct cmsghdr *cp;
  910         struct mbuf *m;
  911 
  912         if (CMSG_SPACE(size) > MCLBYTES) {
  913                 printf("sbcreatecontrol: message too large %d\n", size);
  914                 return NULL;
  915         }
  916 
  917         if ((m = m_get(M_DONTWAIT, MT_CONTROL)) == NULL)
  918                 return ((struct mbuf *) NULL);
  919         if (CMSG_SPACE(size) > MLEN) {
  920                 MCLGET(m, M_DONTWAIT);
  921                 if ((m->m_flags & M_EXT) == 0) {
  922                         m_free(m);
  923                         return NULL;
  924                 }
  925         }
  926         cp = mtod(m, struct cmsghdr *);
  927         bcopy(p, CMSG_DATA(cp), size);
  928         m->m_len = CMSG_SPACE(size);
  929         cp->cmsg_len = CMSG_LEN(size);
  930         cp->cmsg_level = level;
  931         cp->cmsg_type = type;
  932         return (m);
  933 }

/* [<][>][^][v][top][bottom][index][help] */