[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/uipc_socket.c

Version: -  FREEBSD  -  FREEBSD8  -  FREEBSD7  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

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

Cache object: 474418a22ae0656692e797bae7862c4d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.