1 /* $NetBSD: uipc_domain.c,v 1.44 2003/12/04 19:38:24 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.44 2003/12/04 19:38:24 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 __P((void *)); 60 void pfslowtimo __P((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 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 struct protosw * 165 pffindtype(family, type) 166 int family, type; 167 { 168 struct domain *dp; 169 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 struct protosw * 183 pffindproto(family, protocol, type) 184 int family, protocol, type; 185 { 186 struct domain *dp; 187 struct protosw *pr; 188 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(SYSCTL_PERMANENT, 211 CTLTYPE_NODE, "net", NULL, 212 NULL, 0, NULL, 0, 213 CTL_NET, CTL_EOL); 214 215 sysctl_createv(SYSCTL_PERMANENT, 216 CTLTYPE_NODE, "local", NULL, 217 NULL, 0, NULL, 0, 218 CTL_NET, PF_LOCAL, CTL_EOL); 219 220 /* 221 * other protocols are expected to have their own setup 222 * routines that will do everything. we end up not having 223 * anything at all to do. 224 */ 225 } 226 227 void 228 pfctlinput(cmd, sa) 229 int cmd; 230 struct sockaddr *sa; 231 { 232 struct domain *dp; 233 struct protosw *pr; 234 235 for (dp = domains; dp; dp = dp->dom_next) 236 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 237 if (pr->pr_ctlinput) 238 (*pr->pr_ctlinput)(cmd, sa, NULL); 239 } 240 241 void 242 pfctlinput2(cmd, sa, ctlparam) 243 int cmd; 244 struct sockaddr *sa; 245 void *ctlparam; 246 { 247 struct domain *dp; 248 struct protosw *pr; 249 250 if (!sa) 251 return; 252 for (dp = domains; dp; dp = dp->dom_next) { 253 /* 254 * the check must be made by xx_ctlinput() anyways, to 255 * make sure we use data item pointed to by ctlparam in 256 * correct way. the following check is made just for safety. 257 */ 258 if (dp->dom_family != sa->sa_family) 259 continue; 260 261 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 262 if (pr->pr_ctlinput) 263 (*pr->pr_ctlinput)(cmd, sa, ctlparam); 264 } 265 } 266 267 void 268 pfslowtimo(arg) 269 void *arg; 270 { 271 struct domain *dp; 272 struct protosw *pr; 273 274 pfslowtimo_now++; 275 276 for (dp = domains; dp; dp = dp->dom_next) 277 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 278 if (pr->pr_slowtimo) 279 (*pr->pr_slowtimo)(); 280 callout_reset(&pfslowtimo_ch, hz / 2, pfslowtimo, NULL); 281 } 282 283 void 284 pffasttimo(arg) 285 void *arg; 286 { 287 struct domain *dp; 288 struct protosw *pr; 289 290 pffasttimo_now++; 291 292 for (dp = domains; dp; dp = dp->dom_next) 293 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 294 if (pr->pr_fasttimo) 295 (*pr->pr_fasttimo)(); 296 callout_reset(&pffasttimo_ch, hz / 5, pffasttimo, NULL); 297 } 298