1 /* $NetBSD: uipc_domain.c,v 1.38 2003/02/26 06:31:11 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)uipc_domain.c 8.3 (Berkeley) 2/14/95 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: uipc_domain.c,v 1.38 2003/02/26 06:31:11 matt Exp $"); 40 41 #include "opt_inet.h" 42 #include "opt_ipsec.h" 43 #include "opt_atalk.h" 44 #include "opt_ccitt.h" 45 #include "opt_iso.h" 46 #include "opt_ns.h" 47 #include "opt_natm.h" 48 #include "arp.h" 49 50 #include <sys/param.h> 51 #include <sys/socket.h> 52 #include <sys/protosw.h> 53 #include <sys/domain.h> 54 #include <sys/mbuf.h> 55 #include <sys/time.h> 56 #include <sys/kernel.h> 57 #include <sys/systm.h> 58 #include <sys/callout.h> 59 #include <sys/proc.h> 60 #include <sys/sysctl.h> 61 62 void pffasttimo __P((void *)); 63 void pfslowtimo __P((void *)); 64 65 struct domain *domains; 66 67 struct callout pffasttimo_ch, pfslowtimo_ch; 68 69 /* 70 * Current time values for fast and slow timeouts. We can use u_int 71 * relatively safely. The fast timer will roll over in 27 years and 72 * the slow timer in 68 years. 73 */ 74 u_int pfslowtimo_now; 75 u_int pffasttimo_now; 76 77 #define ADDDOMAIN(x) { \ 78 extern struct domain __CONCAT(x,domain); \ 79 __CONCAT(x,domain.dom_next) = domains; \ 80 domains = &__CONCAT(x,domain); \ 81 } 82 83 void 84 domaininit() 85 { 86 struct domain *dp; 87 struct protosw *pr; 88 89 #undef unix 90 /* 91 * KAME NOTE: ADDDOMAIN(route) is moved to the last part so that 92 * it will be initialized as the *first* element. confusing! 93 */ 94 #ifndef lint 95 ADDDOMAIN(unix); 96 #ifdef INET 97 ADDDOMAIN(inet); 98 #endif 99 #ifdef INET6 100 ADDDOMAIN(inet6); 101 #endif 102 #ifdef NS 103 ADDDOMAIN(ns); 104 #endif 105 #ifdef ISO 106 ADDDOMAIN(iso); 107 #endif 108 #ifdef CCITT 109 ADDDOMAIN(ccitt); 110 #endif 111 #ifdef NATM 112 ADDDOMAIN(natm); 113 #endif 114 #ifdef NETATALK 115 ADDDOMAIN(atalk); 116 #endif 117 #ifdef IPSEC 118 ADDDOMAIN(key); 119 #endif 120 #ifdef INET 121 #if NARP > 0 122 ADDDOMAIN(arp); 123 #endif 124 #endif 125 ADDDOMAIN(route); 126 #endif /* ! lint */ 127 128 for (dp = domains; dp; dp = dp->dom_next) { 129 if (dp->dom_init) 130 (*dp->dom_init)(); 131 #ifdef MBUFTRACE 132 if (dp->dom_mowner.mo_name[0] == '\0') { 133 strncpy(dp->dom_mowner.mo_name, dp->dom_name, 134 sizeof(dp->dom_mowner.mo_name)); 135 MOWNER_ATTACH(&dp->dom_mowner); 136 } 137 #endif 138 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 139 if (pr->pr_init) 140 (*pr->pr_init)(); 141 } 142 143 if (max_linkhdr < 16) /* XXX */ 144 max_linkhdr = 16; 145 max_hdr = max_linkhdr + max_protohdr; 146 max_datalen = MHLEN - max_hdr; 147 148 callout_init(&pffasttimo_ch); 149 callout_init(&pfslowtimo_ch); 150 151 callout_reset(&pffasttimo_ch, 1, pffasttimo, NULL); 152 callout_reset(&pfslowtimo_ch, 1, pfslowtimo, NULL); 153 } 154 155 struct domain * 156 pffinddomain(family) 157 int family; 158 { 159 struct domain *dp; 160 161 for (dp = domains; dp != NULL; dp = dp->dom_next) 162 if (dp->dom_family == family) 163 return (dp); 164 return (NULL); 165 } 166 167 struct protosw * 168 pffindtype(family, type) 169 int family, type; 170 { 171 struct domain *dp; 172 struct protosw *pr; 173 174 dp = pffinddomain(family); 175 if (dp == NULL) 176 return (NULL); 177 178 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 179 if (pr->pr_type && pr->pr_type == type) 180 return (pr); 181 182 return (NULL); 183 } 184 185 struct protosw * 186 pffindproto(family, protocol, type) 187 int family, protocol, type; 188 { 189 struct domain *dp; 190 struct protosw *pr; 191 struct protosw *maybe = NULL; 192 193 if (family == 0) 194 return (NULL); 195 196 dp = pffinddomain(family); 197 if (dp == NULL) 198 return (NULL); 199 200 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { 201 if ((pr->pr_protocol == protocol) && (pr->pr_type == type)) 202 return (pr); 203 204 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW && 205 pr->pr_protocol == 0 && maybe == NULL) 206 maybe = pr; 207 } 208 return (maybe); 209 } 210 211 int 212 net_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 213 int *name; 214 u_int namelen; 215 void *oldp; 216 size_t *oldlenp; 217 void *newp; 218 size_t newlen; 219 struct proc *p; 220 { 221 struct domain *dp; 222 struct protosw *pr; 223 int family, protocol; 224 225 /* 226 * All sysctl names at this level are nonterminal. 227 * PF_KEY: next component is protocol family, and then at least one 228 * additional component. 229 * usually: next two components are protocol family and protocol 230 * number, then at least one addition component. 231 */ 232 if (namelen < 2) 233 return (EISDIR); /* overloaded */ 234 family = name[0]; 235 236 if (family == 0) 237 return (0); 238 239 dp = pffinddomain(family); 240 if (dp == NULL) 241 return (ENOPROTOOPT); 242 243 switch (family) { 244 #ifdef IPSEC 245 case PF_KEY: 246 pr = dp->dom_protosw; 247 if (pr->pr_sysctl) 248 return ((*pr->pr_sysctl)(name + 1, namelen - 1, 249 oldp, oldlenp, newp, newlen)); 250 return (ENOPROTOOPT); 251 #endif 252 default: 253 break; 254 } 255 if (namelen < 3) 256 return (EISDIR); /* overloaded */ 257 protocol = name[1]; 258 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 259 if (pr->pr_protocol == protocol && pr->pr_sysctl) 260 return ((*pr->pr_sysctl)(name + 2, namelen - 2, 261 oldp, oldlenp, newp, newlen)); 262 return (ENOPROTOOPT); 263 } 264 265 void 266 pfctlinput(cmd, sa) 267 int cmd; 268 struct sockaddr *sa; 269 { 270 struct domain *dp; 271 struct protosw *pr; 272 273 for (dp = domains; dp; dp = dp->dom_next) 274 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 275 if (pr->pr_ctlinput) 276 (*pr->pr_ctlinput)(cmd, sa, NULL); 277 } 278 279 void 280 pfctlinput2(cmd, sa, ctlparam) 281 int cmd; 282 struct sockaddr *sa; 283 void *ctlparam; 284 { 285 struct domain *dp; 286 struct protosw *pr; 287 288 if (!sa) 289 return; 290 for (dp = domains; dp; dp = dp->dom_next) { 291 /* 292 * the check must be made by xx_ctlinput() anyways, to 293 * make sure we use data item pointed to by ctlparam in 294 * correct way. the following check is made just for safety. 295 */ 296 if (dp->dom_family != sa->sa_family) 297 continue; 298 299 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 300 if (pr->pr_ctlinput) 301 (*pr->pr_ctlinput)(cmd, sa, ctlparam); 302 } 303 } 304 305 void 306 pfslowtimo(arg) 307 void *arg; 308 { 309 struct domain *dp; 310 struct protosw *pr; 311 312 pfslowtimo_now++; 313 314 for (dp = domains; dp; dp = dp->dom_next) 315 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 316 if (pr->pr_slowtimo) 317 (*pr->pr_slowtimo)(); 318 callout_reset(&pfslowtimo_ch, hz / 2, pfslowtimo, NULL); 319 } 320 321 void 322 pffasttimo(arg) 323 void *arg; 324 { 325 struct domain *dp; 326 struct protosw *pr; 327 328 pffasttimo_now++; 329 330 for (dp = domains; dp; dp = dp->dom_next) 331 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 332 if (pr->pr_fasttimo) 333 (*pr->pr_fasttimo)(); 334 callout_reset(&pffasttimo_ch, hz / 5, pffasttimo, NULL); 335 } 336