home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / uipc_socket.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-09  |  23.2 KB  |  992 lines

  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_socket.c    7.28 (Berkeley) 5/4/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "proc.h"
  38. #include "file.h"
  39. #include "malloc.h"
  40. #include "mbuf.h"
  41. #include "domain.h"
  42. #include "kernel.h"
  43. #include "protosw.h"
  44. #include "socket.h"
  45. #include "socketvar.h"
  46. #include "resourcevar.h"
  47.  
  48. /*
  49.  * Socket operation routines.
  50.  * These routines are called by the routines in
  51.  * sys_socket.c or from a system process, and
  52.  * implement the semantics of socket operations by
  53.  * switching out to the protocol specific routines.
  54.  */
  55. /*ARGSUSED*/
  56. socreate(dom, aso, type, proto)
  57.     struct socket **aso;
  58.     register int type;
  59.     int proto;
  60. {
  61.     struct proc *p = curproc;        /* XXX */
  62.     register struct protosw *prp;
  63.     register struct socket *so;
  64.     register int error;
  65.  
  66.     if (proto)
  67.         prp = pffindproto(dom, proto, type);
  68.     else
  69.         prp = pffindtype(dom, type);
  70.     if (prp == 0)
  71.         return (EPROTONOSUPPORT);
  72.     if (prp->pr_type != type)
  73.         return (EPROTOTYPE);
  74.     MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_WAIT);
  75.     bzero((caddr_t)so, sizeof(*so));
  76.     so->so_type = type;
  77.     if (p->p_ucred->cr_uid == 0)
  78.         so->so_state = SS_PRIV;
  79.     so->so_proto = prp;
  80.     error =
  81.         (*prp->pr_usrreq)(so, PRU_ATTACH,
  82.         (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0);
  83.     if (error) {
  84.         so->so_state |= SS_NOFDREF;
  85.         sofree(so);
  86.         return (error);
  87.     }
  88.     *aso = so;
  89.     return (0);
  90. }
  91.  
  92. sobind(so, nam)
  93.     struct socket *so;
  94.     struct mbuf *nam;
  95. {
  96.     int s = splnet();
  97.     int error;
  98.  
  99.     error =
  100.         (*so->so_proto->pr_usrreq)(so, PRU_BIND,
  101.         (struct mbuf *)0, nam, (struct mbuf *)0);
  102.     splx(s);
  103.     return (error);
  104. }
  105.  
  106. solisten(so, backlog)
  107.     register struct socket *so;
  108.     int backlog;
  109. {
  110.     int s = splnet(), error;
  111.  
  112.     error =
  113.         (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
  114.         (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
  115.     if (error) {
  116.         splx(s);
  117.         return (error);
  118.     }
  119.     if (so->so_q == 0)
  120.         so->so_options |= SO_ACCEPTCONN;
  121.     if (backlog < 0)
  122.         backlog = 0;
  123.     so->so_qlimit = min(backlog, SOMAXCONN);
  124.     splx(s);
  125.     return (0);
  126. }
  127.  
  128. sofree(so)
  129.     register struct socket *so;
  130. {
  131.  
  132.     if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
  133.         return;
  134.     if (so->so_head) {
  135.         if (!soqremque(so, 0) && !soqremque(so, 1))
  136.             panic("sofree dq");
  137.         so->so_head = 0;
  138.     }
  139.     sbrelease(&so->so_snd);
  140.     sorflush(so);
  141.     FREE(so, M_SOCKET);
  142. }
  143.  
  144. /*
  145.  * Close a socket on last file table reference removal.
  146.  * Initiate disconnect if connected.
  147.  * Free socket when disconnect complete.
  148.  */
  149. soclose(so)
  150.     register struct socket *so;
  151. {
  152.     int s = splnet();        /* conservative */
  153.     int error = 0;
  154.  
  155.     if (so->so_options & SO_ACCEPTCONN) {
  156.         while (so->so_q0)
  157.             (void) soabort(so->so_q0);
  158.         while (so->so_q)
  159.             (void) soabort(so->so_q);
  160.     }
  161.     if (so->so_pcb == 0)
  162.         goto discard;
  163.     if (so->so_state & SS_ISCONNECTED) {
  164.         if ((so->so_state & SS_ISDISCONNECTING) == 0) {
  165.             error = sodisconnect(so);
  166.             if (error)
  167.                 goto drop;
  168.         }
  169.         if (so->so_options & SO_LINGER) {
  170.             if ((so->so_state & SS_ISDISCONNECTING) &&
  171.                 (so->so_state & SS_NBIO))
  172.                 goto drop;
  173.             while (so->so_state & SS_ISCONNECTED)
  174.                 if (error = tsleep((caddr_t)&so->so_timeo,
  175.                     PSOCK | PCATCH, netcls, so->so_linger))
  176.                     break;
  177.         }
  178.     }
  179. drop:
  180.     if (so->so_pcb) {
  181.         int error2 =
  182.             (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
  183.             (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
  184.         if (error == 0)
  185.             error = error2;
  186.     }
  187. discard:
  188.     if (so->so_state & SS_NOFDREF)
  189.         panic("soclose: NOFDREF");
  190.     so->so_state |= SS_NOFDREF;
  191.     sofree(so);
  192.     splx(s);
  193.     return (error);
  194. }
  195.  
  196. /*
  197.  * Must be called at splnet...
  198.  */
  199. soabort(so)
  200.     struct socket *so;
  201. {
  202.  
  203.     return (
  204.         (*so->so_proto->pr_usrreq)(so, PRU_ABORT,
  205.         (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
  206. }
  207.  
  208. soaccept(so, nam)
  209.     register struct socket *so;
  210.     struct mbuf *nam;
  211. {
  212.     int s = splnet();
  213.     int error;
  214.  
  215.     if ((so->so_state & SS_NOFDREF) == 0)
  216.         panic("soaccept: !NOFDREF");
  217.     so->so_state &= ~SS_NOFDREF;
  218.     error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
  219.         (struct mbuf *)0, nam, (struct mbuf *)0);
  220.     splx(s);
  221.     return (error);
  222. }
  223.  
  224. soconnect(so, nam)
  225.     register struct socket *so;
  226.     struct mbuf *nam;
  227. {
  228.     int s;
  229.     int error;
  230.  
  231.     if (so->so_options & SO_ACCEPTCONN)
  232.         return (EOPNOTSUPP);
  233.     s = splnet();
  234.     /*
  235.      * If protocol is connection-based, can only connect once.
  236.      * Otherwise, if connected, try to disconnect first.
  237.      * This allows user to disconnect by connecting to, e.g.,
  238.      * a null address.
  239.      */
  240.     if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
  241.         ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
  242.         (error = sodisconnect(so))))
  243.         error = EISCONN;
  244.     else
  245.         error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
  246.             (struct mbuf *)0, nam, (struct mbuf *)0);
  247.     splx(s);
  248.     return (error);
  249. }
  250.  
  251. soconnect2(so1, so2)
  252.     register struct socket *so1;
  253.     struct socket *so2;
  254. {
  255.     int s = splnet();
  256.     int error;
  257.  
  258.     error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
  259.         (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0);
  260.     splx(s);
  261.     return (error);
  262. }
  263.  
  264. sodisconnect(so)
  265.     register struct socket *so;
  266. {
  267.     int s = splnet();
  268.     int error;
  269.  
  270.     if ((so->so_state & SS_ISCONNECTED) == 0) {
  271.         error = ENOTCONN;
  272.         goto bad;
  273.     }
  274.     if (so->so_state & SS_ISDISCONNECTING) {
  275.         error = EALREADY;
  276.         goto bad;
  277.     }
  278.     error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
  279.         (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
  280. bad:
  281.     splx(s);
  282.     return (error);
  283. }
  284.  
  285. /*
  286.  * Send on a socket.
  287.  * If send must go all at once and message is larger than
  288.  * send buffering, then hard error.
  289.  * Lock against other senders.
  290.  * If must go all at once and not enough room now, then
  291.  * inform user that this would block and do nothing.
  292.  * Otherwise, if nonblocking, send as much as possible.
  293.  * The data to be sent is described by "uio" if nonzero,
  294.  * otherwise by the mbuf chain "top" (which must be null
  295.  * if uio is not).  Data provided in mbuf chain must be small
  296.  * enough to send all at once.
  297.  *
  298.  * Returns nonzero on error, timeout or signal; callers
  299.  * must check for short counts if EINTR/ERESTART are returned.
  300.  * Data and control buffers are freed on return.
  301.  */
  302. sosend(so, addr, uio, top, control, flags)
  303.     register struct socket *so;
  304.     struct mbuf *addr;
  305.     struct uio *uio;
  306.     struct mbuf *top;
  307.     struct mbuf *control;
  308.     int flags;
  309. {
  310.     struct proc *p = curproc;        /* XXX */
  311.     struct mbuf **mp;
  312.     register struct mbuf *m;
  313.     register long space, len, resid;
  314.     int clen = 0, error, s, dontroute, mlen;
  315.     int atomic = sosendallatonce(so) || top;
  316.  
  317.     if (uio)
  318.         resid = uio->uio_resid;
  319.     else
  320.         resid = top->m_pkthdr.len;
  321.     dontroute =
  322.         (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
  323.         (so->so_proto->pr_flags & PR_ATOMIC);
  324.     p->p_stats->p_ru.ru_msgsnd++;
  325.     if (control)
  326.         clen = control->m_len;
  327. #define    snderr(errno)    { error = errno; splx(s); goto release; }
  328.  
  329. restart:
  330.     if (error = sblock(&so->so_snd))
  331.         goto out;
  332.     do {
  333.         s = splnet();
  334.         if (so->so_state & SS_CANTSENDMORE)
  335.             snderr(EPIPE);
  336.         if (so->so_error)
  337.             snderr(so->so_error);
  338.         if ((so->so_state & SS_ISCONNECTED) == 0) {
  339.             if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
  340.                 if ((so->so_state & SS_ISCONFIRMING) == 0 &&
  341.                     !(resid == 0 && clen != 0))
  342.                     snderr(ENOTCONN);
  343.             } else if (addr == 0)
  344.                 snderr(EDESTADDRREQ);
  345.         }
  346.         space = sbspace(&so->so_snd);
  347.         if (flags & MSG_OOB)
  348.             space += 1024;
  349.         if (space < resid + clen &&
  350.             (atomic || space < so->so_snd.sb_lowat || space < clen)) {
  351.             if (atomic && resid > so->so_snd.sb_hiwat ||
  352.                 clen > so->so_snd.sb_hiwat)
  353.                 snderr(EMSGSIZE);
  354.             if (so->so_state & SS_NBIO)
  355.                 snderr(EWOULDBLOCK);
  356.             sbunlock(&so->so_snd);
  357.             error = sbwait(&so->so_snd);
  358.             splx(s);
  359.             if (error)
  360.                 goto out;
  361.             goto restart;
  362.         }
  363.         splx(s);
  364.         mp = ⊤
  365.         space -= clen;
  366.         do {
  367.             if (uio == NULL) {
  368.             /*
  369.              * Data is prepackaged in "top".
  370.              */
  371.             resid = 0;
  372.             if (flags & MSG_EOR)
  373.                 top->m_flags |= M_EOR;
  374.             } else do {
  375.             if (top == 0) {
  376.                 MGETHDR(m, M_WAIT, MT_DATA);
  377.                 mlen = MHLEN;
  378.                 m->m_pkthdr.len = 0;
  379.                 m->m_pkthdr.rcvif = (struct ifnet *)0;
  380.             } else {
  381.                 MGET(m, M_WAIT, MT_DATA);
  382.                 mlen = MLEN;
  383.             }
  384.             if (resid >= MINCLSIZE && space >= MCLBYTES) {
  385.                 MCLGET(m, M_WAIT);
  386.                 if ((m->m_flags & M_EXT) == 0)
  387.                     goto nopages;
  388.                 mlen = MCLBYTES;
  389. #ifdef    MAPPED_MBUFS
  390.                 len = min(MCLBYTES, resid);
  391. #else
  392.                 if (top == 0) {
  393.                     len = min(MCLBYTES - max_hdr, resid);
  394.                     m->m_data += max_hdr;
  395.                 } else
  396.                     len = min(MCLBYTES, resid);
  397. #endif
  398.                 space -= MCLBYTES;
  399.             } else {
  400. nopages:
  401.                 len = min(min(mlen, resid), space);
  402.                 space -= len;
  403.                 /*
  404.                  * For datagram protocols, leave room
  405.                  * for protocol headers in first mbuf.
  406.                  */
  407.                 if (atomic && top == 0 && len < mlen)
  408.                     MH_ALIGN(m, len);
  409.             }
  410.             error = uiomove(mtod(m, caddr_t), (int)len, uio);
  411.             resid = uio->uio_resid;
  412.             m->m_len = len;
  413.             *mp = m;
  414.             top->m_pkthdr.len += len;
  415.             if (error)
  416.                 goto release;
  417.             mp = &m->m_next;
  418.             if (resid <= 0) {
  419.                 if (flags & MSG_EOR)
  420.                     top->m_flags |= M_EOR;
  421.                 break;
  422.             }
  423.             } while (space > 0 && atomic);
  424.             if (dontroute)
  425.                 so->so_options |= SO_DONTROUTE;
  426.             s = splnet();                /* XXX */
  427.             error = (*so->so_proto->pr_usrreq)(so,
  428.             (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
  429.             top, addr, control);
  430.             splx(s);
  431.             if (dontroute)
  432.                 so->so_options &= ~SO_DONTROUTE;
  433.             clen = 0;
  434.             control = 0;
  435.             top = 0;
  436.             mp = ⊤
  437.             if (error)
  438.             goto release;
  439.         } while (resid && space > 0);
  440.     } while (resid);
  441.  
  442. release:
  443.     sbunlock(&so->so_snd);
  444. out:
  445.     if (top)
  446.         m_freem(top);
  447.     if (control)
  448.         m_freem(control);
  449.     return (error);
  450. }
  451.  
  452. /*
  453.  * Implement receive operations on a socket.
  454.  * We depend on the way that records are added to the sockbuf
  455.  * by sbappend*.  In particular, each record (mbufs linked through m_next)
  456.  * must begin with an address if the protocol so specifies,
  457.  * followed by an optional mbuf or mbufs containing ancillary data,
  458.  * and then zero or more mbufs of data.
  459.  * In order to avoid blocking network interrupts for the entire time here,
  460.  * we splx() while doing the actual copy to user space.
  461.  * Although the sockbuf is locked, new data may still be appended,
  462.  * and thus we must maintain consistency of the sockbuf during that time.
  463.  *
  464.  * The caller may receive the data as a single mbuf chain by supplying
  465.  * an mbuf **mp0 for use in returning the chain.  The uio is then used
  466.  * only for the count in uio_resid.
  467.  */
  468. soreceive(so, paddr, uio, mp0, controlp, flagsp)
  469.     register struct socket *so;
  470.     struct mbuf **paddr;
  471.     struct uio *uio;
  472.     struct mbuf **mp0;
  473.     struct mbuf **controlp;
  474.     int *flagsp;
  475. {
  476.     struct proc *p = curproc;        /* XXX */
  477.     register struct mbuf *m, **mp;
  478.     register int flags, len, error, s, offset;
  479.     struct protosw *pr = so->so_proto;
  480.     struct mbuf *nextrecord;
  481.     int moff, type;
  482.  
  483.     mp = mp0;
  484.     if (paddr)
  485.         *paddr = 0;
  486.     if (controlp)
  487.         *controlp = 0;
  488.     if (flagsp)
  489.         flags = *flagsp &~ MSG_EOR;
  490.     else
  491.         flags = 0;
  492.     if (flags & MSG_OOB) {
  493.         m = m_get(M_WAIT, MT_DATA);
  494.         error = (*pr->pr_usrreq)(so, PRU_RCVOOB,
  495.             m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0);
  496.         if (error)
  497.             goto bad;
  498.         do {
  499.             error = uiomove(mtod(m, caddr_t),
  500.                 (int) min(uio->uio_resid, m->m_len), uio);
  501.             m = m_free(m);
  502.         } while (uio->uio_resid && error == 0 && m);
  503. bad:
  504.         if (m)
  505.             m_freem(m);
  506.         return (error);
  507.     }
  508.     if (mp)
  509.         *mp = (struct mbuf *)0;
  510.     if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
  511.         (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
  512.             (struct mbuf *)0, (struct mbuf *)0);
  513.  
  514. restart:
  515.     if (error = sblock(&so->so_rcv))
  516.         return (error);
  517.     s = splnet();
  518.  
  519.     m = so->so_rcv.sb_mb;
  520.     /*
  521.      * If we have less data than requested, block awaiting more
  522.      * (subject to any timeout) if:
  523.      *   1. the current count is less than the low water mark, or
  524.      *   2. MSG_WAITALL is set, and it is possible to do the entire
  525.      *    receive operation at once if we block (resid <= hiwat).
  526.      * If MSG_WAITALL is set but resid is larger than the receive buffer,
  527.      * we have to do the receive in sections, and thus risk returning
  528.      * a short count if a timeout or signal occurs after we start.
  529.      */
  530.     while (m == 0 || so->so_rcv.sb_cc < uio->uio_resid &&
  531.         (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
  532.         ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
  533.         m->m_nextpkt == 0) {
  534. #ifdef DIAGNOSTIC
  535.         if (m == 0 && so->so_rcv.sb_cc)
  536.             panic("receive 1");
  537. #endif
  538.         if (so->so_error) {
  539.             if (m)
  540.                 break;
  541.             error = so->so_error;
  542.             if ((flags & MSG_PEEK) == 0)
  543.                 so->so_error = 0;
  544.             goto release;
  545.         }
  546.         if (so->so_state & SS_CANTRCVMORE) {
  547.             if (m)
  548.                 break;
  549.             else
  550.                 goto release;
  551.         }
  552.         for (; m; m = m->m_next)
  553.             if (m->m_type == MT_OOBDATA  || (m->m_flags & M_EOR)) {
  554.                 m = so->so_rcv.sb_mb;
  555.                 goto dontblock;
  556.             }
  557.         if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
  558.             (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
  559.             error = ENOTCONN;
  560.             goto release;
  561.         }
  562.         if (uio->uio_resid == 0)
  563.             goto release;
  564.         if (so->so_state & SS_NBIO) {
  565.             error = EWOULDBLOCK;
  566.             goto release;
  567.         }
  568.         sbunlock(&so->so_rcv);
  569.         error = sbwait(&so->so_rcv);
  570.         splx(s);
  571.         if (error)
  572.             return (error);
  573.         goto restart;
  574.     }
  575. dontblock:
  576.     p->p_stats->p_ru.ru_msgrcv++;
  577.     nextrecord = m->m_nextpkt;
  578.     if (pr->pr_flags & PR_ADDR) {
  579. #ifdef DIAGNOSTIC
  580.         if (m->m_type != MT_SONAME)
  581.             panic("receive 1a");
  582. #endif
  583.         if (flags & MSG_PEEK) {
  584.             if (paddr)
  585.                 *paddr = m_copy(m, 0, m->m_len);
  586.             m = m->m_next;
  587.         } else {
  588.             sbfree(&so->so_rcv, m);
  589.             if (paddr) {
  590.                 *paddr = m;
  591.                 so->so_rcv.sb_mb = m->m_next;
  592.                 m->m_next = 0;
  593.                 m = so->so_rcv.sb_mb;
  594.             } else {
  595.                 MFREE(m, so->so_rcv.sb_mb);
  596.                 m = so->so_rcv.sb_mb;
  597.             }
  598.         }
  599.     }
  600.     while (m && m->m_type == MT_CONTROL && error == 0) {
  601.         if (flags & MSG_PEEK) {
  602.             if (controlp)
  603.                 *controlp = m_copy(m, 0, m->m_len);
  604.             m = m->m_next;
  605.         } else {
  606.             sbfree(&so->so_rcv, m);
  607.             if (controlp) {
  608.                 if (pr->pr_domain->dom_externalize &&
  609.                     mtod(m, struct cmsghdr *)->cmsg_type ==
  610.                     SCM_RIGHTS)
  611.                    error = (*pr->pr_domain->dom_externalize)(m);
  612.                 *controlp = m;
  613.                 so->so_rcv.sb_mb = m->m_next;
  614.                 m->m_next = 0;
  615.                 m = so->so_rcv.sb_mb;
  616.             } else {
  617.                 MFREE(m, so->so_rcv.sb_mb);
  618.                 m = so->so_rcv.sb_mb;
  619.             }
  620.         }
  621.         if (controlp)
  622.             controlp = &(*controlp)->m_next;
  623.     }
  624.     if (m) {
  625.         if ((flags & MSG_PEEK) == 0)
  626.             m->m_nextpkt = nextrecord;
  627.         type = m->m_type;
  628.         if (type == MT_OOBDATA)
  629.             flags |= MSG_OOB;
  630.     }
  631.     moff = 0;
  632.     offset = 0;
  633.     while (m && uio->uio_resid > 0 && error == 0) {
  634.         if (m->m_type == MT_OOBDATA) {
  635.             if (type != MT_OOBDATA)
  636.                 break;
  637.         } else if (type == MT_OOBDATA)
  638.             break;
  639. #ifdef DIAGNOSTIC
  640.         else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
  641.             panic("receive 3");
  642. #endif
  643.         so->so_state &= ~SS_RCVATMARK;
  644.         len = uio->uio_resid;
  645.         if (so->so_oobmark && len > so->so_oobmark - offset)
  646.             len = so->so_oobmark - offset;
  647.         if (len > m->m_len - moff)
  648.             len = m->m_len - moff;
  649.         /*
  650.          * If mp is set, just pass back the mbufs.
  651.          * Otherwise copy them out via the uio, then free.
  652.          * Sockbuf must be consistent here (points to current mbuf,
  653.          * it points to next record) when we drop priority;
  654.          * we must note any additions to the sockbuf when we
  655.          * block interrupts again.
  656.          */
  657.         if (mp == 0) {
  658.             splx(s);
  659.             error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
  660.             s = splnet();
  661.         } else
  662.             uio->uio_resid -= len;
  663.         if (len == m->m_len - moff) {
  664.             if (m->m_flags & M_EOR)
  665.                 flags |= MSG_EOR;
  666.             if (flags & MSG_PEEK) {
  667.                 m = m->m_next;
  668.                 moff = 0;
  669.             } else {
  670.                 nextrecord = m->m_nextpkt;
  671.                 sbfree(&so->so_rcv, m);
  672.                 if (mp) {
  673.                     *mp = m;
  674.                     mp = &m->m_next;
  675.                     so->so_rcv.sb_mb = m = m->m_next;
  676.                     *mp = (struct mbuf *)0;
  677.                 } else {
  678.                     MFREE(m, so->so_rcv.sb_mb);
  679.                     m = so->so_rcv.sb_mb;
  680.                 }
  681.                 if (m)
  682.                     m->m_nextpkt = nextrecord;
  683.             }
  684.         } else {
  685.             if (flags & MSG_PEEK)
  686.                 moff += len;
  687.             else {
  688.                 if (mp)
  689.                     *mp = m_copym(m, 0, len, M_WAIT);
  690.                 m->m_data += len;
  691.                 m->m_len -= len;
  692.                 so->so_rcv.sb_cc -= len;
  693.             }
  694.         }
  695.         if (so->so_oobmark) {
  696.             if ((flags & MSG_PEEK) == 0) {
  697.                 so->so_oobmark -= len;
  698.                 if (so->so_oobmark == 0) {
  699.                     so->so_state |= SS_RCVATMARK;
  700.                     break;
  701.                 }
  702.             } else
  703.                 offset += len;
  704.         }
  705.         if (flags & MSG_EOR)
  706.             break;
  707.         /*
  708.          * If the MSG_WAITALL flag is set (for non-atomic socket),
  709.          * we must not quit until "uio->uio_resid == 0" or an error
  710.          * termination.  If a signal/timeout occurs, return
  711.          * with a short count but without error.
  712.          * Keep sockbuf locked against other readers.
  713.          */
  714.         while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
  715.             !sosendallatonce(so)) {
  716.             if (so->so_error || so->so_state & SS_CANTRCVMORE)
  717.                 break;
  718.             error = sbwait(&so->so_rcv);
  719.             if (error) {
  720.                 sbunlock(&so->so_rcv);
  721.                 splx(s);
  722.                 return (0);
  723.             }
  724.             if (m = so->so_rcv.sb_mb)
  725.                 nextrecord = m->m_nextpkt;
  726.         }
  727.     }
  728.     if ((flags & MSG_PEEK) == 0) {
  729.         if (m == 0)
  730.             so->so_rcv.sb_mb = nextrecord;
  731.         else if (pr->pr_flags & PR_ATOMIC) {
  732.             flags |= MSG_TRUNC;
  733.             (void) sbdroprecord(&so->so_rcv);
  734.         }
  735.         if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
  736.             (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
  737.                 (struct mbuf *)flags, (struct mbuf *)0,
  738.                 (struct mbuf *)0);
  739.     }
  740.     if (flagsp)
  741.         *flagsp |= flags;
  742. release:
  743.     sbunlock(&so->so_rcv);
  744.     splx(s);
  745.     return (error);
  746. }
  747.  
  748. soshutdown(so, how)
  749.     register struct socket *so;
  750.     register int how;
  751. {
  752.     register struct protosw *pr = so->so_proto;
  753.  
  754.     how++;
  755.     if (how & FREAD)
  756.         sorflush(so);
  757.     if (how & FWRITE)
  758.         return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN,
  759.             (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
  760.     return (0);
  761. }
  762.  
  763. sorflush(so)
  764.     register struct socket *so;
  765. {
  766.     register struct sockbuf *sb = &so->so_rcv;
  767.     register struct protosw *pr = so->so_proto;
  768.     register int s;
  769.     struct sockbuf asb;
  770.  
  771.     sb->sb_flags |= SB_NOINTR;
  772.     (void) sblock(sb);
  773.     s = splimp();
  774.     socantrcvmore(so);
  775.     sbunlock(sb);
  776.     asb = *sb;
  777.     bzero((caddr_t)sb, sizeof (*sb));
  778.     splx(s);
  779.     if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
  780.         (*pr->pr_domain->dom_dispose)(asb.sb_mb);
  781.     sbrelease(&asb);
  782. }
  783.  
  784. sosetopt(so, level, optname, m0)
  785.     register struct socket *so;
  786.     int level, optname;
  787.     struct mbuf *m0;
  788. {
  789.     int error = 0;
  790.     register struct mbuf *m = m0;
  791.  
  792.     if (level != SOL_SOCKET) {
  793.         if (so->so_proto && so->so_proto->pr_ctloutput)
  794.             return ((*so->so_proto->pr_ctloutput)
  795.                   (PRCO_SETOPT, so, level, optname, &m0));
  796.         error = ENOPROTOOPT;
  797.     } else {
  798.         switch (optname) {
  799.  
  800.         case SO_LINGER:
  801.             if (m == NULL || m->m_len != sizeof (struct linger)) {
  802.                 error = EINVAL;
  803.                 goto bad;
  804.             }
  805.             so->so_linger = mtod(m, struct linger *)->l_linger;
  806.             /* fall thru... */
  807.  
  808.         case SO_DEBUG:
  809.         case SO_KEEPALIVE:
  810.         case SO_DONTROUTE:
  811.         case SO_USELOOPBACK:
  812.         case SO_BROADCAST:
  813.         case SO_REUSEADDR:
  814.         case SO_OOBINLINE:
  815.             if (m == NULL || m->m_len < sizeof (int)) {
  816.                 error = EINVAL;
  817.                 goto bad;
  818.             }
  819.             if (*mtod(m, int *))
  820.                 so->so_options |= optname;
  821.             else
  822.                 so->so_options &= ~optname;
  823.             break;
  824.  
  825.         case SO_SNDBUF:
  826.         case SO_RCVBUF:
  827.         case SO_SNDLOWAT:
  828.         case SO_RCVLOWAT:
  829.             if (m == NULL || m->m_len < sizeof (int)) {
  830.                 error = EINVAL;
  831.                 goto bad;
  832.             }
  833.             switch (optname) {
  834.  
  835.             case SO_SNDBUF:
  836.             case SO_RCVBUF:
  837.                 if (sbreserve(optname == SO_SNDBUF ?
  838.                     &so->so_snd : &so->so_rcv,
  839.                     (u_long) *mtod(m, int *)) == 0) {
  840.                     error = ENOBUFS;
  841.                     goto bad;
  842.                 }
  843.                 break;
  844.  
  845.             case SO_SNDLOWAT:
  846.                 so->so_snd.sb_lowat = *mtod(m, int *);
  847.                 break;
  848.             case SO_RCVLOWAT:
  849.                 so->so_rcv.sb_lowat = *mtod(m, int *);
  850.                 break;
  851.             }
  852.             break;
  853.  
  854.         case SO_SNDTIMEO:
  855.         case SO_RCVTIMEO:
  856.             {
  857.             struct timeval *tv;
  858.             short val;
  859.  
  860.             if (m == NULL || m->m_len < sizeof (*tv)) {
  861.                 error = EINVAL;
  862.                 goto bad;
  863.             }
  864.             tv = mtod(m, struct timeval *);
  865.             if (tv->tv_sec > SHRT_MAX / hz - hz) {
  866.                 error = EDOM;
  867.                 goto bad;
  868.             }
  869.             val = tv->tv_sec * hz + tv->tv_usec / tick;
  870.  
  871.             switch (optname) {
  872.  
  873.             case SO_SNDTIMEO:
  874.                 so->so_snd.sb_timeo = val;
  875.                 break;
  876.             case SO_RCVTIMEO:
  877.                 so->so_rcv.sb_timeo = val;
  878.                 break;
  879.             }
  880.             break;
  881.             }
  882.  
  883.         default:
  884.             error = ENOPROTOOPT;
  885.             break;
  886.         }
  887.     }
  888. bad:
  889.     if (m)
  890.         (void) m_free(m);
  891.     return (error);
  892. }
  893.  
  894. sogetopt(so, level, optname, mp)
  895.     register struct socket *so;
  896.     int level, optname;
  897.     struct mbuf **mp;
  898. {
  899.     register struct mbuf *m;
  900.  
  901.     if (level != SOL_SOCKET) {
  902.         if (so->so_proto && so->so_proto->pr_ctloutput) {
  903.             return ((*so->so_proto->pr_ctloutput)
  904.                   (PRCO_GETOPT, so, level, optname, mp));
  905.         } else
  906.             return (ENOPROTOOPT);
  907.     } else {
  908.         m = m_get(M_WAIT, MT_SOOPTS);
  909.         m->m_len = sizeof (int);
  910.  
  911.         switch (optname) {
  912.  
  913.         case SO_LINGER:
  914.             m->m_len = sizeof (struct linger);
  915.             mtod(m, struct linger *)->l_onoff =
  916.                 so->so_options & SO_LINGER;
  917.             mtod(m, struct linger *)->l_linger = so->so_linger;
  918.             break;
  919.  
  920.         case SO_USELOOPBACK:
  921.         case SO_DONTROUTE:
  922.         case SO_DEBUG:
  923.         case SO_KEEPALIVE:
  924.         case SO_REUSEADDR:
  925.         case SO_BROADCAST:
  926.         case SO_OOBINLINE:
  927.             *mtod(m, int *) = so->so_options & optname;
  928.             break;
  929.  
  930.         case SO_TYPE:
  931.             *mtod(m, int *) = so->so_type;
  932.             break;
  933.  
  934.         case SO_ERROR:
  935.             *mtod(m, int *) = so->so_error;
  936.             so->so_error = 0;
  937.             break;
  938.  
  939.         case SO_SNDBUF:
  940.             *mtod(m, int *) = so->so_snd.sb_hiwat;
  941.             break;
  942.  
  943.         case SO_RCVBUF:
  944.             *mtod(m, int *) = so->so_rcv.sb_hiwat;
  945.             break;
  946.  
  947.         case SO_SNDLOWAT:
  948.             *mtod(m, int *) = so->so_snd.sb_lowat;
  949.             break;
  950.  
  951.         case SO_RCVLOWAT:
  952.             *mtod(m, int *) = so->so_rcv.sb_lowat;
  953.             break;
  954.  
  955.         case SO_SNDTIMEO:
  956.         case SO_RCVTIMEO:
  957.             {
  958.             int val = (optname == SO_SNDTIMEO ?
  959.                  so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
  960.  
  961.             m->m_len = sizeof(struct timeval);
  962.             mtod(m, struct timeval *)->tv_sec = val / hz;
  963.             mtod(m, struct timeval *)->tv_usec =
  964.                 (val % hz) / tick;
  965.             break;
  966.             }
  967.  
  968.         default:
  969.             (void)m_free(m);
  970.             return (ENOPROTOOPT);
  971.         }
  972.         *mp = m;
  973.         return (0);
  974.     }
  975. }
  976.  
  977. sohasoutofband(so)
  978.     register struct socket *so;
  979. {
  980.     struct proc *p;
  981.  
  982.     if (so->so_pgid < 0)
  983.         gsignal(-so->so_pgid, SIGURG);
  984.     else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
  985.         psignal(p, SIGURG);
  986.     if (so->so_rcv.sb_sel) {
  987.         selwakeup(so->so_rcv.sb_sel, so->so_rcv.sb_flags & SB_COLL);
  988.         so->so_rcv.sb_sel = 0;
  989.         so->so_rcv.sb_flags &= ~SB_COLL;
  990.     }
  991. }
  992.