Home | History | Annotate | Line # | Download | only in kern
uipc_domain.c revision 1.41.2.5
      1 /*	$NetBSD: uipc_domain.c,v 1.41.2.5 2005/01/24 08:35:36 skrll 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.41.2.5 2005/01/24 08:35:36 skrll Exp $");
     36 
     37 #include <sys/param.h>
     38 #include <sys/socket.h>
     39 #include <sys/protosw.h>
     40 #include <sys/domain.h>
     41 #include <sys/mbuf.h>
     42 #include <sys/time.h>
     43 #include <sys/kernel.h>
     44 #include <sys/systm.h>
     45 #include <sys/callout.h>
     46 #include <sys/queue.h>
     47 #include <sys/proc.h>
     48 #include <sys/sysctl.h>
     49 
     50 void	pffasttimo(void *);
     51 void	pfslowtimo(void *);
     52 
     53 struct domainhead domains = STAILQ_HEAD_INITIALIZER(domains);
     54 
     55 struct callout pffasttimo_ch, pfslowtimo_ch;
     56 
     57 /*
     58  * Current time values for fast and slow timeouts.  We can use u_int
     59  * relatively safely.  The fast timer will roll over in 27 years and
     60  * the slow timer in 68 years.
     61  */
     62 u_int	pfslowtimo_now;
     63 u_int	pffasttimo_now;
     64 
     65 void
     66 domaininit()
     67 {
     68 	__link_set_decl(domains, struct domain);
     69 	struct domain * const * dpp;
     70 	struct domain *rt_domain = NULL;
     71 
     72 	/*
     73 	 * Add all of the domains.  Make sure the PF_ROUTE
     74 	 * domain is added last.
     75 	 */
     76 	__link_set_foreach(dpp, domains) {
     77 		if ((*dpp)->dom_family == PF_ROUTE)
     78 			rt_domain = *dpp;
     79 		else
     80 			domain_attach(*dpp);
     81 	}
     82 	if (rt_domain)
     83 		domain_attach(rt_domain);
     84 
     85 	callout_init(&pffasttimo_ch);
     86 	callout_init(&pfslowtimo_ch);
     87 
     88 	callout_reset(&pffasttimo_ch, 1, pffasttimo, NULL);
     89 	callout_reset(&pfslowtimo_ch, 1, pfslowtimo, NULL);
     90 }
     91 
     92 void
     93 domain_attach(struct domain *dp)
     94 {
     95 	const struct protosw *pr;
     96 
     97 	STAILQ_INSERT_TAIL(&domains, dp, dom_link);
     98 
     99 	if (dp->dom_init)
    100 		(*dp->dom_init)();
    101 
    102 #ifdef MBUFTRACE
    103 	if (dp->dom_mowner.mo_name[0] == '\0') {
    104 		strncpy(dp->dom_mowner.mo_name, dp->dom_name,
    105 		    sizeof(dp->dom_mowner.mo_name));
    106 		MOWNER_ATTACH(&dp->dom_mowner);
    107 	}
    108 #endif
    109 	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
    110 		if (pr->pr_init)
    111 			(*pr->pr_init)();
    112 	}
    113 
    114 	if (max_linkhdr < 16)		/* XXX */
    115 		max_linkhdr = 16;
    116 	max_hdr = max_linkhdr + max_protohdr;
    117 	max_datalen = MHLEN - max_hdr;
    118 }
    119 
    120 struct domain *
    121 pffinddomain(int family)
    122 {
    123 	struct domain *dp;
    124 
    125 	DOMAIN_FOREACH(dp)
    126 		if (dp->dom_family == family)
    127 			return (dp);
    128 	return (NULL);
    129 }
    130 
    131 const struct protosw *
    132 pffindtype(int family, int type)
    133 {
    134 	struct domain *dp;
    135 	const struct protosw *pr;
    136 
    137 	dp = pffinddomain(family);
    138 	if (dp == NULL)
    139 		return (NULL);
    140 
    141 	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
    142 		if (pr->pr_type && pr->pr_type == type)
    143 			return (pr);
    144 
    145 	return (NULL);
    146 }
    147 
    148 const struct protosw *
    149 pffindproto(int family, int protocol, int type)
    150 {
    151 	struct domain *dp;
    152 	const struct protosw *pr;
    153 	const struct protosw *maybe = NULL;
    154 
    155 	if (family == 0)
    156 		return (NULL);
    157 
    158 	dp = pffinddomain(family);
    159 	if (dp == NULL)
    160 		return (NULL);
    161 
    162 	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
    163 		if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
    164 			return (pr);
    165 
    166 		if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
    167 		    pr->pr_protocol == 0 && maybe == NULL)
    168 			maybe = pr;
    169 	}
    170 	return (maybe);
    171 }
    172 
    173 SYSCTL_SETUP(sysctl_net_setup, "sysctl net subtree setup")
    174 {
    175 	sysctl_createv(clog, 0, NULL, NULL,
    176 		       CTLFLAG_PERMANENT,
    177 		       CTLTYPE_NODE, "net", NULL,
    178 		       NULL, 0, NULL, 0,
    179 		       CTL_NET, CTL_EOL);
    180 
    181 	sysctl_createv(clog, 0, NULL, NULL,
    182 		       CTLFLAG_PERMANENT,
    183 		       CTLTYPE_NODE, "local",
    184 		       SYSCTL_DESCR("PF_LOCAL related settings"),
    185 		       NULL, 0, NULL, 0,
    186 		       CTL_NET, PF_LOCAL, CTL_EOL);
    187 
    188 	/*
    189 	 * other protocols are expected to have their own setup
    190 	 * routines that will do everything.  we end up not having
    191 	 * anything at all to do.
    192 	 */
    193 }
    194 
    195 void
    196 pfctlinput(int cmd, struct sockaddr *sa)
    197 {
    198 	struct domain *dp;
    199 	const struct protosw *pr;
    200 
    201 	DOMAIN_FOREACH(dp)
    202 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
    203 			if (pr->pr_ctlinput)
    204 				(*pr->pr_ctlinput)(cmd, sa, NULL);
    205 }
    206 
    207 void
    208 pfctlinput2(int cmd, struct sockaddr *sa, void *ctlparam)
    209 {
    210 	struct domain *dp;
    211 	const struct protosw *pr;
    212 
    213 	if (!sa)
    214 		return;
    215 
    216 	DOMAIN_FOREACH(dp) {
    217 		/*
    218 		 * the check must be made by xx_ctlinput() anyways, to
    219 		 * make sure we use data item pointed to by ctlparam in
    220 		 * correct way.  the following check is made just for safety.
    221 		 */
    222 		if (dp->dom_family != sa->sa_family)
    223 			continue;
    224 
    225 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
    226 			if (pr->pr_ctlinput)
    227 				(*pr->pr_ctlinput)(cmd, sa, ctlparam);
    228 	}
    229 }
    230 
    231 void
    232 pfslowtimo(void *arg)
    233 {
    234 	struct domain *dp;
    235 	const struct protosw *pr;
    236 
    237 	pfslowtimo_now++;
    238 
    239 	DOMAIN_FOREACH(dp) {
    240 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
    241 			if (pr->pr_slowtimo)
    242 				(*pr->pr_slowtimo)();
    243 	}
    244 	callout_reset(&pfslowtimo_ch, hz / 2, pfslowtimo, NULL);
    245 }
    246 
    247 void
    248 pffasttimo(void *arg)
    249 {
    250 	struct domain *dp;
    251 	const struct protosw *pr;
    252 
    253 	pffasttimo_now++;
    254 
    255 	DOMAIN_FOREACH(dp) {
    256 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
    257 			if (pr->pr_fasttimo)
    258 				(*pr->pr_fasttimo)();
    259 	}
    260 	callout_reset(&pffasttimo_ch, hz / 5, pffasttimo, NULL);
    261 }
    262