uipc_domain.c revision 92751
1/* 2 * Copyright (c) 1982, 1986, 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_domain.c 8.2 (Berkeley) 10/18/93 34 * $FreeBSD: head/sys/kern/uipc_domain.c 92751 2002-03-20 04:09:59Z jeff $ 35 */ 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/kernel.h> 43#include <sys/socketvar.h> 44#include <sys/systm.h> 45#include <vm/uma.h> 46 47/* 48 * System initialization 49 * 50 * Note: domain initialization takes place on a per domain basis 51 * as a result of traversing a SYSINIT linker set. Most likely, 52 * each domain would want to call DOMAIN_SET(9) itself, which 53 * would cause the domain to be added just after domaininit() 54 * is called during startup. 55 * 56 * See DOMAIN_SET(9) for details on its use. 57 */ 58 59static void domaininit(void *); 60SYSINIT(domain, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, domaininit, NULL) 61 62static struct callout pffast_callout; 63static struct callout pfslow_callout; 64 65static void pffasttimo(void *); 66static void pfslowtimo(void *); 67 68struct domain *domains; 69 70/* 71 * Add a new protocol domain to the list of supported domains 72 * Note: you cant unload it again because a socket may be using it. 73 * XXX can't fail at this time. 74 */ 75static void 76net_init_domain(struct domain *dp) 77{ 78 register struct protosw *pr; 79 int s; 80 81 s = splnet(); 82 if (dp->dom_init) 83 (*dp->dom_init)(); 84 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++){ 85 if (pr->pr_usrreqs == 0) 86 panic("domaininit: %ssw[%d] has no usrreqs!", 87 dp->dom_name, 88 (int)(pr - dp->dom_protosw)); 89 if (pr->pr_init) 90 (*pr->pr_init)(); 91 } 92 /* 93 * update global informatio about maximums 94 */ 95 max_hdr = max_linkhdr + max_protohdr; 96 max_datalen = MHLEN - max_hdr; 97 splx(s); 98} 99 100/* 101 * Add a new protocol domain to the list of supported domains 102 * Note: you cant unload it again because a socket may be using it. 103 * XXX can't fail at this time. 104 */ 105void 106net_add_domain(void *data) 107{ 108 int s; 109 struct domain *dp; 110 111 dp = (struct domain *)data; 112 s = splnet(); 113 dp->dom_next = domains; 114 domains = dp; 115 splx(s); 116 net_init_domain(dp); 117} 118 119/* ARGSUSED*/ 120static void 121domaininit(void *dummy) 122{ 123 /* 124 * Before we do any setup, make sure to initialize the 125 * zone allocator we get struct sockets from. 126 */ 127 128 socket_zone = uma_zcreate("socket", sizeof(struct socket), NULL, NULL, 129 NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); 130 131 if (max_linkhdr < 16) /* XXX */ 132 max_linkhdr = 16; 133 134 callout_init(&pffast_callout, 0); 135 callout_init(&pfslow_callout, 0); 136 137 callout_reset(&pffast_callout, 1, pffasttimo, NULL); 138 callout_reset(&pfslow_callout, 1, pfslowtimo, NULL); 139} 140 141 142struct protosw * 143pffindtype(family, type) 144 int family; 145 int type; 146{ 147 register struct domain *dp; 148 register struct protosw *pr; 149 150 for (dp = domains; dp; dp = dp->dom_next) 151 if (dp->dom_family == family) 152 goto found; 153 return (0); 154found: 155 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 156 if (pr->pr_type && pr->pr_type == type) 157 return (pr); 158 return (0); 159} 160 161struct protosw * 162pffindproto(family, protocol, type) 163 int family; 164 int protocol; 165 int type; 166{ 167 register struct domain *dp; 168 register struct protosw *pr; 169 struct protosw *maybe = 0; 170 171 if (family == 0) 172 return (0); 173 for (dp = domains; dp; dp = dp->dom_next) 174 if (dp->dom_family == family) 175 goto found; 176 return (0); 177found: 178 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { 179 if ((pr->pr_protocol == protocol) && (pr->pr_type == type)) 180 return (pr); 181 182 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW && 183 pr->pr_protocol == 0 && maybe == (struct protosw *)0) 184 maybe = pr; 185 } 186 return (maybe); 187} 188 189void 190pfctlinput(cmd, sa) 191 int cmd; 192 struct sockaddr *sa; 193{ 194 register struct domain *dp; 195 register struct protosw *pr; 196 197 for (dp = domains; dp; dp = dp->dom_next) 198 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 199 if (pr->pr_ctlinput) 200 (*pr->pr_ctlinput)(cmd, sa, (void *)0); 201} 202 203void 204pfctlinput2(cmd, sa, ctlparam) 205 int cmd; 206 struct sockaddr *sa; 207 void *ctlparam; 208{ 209 struct domain *dp; 210 struct protosw *pr; 211 212 if (!sa) 213 return; 214 for (dp = domains; dp; dp = dp->dom_next) { 215 /* 216 * the check must be made by xx_ctlinput() anyways, to 217 * make sure we use data item pointed to by ctlparam in 218 * correct way. the following check is made just for safety. 219 */ 220 if (dp->dom_family != sa->sa_family) 221 continue; 222 223 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 224 if (pr->pr_ctlinput) 225 (*pr->pr_ctlinput)(cmd, sa, ctlparam); 226 } 227} 228 229static void 230pfslowtimo(arg) 231 void *arg; 232{ 233 register struct domain *dp; 234 register struct protosw *pr; 235 236 for (dp = domains; dp; dp = dp->dom_next) 237 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 238 if (pr->pr_slowtimo) 239 (*pr->pr_slowtimo)(); 240 callout_reset(&pfslow_callout, hz/2, pfslowtimo, NULL); 241} 242 243static void 244pffasttimo(arg) 245 void *arg; 246{ 247 register struct domain *dp; 248 register struct protosw *pr; 249 250 for (dp = domains; dp; dp = dp->dom_next) 251 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 252 if (pr->pr_fasttimo) 253 (*pr->pr_fasttimo)(); 254 callout_reset(&pffast_callout, hz/5, pffasttimo, NULL); 255} 256