1 /* $NetBSD: uipc_domain.c,v 1.48 2004/05/25 04:33:59 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.48 2004/05/25 04:33:59 atatat Exp $"); 36 37 #include "opt_inet.h" 38 #include "opt_ipsec.h" 39 #include "opt_atalk.h" 40 #include "opt_ccitt.h" 41 #include "opt_iso.h" 42 #include "opt_ns.h" 43 #include "opt_mbuftrace.h" 44 #include "opt_natm.h" 45 #include "arp.h" 46 47 #include <sys/param.h> 48 #include <sys/socket.h> 49 #include <sys/protosw.h> 50 #include <sys/domain.h> 51 #include <sys/mbuf.h> 52 #include <sys/time.h> 53 #include <sys/kernel.h> 54 #include <sys/systm.h> 55 #include <sys/callout.h> 56 #include <sys/proc.h> 57 #include <sys/sysctl.h> 58 59 void pffasttimo(void *); 60 void pfslowtimo(void *); 61 62 struct domain *domains; 63 64 struct callout pffasttimo_ch, pfslowtimo_ch; 65 66 /* 67 * Current time values for fast and slow timeouts. We can use u_int 68 * relatively safely. The fast timer will roll over in 27 years and 69 * the slow timer in 68 years. 70 */ 71 u_int pfslowtimo_now; 72 u_int pffasttimo_now; 73 74 #define ADDDOMAIN(x) { \ 75 extern struct domain __CONCAT(x,domain); \ 76 __CONCAT(x,domain.dom_next) = domains; \ 77 domains = &__CONCAT(x,domain); \ 78 } 79 80 void 81 domaininit() 82 { 83 struct domain *dp; 84 const struct protosw *pr; 85 86 #undef unix 87 /* 88 * KAME NOTE: ADDDOMAIN(route) is moved to the last part so that 89 * it will be initialized as the *first* element. confusing! 90 */ 91 #ifndef lint 92 ADDDOMAIN(unix); 93 #ifdef INET 94 ADDDOMAIN(inet); 95 #endif 96 #ifdef INET6 97 ADDDOMAIN(inet6); 98 #endif 99 #ifdef NS 100 ADDDOMAIN(ns); 101 #endif 102 #ifdef ISO 103 ADDDOMAIN(iso); 104 #endif 105 #ifdef CCITT 106 ADDDOMAIN(ccitt); 107 #endif 108 #ifdef NATM 109 ADDDOMAIN(natm); 110 #endif 111 #ifdef NETATALK 112 ADDDOMAIN(atalk); 113 #endif 114 #if defined(IPSEC) || defined(FAST_IPSEC) 115 ADDDOMAIN(key); 116 #endif 117 #ifdef INET 118 #if NARP > 0 119 ADDDOMAIN(arp); 120 #endif 121 #endif 122 ADDDOMAIN(route); 123 #endif /* ! lint */ 124 125 for (dp = domains; dp; dp = dp->dom_next) { 126 if (dp->dom_init) 127 (*dp->dom_init)(); 128 #ifdef MBUFTRACE 129 if (dp->dom_mowner.mo_name[0] == '\0') { 130 strncpy(dp->dom_mowner.mo_name, dp->dom_name, 131 sizeof(dp->dom_mowner.mo_name)); 132 MOWNER_ATTACH(&dp->dom_mowner); 133 } 134 #endif 135 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 136 if (pr->pr_init) 137 (*pr->pr_init)(); 138 } 139 140 if (max_linkhdr < 16) /* XXX */ 141 max_linkhdr = 16; 142 max_hdr = max_linkhdr + max_protohdr; 143 max_datalen = MHLEN - max_hdr; 144 145 callout_init(&pffasttimo_ch); 146 callout_init(&pfslowtimo_ch); 147 148 callout_reset(&pffasttimo_ch, 1, pffasttimo, NULL); 149 callout_reset(&pfslowtimo_ch, 1, pfslowtimo, NULL); 150 } 151 152 struct domain * 153 pffinddomain(family) 154 int family; 155 { 156 struct domain *dp; 157 158 for (dp = domains; dp != NULL; dp = dp->dom_next) 159 if (dp->dom_family == family) 160 return (dp); 161 return (NULL); 162 } 163 164 const struct protosw * 165 pffindtype(family, type) 166 int family, type; 167 { 168 struct domain *dp; 169 const struct protosw *pr; 170 171 dp = pffinddomain(family); 172 if (dp == NULL) 173 return (NULL); 174 175 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 176 if (pr->pr_type && pr->pr_type == type) 177 return (pr); 178 179 return (NULL); 180 } 181 182 const struct protosw * 183 pffindproto(family, protocol, type) 184 int family, protocol, type; 185 { 186 struct domain *dp; 187 const struct protosw *pr; 188 const struct protosw *maybe = NULL; 189 190 if (family == 0) 191 return (NULL); 192 193 dp = pffinddomain(family); 194 if (dp == NULL) 195 return (NULL); 196 197 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { 198 if ((pr->pr_protocol == protocol) && (pr->pr_type == type)) 199 return (pr); 200 201 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW && 202 pr->pr_protocol == 0 && maybe == NULL) 203 maybe = pr; 204 } 205 return (maybe); 206 } 207 208 SYSCTL_SETUP(sysctl_net_setup, "sysctl net subtree setup") 209 { 210 sysctl_createv(clog, 0, NULL, NULL, 211 CTLFLAG_PERMANENT, 212 CTLTYPE_NODE, "net", NULL, 213 NULL, 0, NULL, 0, 214 CTL_NET, CTL_EOL); 215 216 sysctl_createv(clog, 0, NULL, NULL, 217 CTLFLAG_PERMANENT, 218 CTLTYPE_NODE, "local", 219 SYSCTL_DESCR("PF_LOCAL related settings"), 220 NULL, 0, NULL, 0, 221 CTL_NET, PF_LOCAL, CTL_EOL); 222 223 /* 224 * other protocols are expected to have their own setup 225 * routines that will do everything. we end up not having 226 * anything at all to do. 227 */ 228 } 229 230 void 231 pfctlinput(cmd, sa) 232 int cmd; 233 struct sockaddr *sa; 234 { 235 struct domain *dp; 236 const struct protosw *pr; 237 238 for (dp = domains; dp; dp = dp->dom_next) 239 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 240 if (pr->pr_ctlinput) 241 (*pr->pr_ctlinput)(cmd, sa, NULL); 242 } 243 244 void 245 pfctlinput2(cmd, sa, ctlparam) 246 int cmd; 247 struct sockaddr *sa; 248 void *ctlparam; 249 { 250 struct domain *dp; 251 const struct protosw *pr; 252 253 if (!sa) 254 return; 255 for (dp = domains; dp; dp = dp->dom_next) { 256 /* 257 * the check must be made by xx_ctlinput() anyways, to 258 * make sure we use data item pointed to by ctlparam in 259 * correct way. the following check is made just for safety. 260 */ 261 if (dp->dom_family != sa->sa_family) 262 continue; 263 264 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 265 if (pr->pr_ctlinput) 266 (*pr->pr_ctlinput)(cmd, sa, ctlparam); 267 } 268 } 269 270 void 271 pfslowtimo(arg) 272 void *arg; 273 { 274 struct domain *dp; 275 const struct protosw *pr; 276 277 pfslowtimo_now++; 278 279 for (dp = domains; dp; dp = dp->dom_next) 280 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 281 if (pr->pr_slowtimo) 282 (*pr->pr_slowtimo)(); 283 callout_reset(&pfslowtimo_ch, hz / 2, pfslowtimo, NULL); 284 } 285 286 void 287 pffasttimo(arg) 288 void *arg; 289 { 290 struct domain *dp; 291 const struct protosw *pr; 292 293 pffasttimo_now++; 294 295 for (dp = domains; dp; dp = dp->dom_next) 296 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 297 if (pr->pr_fasttimo) 298 (*pr->pr_fasttimo)(); 299 callout_reset(&pffasttimo_ch, hz / 5, pffasttimo, NULL); 300 } 301