The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


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

FreeBSD/Linux Kernel Cross Reference
sys/bsd/kern/sys_socket.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*
   26  * Copyright (c) 1982, 1986, 1990, 1993
   27  *      The Regents of the University of California.  All rights reserved.
   28  *
   29  * Redistribution and use in source and binary forms, with or without
   30  * modification, are permitted provided that the following conditions
   31  * are met:
   32  * 1. Redistributions of source code must retain the above copyright
   33  *    notice, this list of conditions and the following disclaimer.
   34  * 2. Redistributions in binary form must reproduce the above copyright
   35  *    notice, this list of conditions and the following disclaimer in the
   36  *    documentation and/or other materials provided with the distribution.
   37  * 3. All advertising materials mentioning features or use of this software
   38  *    must display the following acknowledgement:
   39  *      This product includes software developed by the University of
   40  *      California, Berkeley and its contributors.
   41  * 4. Neither the name of the University nor the names of its contributors
   42  *    may be used to endorse or promote products derived from this software
   43  *    without specific prior written permission.
   44  *
   45  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   55  * SUCH DAMAGE.
   56  *
   57  *      @(#)sys_socket.c        8.1 (Berkeley) 6/10/93
   58  */
   59 
   60 #include <sys/param.h>
   61 #include <sys/systm.h>
   62 #include <sys/file.h>
   63 #include <sys/event.h>
   64 #include <sys/protosw.h>
   65 #include <sys/socket.h>
   66 #include <sys/socketvar.h>
   67 #include <sys/filio.h>                  /* XXX */
   68 #include <sys/sockio.h>
   69 #include <sys/stat.h>
   70 #include <sys/uio.h>
   71 #include <sys/filedesc.h>
   72 
   73 #include <net/if.h>
   74 #include <net/route.h>
   75 
   76 int soo_read __P((struct file *fp, struct uio *uio, 
   77                 struct ucred *cred, int flags, struct proc *p));
   78 int soo_write __P((struct file *fp, struct uio *uio, 
   79                 struct ucred *cred, int flags, struct proc *p));
   80 int soo_close __P((struct file *fp, struct proc *p));
   81 
   82 int soo_select __P((struct file *fp, int which, void * wql, struct proc *p));
   83 
   84 int soo_kqfilter __P((struct file *fp, struct knote *kn, struct proc *p));
   85 
   86 struct  fileops socketops =
   87     { soo_read, soo_write, soo_ioctl, soo_select, soo_close, soo_kqfilter };
   88 
   89 /* ARGSUSED */
   90 int
   91 soo_read(fp, uio, cred, flags, p)
   92         struct file *fp;
   93         struct uio *uio;
   94         struct ucred *cred;
   95         int flags;
   96         struct proc *p;
   97 {
   98         struct socket *so;
   99         struct kextcb *kp;
  100         int stat;
  101         int (*fsoreceive) __P((struct socket *so, 
  102                                struct sockaddr **paddr,
  103                                struct uio *uio, struct mbuf **mp0,
  104                                struct mbuf **controlp, int *flagsp));
  105 
  106 
  107         thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  108 
  109         if ((so = (struct socket *)fp->f_data) == NULL) {
  110                 /* This is not a valid open file descriptor */
  111                 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  112                 return (EBADF);
  113         }
  114 
  115         fsoreceive = so->so_proto->pr_usrreqs->pru_soreceive;
  116         if (fsoreceive != soreceive)
  117         {       kp = sotokextcb(so);
  118                 while (kp)
  119                 {       if (kp->e_soif && kp->e_soif->sf_soreceive)
  120                                 (*kp->e_soif->sf_soreceive)(so, 0, &uio,
  121                                                             0, 0, 0, kp);
  122                         kp = kp->e_next;
  123                 }
  124 
  125         }
  126         
  127         stat = (*fsoreceive)(so, 0, uio, 0, 0, 0);
  128         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  129         return stat;
  130 }
  131 
  132 /* ARGSUSED */
  133 int
  134 soo_write(fp, uio, cred, flags, p)
  135         struct file *fp;
  136         struct uio *uio;
  137         struct ucred *cred;
  138         int flags;
  139         struct proc *p;
  140 {
  141         struct socket *so;
  142         int     (*fsosend) __P((struct socket *so, struct sockaddr *addr,
  143                                 struct uio *uio, struct mbuf *top,
  144                                 struct mbuf *control, int flags));
  145         struct kextcb *kp;
  146         int           stat;
  147 
  148         thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  149 
  150         if ((so = (struct socket *)fp->f_data) == NULL) {
  151                 /* This is not a valid open file descriptor */
  152                 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  153                 return (EBADF);
  154         }
  155 
  156         fsosend = so->so_proto->pr_usrreqs->pru_sosend;
  157         if (fsosend != sosend)
  158         {       kp = sotokextcb(so);
  159                 while (kp)
  160                 {       if (kp->e_soif && kp->e_soif->sf_sosend)
  161                         (*kp->e_soif->sf_sosend)(so, 0, &uio,
  162                                                  0, 0, 0, kp);
  163                         kp = kp->e_next;
  164                 }
  165         }
  166 
  167         stat = (*fsosend)(so, 0, uio, 0, 0, 0);
  168         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  169 
  170         /* Generation of SIGPIPE can be controlled per socket */
  171         if (stat == EPIPE && uio->uio_procp && !(so->so_flags & SOF_NOSIGPIPE))
  172             psignal(uio->uio_procp, SIGPIPE);
  173 
  174         return stat;
  175 }
  176 
  177 int
  178 soo_ioctl(fp, cmd, data, p)
  179         struct file *fp;
  180         u_long cmd;
  181         register caddr_t data;
  182         struct proc *p;
  183 {
  184         register struct socket *so;
  185         struct sockopt sopt;
  186         struct kextcb *kp;
  187         int    error = 0;
  188 
  189         thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  190 
  191         if ((so = (struct socket *)fp->f_data) == NULL) {
  192                 /* This is not a valid open file descriptor */
  193                 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  194                 return (EBADF);
  195         }
  196 
  197         kp = sotokextcb(so);
  198         sopt.sopt_level = cmd;
  199         sopt.sopt_name = (int)data;
  200         sopt.sopt_p = p;
  201 
  202         while (kp)
  203         {       if (kp->e_soif && kp->e_soif->sf_socontrol)
  204                         (*kp->e_soif->sf_socontrol)(so, &sopt, kp);
  205                 kp = kp->e_next;
  206         }
  207 
  208         switch (cmd) {
  209 
  210         case FIONBIO:
  211                 if (*(int *)data)
  212                         so->so_state |= SS_NBIO;
  213                 else
  214                         so->so_state &= ~SS_NBIO;
  215 
  216                 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  217                 return (0);
  218 
  219         case FIOASYNC:
  220                 if (*(int *)data) {
  221                         so->so_state |= SS_ASYNC;
  222                         so->so_rcv.sb_flags |= SB_ASYNC;
  223                         so->so_snd.sb_flags |= SB_ASYNC;
  224                 } else {
  225                         so->so_state &= ~SS_ASYNC;
  226                         so->so_rcv.sb_flags &= ~SB_ASYNC;
  227                         so->so_snd.sb_flags &= ~SB_ASYNC;
  228                 }
  229                 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  230                 return (0);
  231 
  232         case FIONREAD:
  233                 *(int *)data = so->so_rcv.sb_cc;
  234                 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  235                 return (0);
  236 
  237         case SIOCSPGRP:
  238                 so->so_pgid = *(int *)data;
  239                 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  240                 return (0);
  241 
  242         case SIOCGPGRP:
  243                 *(int *)data = so->so_pgid;
  244                 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  245                 return (0);
  246 
  247         case SIOCATMARK:
  248              *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
  249                 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  250                 return (0);
  251 
  252         case SIOCSETOT: {
  253              /*
  254               * Set socket level options here and then call protocol
  255               * specific routine.
  256               */
  257              struct socket      *cloned_so = NULL;
  258              int                                cloned_fd = *(int *)data;
  259 
  260              /* let's make sure it's either -1 or a valid file descriptor */
  261              if (cloned_fd != -1) {
  262                   struct file     *cloned_fp;
  263                   error = getsock(p->p_fd, cloned_fd, &cloned_fp);
  264                   if (error) {
  265                        thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  266                        return (error);
  267                   }
  268 
  269                   cloned_so = (struct socket *)cloned_fp->f_data;
  270              }
  271 
  272              /* Always set socket non-blocking for OT */
  273              fp->f_flag |= FNONBLOCK;
  274              so->so_state |= SS_NBIO;
  275              so->so_options |= SO_DONTTRUNC | SO_WANTMORE;
  276           so->so_flags |= SOF_NOSIGPIPE;
  277 
  278              if (cloned_so && so != cloned_so) {
  279                   /* Flags options */
  280                   so->so_options |= cloned_so->so_options & ~SO_ACCEPTCONN;
  281 
  282             /* SO_LINGER */
  283             if (so->so_options & SO_LINGER)
  284                 so->so_linger = cloned_so->so_linger;
  285 
  286             /* SO_SNDBUF, SO_RCVBUF */
  287                   if (cloned_so->so_snd.sb_hiwat > 0) {
  288                        if (sbreserve(&so->so_snd, cloned_so->so_snd.sb_hiwat) == 0) {
  289                             error = ENOBUFS;
  290                             thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  291                             return (error);
  292                        }
  293                   }
  294                   if (cloned_so->so_rcv.sb_hiwat > 0) {
  295                        if (sbreserve(&so->so_rcv, cloned_so->so_rcv.sb_hiwat) == 0) {
  296                             error = ENOBUFS;
  297                             thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  298                             return (error);
  299                        }
  300                   }
  301 
  302                   /* SO_SNDLOWAT, SO_RCVLOWAT */
  303                   so->so_snd.sb_lowat =
  304                        (cloned_so->so_snd.sb_lowat > so->so_snd.sb_hiwat) ?
  305                        so->so_snd.sb_hiwat : cloned_so->so_snd.sb_lowat;
  306                   so->so_rcv.sb_lowat =
  307                        (cloned_so->so_rcv.sb_lowat > so->so_rcv.sb_hiwat) ?
  308                        so->so_rcv.sb_hiwat : cloned_so->so_rcv.sb_lowat;
  309 
  310             /* SO_SNDTIMEO, SO_RCVTIMEO */
  311                   so->so_snd.sb_timeo = cloned_so->so_snd.sb_timeo;
  312                   so->so_rcv.sb_timeo = cloned_so->so_rcv.sb_timeo;
  313              }
  314 
  315              error = (*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, 0, p);
  316              /* Just ignore protocols that do not understand it */
  317              if (error == EOPNOTSUPP)
  318                   error = 0;
  319 
  320              thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  321              return (error);
  322         }
  323         }
  324         /*
  325          * Interface/routing/protocol specific ioctls:
  326          * interface and routing ioctls should have a
  327          * different entry since a socket's unnecessary
  328          */
  329         if (IOCGROUP(cmd) == 'i')
  330              error = ifioctl(so, cmd, data, p);
  331         else 
  332              if (IOCGROUP(cmd) == 'r')
  333                   error = rtioctl(cmd, data, p);
  334              else
  335                   error = (*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, 0, p);
  336 
  337         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  338         return error;
  339 }
  340 
  341 int
  342 soo_select(fp, which, wql, p)
  343         struct file *fp;
  344         int which;
  345         void * wql;
  346         struct proc *p;
  347 {
  348         register struct socket *so = (struct socket *)fp->f_data;
  349         register int s = splnet();
  350         int retnum=0;
  351 
  352         if (so == NULL || so == (struct socket*)-1) goto done;
  353 
  354         switch (which) {
  355 
  356         case FREAD:
  357                 so->so_rcv.sb_flags |= SB_SEL;
  358                 if (soreadable(so)) {
  359                         splx(s);
  360                         retnum = 1;
  361                         so->so_rcv.sb_flags &= ~SB_SEL;
  362                         goto done;
  363                 }
  364                 selrecord(p, &so->so_rcv.sb_sel, wql);
  365                 break;
  366 
  367         case FWRITE:
  368                 so->so_snd.sb_flags |= SB_SEL;
  369                 if (sowriteable(so)) {
  370                         splx(s);
  371                         retnum = 1;
  372                         so->so_snd.sb_flags &= ~SB_SEL;
  373                         goto done;
  374                 }
  375                 selrecord(p, &so->so_snd.sb_sel, wql);
  376                 break;
  377 
  378         case 0:
  379                 so->so_rcv.sb_flags |= SB_SEL;
  380                 if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {
  381                         splx(s);
  382                         retnum = 1;
  383                         so->so_rcv.sb_flags &= ~SB_SEL;
  384                         goto done;
  385                 }
  386                 selrecord(p, &so->so_rcv.sb_sel, wql);
  387                 break;
  388         }
  389         splx(s);
  390 done:
  391         return (retnum);
  392 }
  393 
  394 
  395 int
  396 soo_stat(so, ub)
  397         register struct socket *so;
  398         register struct stat *ub;
  399 {
  400         int stat;
  401 
  402         /*
  403          * DANGER: by the time we get the network funnel the socket 
  404          * may have been closed
  405          */
  406         thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  407         bzero((caddr_t)ub, sizeof (*ub));
  408         ub->st_mode = S_IFSOCK;
  409         stat = (*so->so_proto->pr_usrreqs->pru_sense)(so, ub);
  410         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  411         return stat;
  412 }
  413 
  414 /* ARGSUSED */
  415 int
  416 soo_close(fp, p)
  417         struct file *fp;
  418         struct proc *p;
  419 {
  420         int error = 0;
  421         struct socket *sp;
  422 
  423         sp = (struct socket *)fp->f_data;
  424         fp->f_data = NULL;
  425 
  426         thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
  427 
  428         if (sp)
  429              error = soclose(sp);
  430 
  431         thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
  432 
  433         return (error);
  434 }

Cache object: bd21d2aca64b8e94dd62bf475c629e99


[ 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.