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 /*      $NetBSD: uipc_domain.c,v 1.50 2005/03/09 05:07:19 atatat Exp $  */
    2 
    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.3 (Berkeley) 2/14/95
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: uipc_domain.c,v 1.50 2005/03/09 05:07:19 atatat Exp $");
   36 
   37 #include <sys/param.h>
   38 #include <sys/socket.h>
   39 #include <sys/socketvar.h>
   40 #include <sys/protosw.h>
   41 #include <sys/domain.h>
   42 #include <sys/mbuf.h>
   43 #include <sys/time.h>
   44 #include <sys/kernel.h>
   45 #include <sys/systm.h>
   46 #include <sys/callout.h>
   47 #include <sys/queue.h>
   48 #include <sys/proc.h>
   49 #include <sys/sysctl.h>
   50 #include <sys/un.h>
   51 #include <sys/unpcb.h>
   52 #include <sys/file.h>
   53 
   54 void    pffasttimo(void *);
   55 void    pfslowtimo(void *);
   56 
   57 struct domainhead domains = STAILQ_HEAD_INITIALIZER(domains);
   58 
   59 struct callout pffasttimo_ch, pfslowtimo_ch;
   60 
   61 /*
   62  * Current time values for fast and slow timeouts.  We can use u_int
   63  * relatively safely.  The fast timer will roll over in 27 years and
   64  * the slow timer in 68 years.
   65  */
   66 u_int   pfslowtimo_now;
   67 u_int   pffasttimo_now;
   68 
   69 void
   70 domaininit()
   71 {
   72         __link_set_decl(domains, struct domain);
   73         struct domain * const * dpp;
   74         struct domain *rt_domain = NULL;
   75 
   76         /*
   77          * Add all of the domains.  Make sure the PF_ROUTE
   78          * domain is added last.
   79          */
   80         __link_set_foreach(dpp, domains) {
   81                 if ((*dpp)->dom_family == PF_ROUTE)
   82                         rt_domain = *dpp;
   83                 else
   84                         domain_attach(*dpp);
   85         }
   86         if (rt_domain)
   87                 domain_attach(rt_domain);
   88 
   89         callout_init(&pffasttimo_ch);
   90         callout_init(&pfslowtimo_ch);
   91 
   92         callout_reset(&pffasttimo_ch, 1, pffasttimo, NULL);
   93         callout_reset(&pfslowtimo_ch, 1, pfslowtimo, NULL);
   94 }
   95 
   96 void
   97 domain_attach(struct domain *dp)
   98 {
   99         const struct protosw *pr;
  100 
  101         STAILQ_INSERT_TAIL(&domains, dp, dom_link);
  102 
  103         if (dp->dom_init)
  104                 (*dp->dom_init)();
  105 
  106 #ifdef MBUFTRACE
  107         if (dp->dom_mowner.mo_name[0] == '\0') {
  108                 strncpy(dp->dom_mowner.mo_name, dp->dom_name,
  109                     sizeof(dp->dom_mowner.mo_name));
  110                 MOWNER_ATTACH(&dp->dom_mowner);
  111         }
  112 #endif
  113         for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
  114                 if (pr->pr_init)
  115                         (*pr->pr_init)();
  116         }
  117 
  118         if (max_linkhdr < 16)           /* XXX */
  119                 max_linkhdr = 16;
  120         max_hdr = max_linkhdr + max_protohdr;
  121         max_datalen = MHLEN - max_hdr;
  122 }
  123 
  124 struct domain *
  125 pffinddomain(int family)
  126 {
  127         struct domain *dp;
  128 
  129         DOMAIN_FOREACH(dp)
  130                 if (dp->dom_family == family)
  131                         return (dp);
  132         return (NULL);
  133 }
  134 
  135 const struct protosw *
  136 pffindtype(int family, int type)
  137 {
  138         struct domain *dp;
  139         const struct protosw *pr;
  140 
  141         dp = pffinddomain(family);
  142         if (dp == NULL)
  143                 return (NULL);
  144 
  145         for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
  146                 if (pr->pr_type && pr->pr_type == type)
  147                         return (pr);
  148 
  149         return (NULL);
  150 }
  151 
  152 const struct protosw *
  153 pffindproto(int family, int protocol, int type)
  154 {
  155         struct domain *dp;
  156         const struct protosw *pr;
  157         const struct protosw *maybe = NULL;
  158 
  159         if (family == 0)
  160                 return (NULL);
  161 
  162         dp = pffinddomain(family);
  163         if (dp == NULL)
  164                 return (NULL);
  165 
  166         for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
  167                 if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
  168                         return (pr);
  169 
  170                 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
  171                     pr->pr_protocol == 0 && maybe == NULL)
  172                         maybe = pr;
  173         }
  174         return (maybe);
  175 }
  176 
  177 /*
  178  * sysctl helper to stuff PF_LOCAL pcbs into sysctl structures
  179  */
  180 static void
  181 sysctl_dounpcb(struct kinfo_pcb *pcb, const struct socket *so)
  182 {
  183         struct unpcb *unp = sotounpcb(so);
  184         struct sockaddr_un *un = unp->unp_addr;
  185 
  186         memset(pcb, 0, sizeof(*pcb));
  187 
  188         pcb->ki_family = so->so_proto->pr_domain->dom_family;
  189         pcb->ki_type = so->so_proto->pr_type;
  190         pcb->ki_protocol = so->so_proto->pr_protocol;
  191         pcb->ki_pflags = unp->unp_flags;
  192 
  193         pcb->ki_pcbaddr = PTRTOUINT64(unp);
  194         /* pcb->ki_ppcbaddr = unp has no ppcb... */
  195         pcb->ki_sockaddr = PTRTOUINT64(so);
  196 
  197         pcb->ki_sostate = so->so_state;
  198         /* pcb->ki_prstate = unp has no state... */
  199 
  200         pcb->ki_rcvq = so->so_rcv.sb_cc;
  201         pcb->ki_sndq = so->so_snd.sb_cc;
  202 
  203         un = (struct sockaddr_un *)&pcb->ki_src;
  204         /*
  205          * local domain sockets may bind without having a local
  206          * endpoint.  bleah!
  207          */
  208         if (unp->unp_addr != NULL) {
  209                 un->sun_len = unp->unp_addr->sun_len;
  210                 un->sun_family = unp->unp_addr->sun_family;
  211                 strlcpy(un->sun_path, unp->unp_addr->sun_path,
  212                     sizeof(pcb->ki_s));
  213         }
  214         else {
  215                 un->sun_len = offsetof(struct sockaddr_un, sun_path);
  216                 un->sun_family = pcb->ki_family;
  217         }
  218         if (unp->unp_conn != NULL) {
  219                 un = (struct sockaddr_un *)&pcb->ki_dst;
  220                 if (unp->unp_conn->unp_addr != NULL) {
  221                         un->sun_len = unp->unp_conn->unp_addr->sun_len;
  222                         un->sun_family = unp->unp_conn->unp_addr->sun_family;
  223                         un->sun_family = unp->unp_conn->unp_addr->sun_family;
  224                         strlcpy(un->sun_path, unp->unp_conn->unp_addr->sun_path,
  225                                 sizeof(pcb->ki_d));
  226                 }
  227                 else {
  228                         un->sun_len = offsetof(struct sockaddr_un, sun_path);
  229                         un->sun_family = pcb->ki_family;
  230                 }
  231         }
  232 
  233         pcb->ki_inode = unp->unp_ino;
  234         pcb->ki_vnode = PTRTOUINT64(unp->unp_vnode);
  235         pcb->ki_conn = PTRTOUINT64(unp->unp_conn);
  236         pcb->ki_refs = PTRTOUINT64(unp->unp_refs);
  237         pcb->ki_nextref = PTRTOUINT64(unp->unp_nextref);
  238 }
  239 
  240 static int
  241 sysctl_unpcblist(SYSCTLFN_ARGS)
  242 {
  243         struct file *fp;
  244         struct socket *so;
  245         struct kinfo_pcb pcb;
  246         char *dp;
  247         u_int op, arg;
  248         size_t len, needed, elem_size, out_size;
  249         int error, elem_count, pf, type, pf2;
  250 
  251         if (namelen == 1 && name[0] == CTL_QUERY)
  252                 return (sysctl_query(SYSCTLFN_CALL(rnode)));
  253 
  254         if (namelen != 4)
  255                 return (EINVAL);
  256 
  257         error = 0;
  258         dp = oldp;
  259         len = (oldp != NULL) ? *oldlenp : 0;
  260         op = name[0];
  261         arg = name[1];
  262         elem_size = name[2];
  263         elem_count = name[3];
  264         out_size = MIN(sizeof(pcb), elem_size);
  265         needed = 0;
  266 
  267         elem_count = INT_MAX;
  268         elem_size = out_size = sizeof(pcb);
  269 
  270         if (name - oname != 4)
  271                 return (EINVAL);
  272 
  273         pf = oname[1];
  274         type = oname[2];
  275         pf2 = (oldp == NULL) ? 0 : pf;
  276 
  277         /*
  278          * there's no "list" of local domain sockets, so we have
  279          * to walk the file list looking for them.  :-/
  280          */
  281         LIST_FOREACH(fp, &filehead, f_list) {
  282                 if (fp->f_type != DTYPE_SOCKET)
  283                         continue;
  284                 so = (struct socket *)fp->f_data;
  285                 if (so->so_type != type)
  286                         continue;
  287                 if (so->so_proto->pr_domain->dom_family != pf)
  288                         continue;
  289                 if (len >= elem_size && elem_count > 0) {
  290                         sysctl_dounpcb(&pcb, so);
  291                         error = copyout(&pcb, dp, out_size);
  292                         if (error)
  293                                 break;
  294                         dp += elem_size;
  295                         len -= elem_size;
  296                 }
  297                 if (elem_count > 0) {
  298                         needed += elem_size;
  299                         if (elem_count != INT_MAX)
  300                                 elem_count--;
  301                 }
  302         }
  303 
  304         *oldlenp = needed;
  305         if (oldp == NULL)
  306                 *oldlenp += PCB_SLOP * sizeof(struct kinfo_pcb);
  307 
  308         return (error);
  309 }
  310 
  311 SYSCTL_SETUP(sysctl_net_setup, "sysctl net subtree setup")
  312 {
  313         sysctl_createv(clog, 0, NULL, NULL,
  314                        CTLFLAG_PERMANENT,
  315                        CTLTYPE_NODE, "net", NULL,
  316                        NULL, 0, NULL, 0,
  317                        CTL_NET, CTL_EOL);
  318         sysctl_createv(clog, 0, NULL, NULL,
  319                        CTLFLAG_PERMANENT,
  320                        CTLTYPE_NODE, "local",
  321                        SYSCTL_DESCR("PF_LOCAL related settings"),
  322                        NULL, 0, NULL, 0,
  323                        CTL_NET, PF_LOCAL, CTL_EOL);
  324         sysctl_createv(clog, 0, NULL, NULL,
  325                        CTLFLAG_PERMANENT,
  326                        CTLTYPE_NODE, "stream",
  327                        SYSCTL_DESCR("SOCK_STREAM settings"),
  328                        NULL, 0, NULL, 0,
  329                        CTL_NET, PF_LOCAL, SOCK_STREAM, CTL_EOL);
  330         sysctl_createv(clog, 0, NULL, NULL,
  331                        CTLFLAG_PERMANENT,
  332                        CTLTYPE_NODE, "dgram",
  333                        SYSCTL_DESCR("SOCK_DGRAM settings"),
  334                        NULL, 0, NULL, 0,
  335                        CTL_NET, PF_LOCAL, SOCK_DGRAM, CTL_EOL);
  336 
  337         sysctl_createv(clog, 0, NULL, NULL,
  338                        CTLFLAG_PERMANENT,
  339                        CTLTYPE_STRUCT, "pcblist",
  340                        SYSCTL_DESCR("SOCK_STREAM protocol control block list"),
  341                        sysctl_unpcblist, 0, NULL, 0,
  342                        CTL_NET, PF_LOCAL, SOCK_STREAM, CTL_CREATE, CTL_EOL);
  343         sysctl_createv(clog, 0, NULL, NULL,
  344                        CTLFLAG_PERMANENT,
  345                        CTLTYPE_STRUCT, "pcblist",
  346                        SYSCTL_DESCR("SOCK_DGRAM protocol control block list"),
  347                        sysctl_unpcblist, 0, NULL, 0,
  348                        CTL_NET, PF_LOCAL, SOCK_DGRAM, CTL_CREATE, CTL_EOL);
  349 }
  350 
  351 void
  352 pfctlinput(int cmd, struct sockaddr *sa)
  353 {
  354         struct domain *dp;
  355         const struct protosw *pr;
  356 
  357         DOMAIN_FOREACH(dp)
  358                 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
  359                         if (pr->pr_ctlinput)
  360                                 (*pr->pr_ctlinput)(cmd, sa, NULL);
  361 }
  362 
  363 void
  364 pfctlinput2(int cmd, struct sockaddr *sa, void *ctlparam)
  365 {
  366         struct domain *dp;
  367         const struct protosw *pr;
  368 
  369         if (!sa)
  370                 return;
  371 
  372         DOMAIN_FOREACH(dp) {
  373                 /*
  374                  * the check must be made by xx_ctlinput() anyways, to
  375                  * make sure we use data item pointed to by ctlparam in
  376                  * correct way.  the following check is made just for safety.
  377                  */
  378                 if (dp->dom_family != sa->sa_family)
  379                         continue;
  380 
  381                 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
  382                         if (pr->pr_ctlinput)
  383                                 (*pr->pr_ctlinput)(cmd, sa, ctlparam);
  384         }
  385 }
  386 
  387 void
  388 pfslowtimo(void *arg)
  389 {
  390         struct domain *dp;
  391         const struct protosw *pr;
  392 
  393         pfslowtimo_now++;
  394 
  395         DOMAIN_FOREACH(dp) {
  396                 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
  397                         if (pr->pr_slowtimo)
  398                                 (*pr->pr_slowtimo)();
  399         }
  400         callout_reset(&pfslowtimo_ch, hz / 2, pfslowtimo, NULL);
  401 }
  402 
  403 void
  404 pffasttimo(void *arg)
  405 {
  406         struct domain *dp;
  407         const struct protosw *pr;
  408 
  409         pffasttimo_now++;
  410 
  411         DOMAIN_FOREACH(dp) {
  412                 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
  413                         if (pr->pr_fasttimo)
  414                                 (*pr->pr_fasttimo)();
  415         }
  416         callout_reset(&pffasttimo_ch, hz / 5, pffasttimo, NULL);
  417 }

Cache object: 7f310b4f310f299856624035c57c6a00


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