1 /* $NetBSD: uipc_domain.c,v 1.49 2005/01/23 18:41:56 matt 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.49 2005/01/23 18:41:56 matt 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