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/kern/uipc_domain.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  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 1982, 1986, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)uipc_domain.c       8.2 (Berkeley) 10/18/93
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD$");
   36 
   37 #include <sys/param.h>
   38 #include <sys/socket.h>
   39 #include <sys/protosw.h>
   40 #include <sys/domain.h>
   41 #include <sys/eventhandler.h>
   42 #include <sys/epoch.h>
   43 #include <sys/mbuf.h>
   44 #include <sys/kernel.h>
   45 #include <sys/lock.h>
   46 #include <sys/mutex.h>
   47 #include <sys/rmlock.h>
   48 #include <sys/socketvar.h>
   49 #include <sys/systm.h>
   50 
   51 #include <machine/atomic.h>
   52 
   53 #include <net/vnet.h>
   54 
   55 struct domainhead domains = SLIST_HEAD_INITIALIZER(&domains);
   56 int domain_init_status = 1;
   57 static struct mtx dom_mtx;              /* domain list lock */
   58 MTX_SYSINIT(domain, &dom_mtx, "domain list", MTX_DEF);
   59 
   60 static int
   61 pr_accept_notsupp(struct socket *so, struct sockaddr **nam)
   62 {
   63         return (EOPNOTSUPP);
   64 }
   65 
   66 static int
   67 pr_aio_queue_notsupp(struct socket *so, struct kaiocb *job)
   68 {
   69         return (EOPNOTSUPP);
   70 }
   71 
   72 static int
   73 pr_bind_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td)
   74 {
   75         return (EOPNOTSUPP);
   76 }
   77 
   78 static int
   79 pr_bindat_notsupp(int fd, struct socket *so, struct sockaddr *nam,
   80     struct thread *td)
   81 {
   82         return (EOPNOTSUPP);
   83 }
   84 
   85 static int
   86 pr_connect_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td)
   87 {
   88         return (EOPNOTSUPP);
   89 }
   90 
   91 static int
   92 pr_connectat_notsupp(int fd, struct socket *so, struct sockaddr *nam,
   93     struct thread *td)
   94 {
   95         return (EOPNOTSUPP);
   96 }
   97 
   98 static int
   99 pr_connect2_notsupp(struct socket *so1, struct socket *so2)
  100 {
  101         return (EOPNOTSUPP);
  102 }
  103 
  104 static int
  105 pr_control_notsupp(struct socket *so, u_long cmd, void *data,
  106     struct ifnet *ifp, struct thread *td)
  107 {
  108         return (EOPNOTSUPP);
  109 }
  110 
  111 static int
  112 pr_disconnect_notsupp(struct socket *so)
  113 {
  114         return (EOPNOTSUPP);
  115 }
  116 
  117 static int
  118 pr_listen_notsupp(struct socket *so, int backlog, struct thread *td)
  119 {
  120         return (EOPNOTSUPP);
  121 }
  122 
  123 static int
  124 pr_peeraddr_notsupp(struct socket *so, struct sockaddr **nam)
  125 {
  126         return (EOPNOTSUPP);
  127 }
  128 
  129 static int
  130 pr_rcvd_notsupp(struct socket *so, int flags)
  131 {
  132         return (EOPNOTSUPP);
  133 }
  134 
  135 static int
  136 pr_rcvoob_notsupp(struct socket *so, struct mbuf *m, int flags)
  137 {
  138         return (EOPNOTSUPP);
  139 }
  140 
  141 static int
  142 pr_send_notsupp(struct socket *so, int flags, struct mbuf *m,
  143     struct sockaddr *addr, struct mbuf *control, struct thread *td)
  144 {
  145         if (control != NULL)
  146                 m_freem(control);
  147         if ((flags & PRUS_NOTREADY) == 0)
  148                 m_freem(m);
  149         return (EOPNOTSUPP);
  150 }
  151 
  152 static int
  153 pr_ready_notsupp(struct socket *so, struct mbuf *m, int count)
  154 {
  155         return (EOPNOTSUPP);
  156 }
  157 
  158 static int
  159 pr_shutdown_notsupp(struct socket *so)
  160 {
  161         return (EOPNOTSUPP);
  162 }
  163 
  164 static int
  165 pr_sockaddr_notsupp(struct socket *so, struct sockaddr **nam)
  166 {
  167         return (EOPNOTSUPP);
  168 }
  169 
  170 static int
  171 pr_sosend_notsupp(struct socket *so, struct sockaddr *addr, struct uio *uio,
  172     struct mbuf *top, struct mbuf *control, int flags, struct thread *td)
  173 {
  174         return (EOPNOTSUPP);
  175 }
  176 
  177 static int
  178 pr_soreceive_notsupp(struct socket *so, struct sockaddr **paddr,
  179     struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
  180 {
  181         return (EOPNOTSUPP);
  182 }
  183 
  184 static int
  185 pr_sopoll_notsupp(struct socket *so, int events, struct ucred *cred,
  186     struct thread *td)
  187 {
  188         return (EOPNOTSUPP);
  189 }
  190 
  191 static void
  192 pr_init(struct domain *dom, struct protosw *pr)
  193 {
  194 
  195         KASSERT(pr->pr_attach != NULL,
  196             ("%s: protocol doesn't have pr_attach", __func__));
  197 
  198         pr->pr_domain = dom;
  199 
  200 #define DEFAULT(foo, bar)       if (pr->foo == NULL) pr->foo = bar
  201         DEFAULT(pr_sosend, sosend_generic);
  202         DEFAULT(pr_soreceive, soreceive_generic);
  203         DEFAULT(pr_sopoll, sopoll_generic);
  204         DEFAULT(pr_setsbopt, sbsetopt);
  205 
  206 #define NOTSUPP(foo)    if (pr->foo == NULL)  pr->foo = foo ## _notsupp
  207         NOTSUPP(pr_accept);
  208         NOTSUPP(pr_aio_queue);
  209         NOTSUPP(pr_bind);
  210         NOTSUPP(pr_bindat);
  211         NOTSUPP(pr_connect);
  212         NOTSUPP(pr_connect2);
  213         NOTSUPP(pr_connectat);
  214         NOTSUPP(pr_control);
  215         NOTSUPP(pr_disconnect);
  216         NOTSUPP(pr_listen);
  217         NOTSUPP(pr_peeraddr);
  218         NOTSUPP(pr_rcvd);
  219         NOTSUPP(pr_rcvoob);
  220         NOTSUPP(pr_send);
  221         NOTSUPP(pr_shutdown);
  222         NOTSUPP(pr_sockaddr);
  223         NOTSUPP(pr_sosend);
  224         NOTSUPP(pr_soreceive);
  225         NOTSUPP(pr_sopoll);
  226         NOTSUPP(pr_ready);
  227 }
  228 
  229 /*
  230  * Add a new protocol domain to the list of supported domains
  231  * Note: you cant unload it again because a socket may be using it.
  232  * XXX can't fail at this time.
  233  */
  234 void
  235 domain_add(struct domain *dp)
  236 {
  237         struct protosw *pr;
  238 
  239         MPASS(IS_DEFAULT_VNET(curvnet));
  240 
  241         if (dp->dom_probe != NULL && (*dp->dom_probe)() != 0)
  242                 return;
  243 
  244         for (int i = 0; i < dp->dom_nprotosw; i++)
  245                 if ((pr = dp->dom_protosw[i]) != NULL)
  246                         pr_init(dp, pr);
  247 
  248         mtx_lock(&dom_mtx);
  249 #ifdef INVARIANTS
  250         struct domain *tmp;
  251         SLIST_FOREACH(tmp, &domains, dom_next)
  252                 MPASS(tmp->dom_family != dp->dom_family);
  253 #endif
  254         SLIST_INSERT_HEAD(&domains, dp, dom_next);
  255         mtx_unlock(&dom_mtx);
  256 }
  257 
  258 void
  259 domain_remove(struct domain *dp)
  260 {
  261 
  262         if ((dp->dom_flags & DOMF_UNLOADABLE) == 0)
  263                 return;
  264 
  265         mtx_lock(&dom_mtx);
  266         SLIST_REMOVE(&domains, dp, domain, dom_next);
  267         mtx_unlock(&dom_mtx);
  268 }
  269 
  270 static void
  271 domainfinalize(void *dummy)
  272 {
  273 
  274         mtx_lock(&dom_mtx);
  275         KASSERT(domain_init_status == 1, ("domainfinalize called too late!"));
  276         domain_init_status = 2;
  277         mtx_unlock(&dom_mtx);   
  278 }
  279 SYSINIT(domainfin, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST, domainfinalize,
  280     NULL);
  281 
  282 struct domain *
  283 pffinddomain(int family)
  284 {
  285         struct domain *dp;
  286 
  287         SLIST_FOREACH(dp, &domains, dom_next)
  288                 if (dp->dom_family == family)
  289                         return (dp);
  290         return (NULL);
  291 }
  292 
  293 struct protosw *
  294 pffindproto(int family, int type, int proto)
  295 {
  296         struct domain *dp;
  297         struct protosw *pr;
  298 
  299         dp = pffinddomain(family);
  300         if (dp == NULL)
  301                 return (NULL);
  302 
  303         for (int i = 0; i < dp->dom_nprotosw; i++)
  304                 if ((pr = dp->dom_protosw[i]) != NULL && pr->pr_type == type &&
  305                     (pr->pr_protocol == 0 || proto == 0 ||
  306                      pr->pr_protocol == proto))
  307                         return (pr);
  308 
  309         return (NULL);
  310 }
  311 
  312 /*
  313  * The caller must make sure that the new protocol is fully set up and ready to
  314  * accept requests before it is registered.
  315  */
  316 int
  317 protosw_register(struct domain *dp, struct protosw *npr)
  318 {
  319         struct protosw **prp;
  320 
  321         MPASS(dp);
  322         MPASS(npr && npr->pr_type > 0 && npr->pr_protocol > 0);
  323 
  324         prp = NULL;
  325         /*
  326          * Protect us against races when two protocol registrations for
  327          * the same protocol happen at the same time.
  328          */
  329         mtx_lock(&dom_mtx);
  330         for (int i = 0; i < dp->dom_nprotosw; i++) {
  331                 if (dp->dom_protosw[i] == NULL) {
  332                         /* Remember the first free spacer. */
  333                         if (prp == NULL)
  334                                 prp = &dp->dom_protosw[i];
  335                 } else {
  336                         /*
  337                          * The new protocol must not yet exist.
  338                          * XXXAO: Check only protocol?
  339                          * XXXGL: Maybe assert that it doesn't exist?
  340                          */
  341                         if ((dp->dom_protosw[i]->pr_type == npr->pr_type) &&
  342                             (dp->dom_protosw[i]->pr_protocol ==
  343                             npr->pr_protocol)) {
  344                                 mtx_unlock(&dom_mtx);
  345                                 return (EEXIST);
  346                         }
  347 
  348                 }
  349         }
  350 
  351         /* If no free spacer is found we can't add the new protocol. */
  352         if (prp == NULL) {
  353                 mtx_unlock(&dom_mtx);
  354                 return (ENOMEM);
  355         }
  356 
  357         pr_init(dp, npr);
  358         *prp = npr;
  359         mtx_unlock(&dom_mtx);
  360 
  361         return (0);
  362 }
  363 
  364 /*
  365  * The caller must make sure the protocol and its functions correctly shut down
  366  * all sockets and release all locks and memory references.
  367  */
  368 int
  369 protosw_unregister(struct protosw *pr)
  370 {
  371         struct domain *dp;
  372         struct protosw **prp;
  373 
  374         dp = pr->pr_domain;
  375         prp = NULL;
  376 
  377         mtx_lock(&dom_mtx);
  378         /* The protocol must exist and only once. */
  379         for (int i = 0; i < dp->dom_nprotosw; i++) {
  380                 if (dp->dom_protosw[i] == pr) {
  381                         KASSERT(prp == NULL,
  382                             ("%s: domain %p protocol %p registered twice\n",
  383                             __func__, dp, pr));
  384                         prp = &dp->dom_protosw[i];
  385                 }
  386         }
  387 
  388         /* Protocol does not exist.  XXXGL: assert that it does? */
  389         if (prp == NULL) {
  390                 mtx_unlock(&dom_mtx);
  391                 return (EPROTONOSUPPORT);
  392         }
  393 
  394         /* De-orbit the protocol and make the slot available again. */
  395         *prp = NULL;
  396         mtx_unlock(&dom_mtx);
  397 
  398         return (0);
  399 }

Cache object: 2fb94dac3c22859204e97e4eef6fc166


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