1 /* $NetBSD: uipc_domain.c,v 1.37 2002/05/12 20:36:58 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.37 2002/05/12 20:36:58 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 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 132 if (pr->pr_init) 133 (*pr->pr_init)(); 134 } 135 136 if (max_linkhdr < 16) /* XXX */ 137 max_linkhdr = 16; 138 max_hdr = max_linkhdr + max_protohdr; 139 max_datalen = MHLEN - max_hdr; 140 141 callout_init(&pffasttimo_ch); 142 callout_init(&pfslowtimo_ch); 143 144 callout_reset(&pffasttimo_ch, 1, pffasttimo, NULL); 145 callout_reset(&pfslowtimo_ch, 1, pfslowtimo, NULL); 146 } 147 148 struct domain * 149 pffinddomain(family) 150 int family; 151 { 152 struct domain *dp; 153 154 for (dp = domains; dp != NULL; dp = dp->dom_next) 155 if (dp->dom_family == family) 156 return (dp); 157 return (NULL); 158 } 159 160 struct protosw * 161 pffindtype(family, type) 162 int family, type; 163 { 164 struct domain *dp; 165 struct protosw *pr; 166 167 dp = pffinddomain(family); 168 if (dp == NULL) 169 return (NULL); 170 171 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 172 if (pr->pr_type && pr->pr_type == type) 173 return (pr); 174 175 return (NULL); 176 } 177 178 struct protosw * 179 pffindproto(family, protocol, type) 180 int family, protocol, type; 181 { 182 struct domain *dp; 183 struct protosw *pr; 184 struct protosw *maybe = NULL; 185 186 if (family == 0) 187 return (NULL); 188 189 dp = pffinddomain(family); 190 if (dp == NULL) 191 return (NULL); 192 193 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { 194 if ((pr->pr_protocol == protocol) && (pr->pr_type == type)) 195 return (pr); 196 197 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW && 198 pr->pr_protocol == 0 && maybe == NULL) 199 maybe = pr; 200 } 201 return (maybe); 202 } 203 204 int 205 net_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 206 int *name; 207 u_int namelen; 208 void *oldp; 209 size_t *oldlenp; 210 void *newp; 211 size_t newlen; 212 struct proc *p; 213 { 214 struct domain *dp; 215 struct protosw *pr; 216 int family, protocol; 217 218 /* 219 * All sysctl names at this level are nonterminal. 220 * PF_KEY: next component is protocol family, and then at least one 221 * additional component. 222 * usually: next two components are protocol family and protocol 223 * number, then at least one addition component. 224 */ 225 if (namelen < 2) 226 return (EISDIR); /* overloaded */ 227 family = name[0]; 228 229 if (family == 0) 230 return (0); 231 232 dp = pffinddomain(family); 233 if (dp == NULL) 234 return (ENOPROTOOPT); 235 236 switch (family) { 237 #ifdef IPSEC 238 case PF_KEY: 239 pr = dp->dom_protosw; 240 if (pr->pr_sysctl) 241 return ((*pr->pr_sysctl)(name + 1, namelen - 1, 242 oldp, oldlenp, newp, newlen)); 243 return (ENOPROTOOPT); 244 #endif 245 default: 246 break; 247 } 248 if (namelen < 3) 249 return (EISDIR); /* overloaded */ 250 protocol = name[1]; 251 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 252 if (pr->pr_protocol == protocol && pr->pr_sysctl) 253 return ((*pr->pr_sysctl)(name + 2, namelen - 2, 254 oldp, oldlenp, newp, newlen)); 255 return (ENOPROTOOPT); 256 } 257 258 void 259 pfctlinput(cmd, sa) 260 int cmd; 261 struct sockaddr *sa; 262 { 263 struct domain *dp; 264 struct protosw *pr; 265 266 for (dp = domains; dp; dp = dp->dom_next) 267 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 268 if (pr->pr_ctlinput) 269 (*pr->pr_ctlinput)(cmd, sa, NULL); 270 } 271 272 void 273 pfctlinput2(cmd, sa, ctlparam) 274 int cmd; 275 struct sockaddr *sa; 276 void *ctlparam; 277 { 278 struct domain *dp; 279 struct protosw *pr; 280 281 if (!sa) 282 return; 283 for (dp = domains; dp; dp = dp->dom_next) { 284 /* 285 * the check must be made by xx_ctlinput() anyways, to 286 * make sure we use data item pointed to by ctlparam in 287 * correct way. the following check is made just for safety. 288 */ 289 if (dp->dom_family != sa->sa_family) 290 continue; 291 292 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 293 if (pr->pr_ctlinput) 294 (*pr->pr_ctlinput)(cmd, sa, ctlparam); 295 } 296 } 297 298 void 299 pfslowtimo(arg) 300 void *arg; 301 { 302 struct domain *dp; 303 struct protosw *pr; 304 305 pfslowtimo_now++; 306 307 for (dp = domains; dp; dp = dp->dom_next) 308 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 309 if (pr->pr_slowtimo) 310 (*pr->pr_slowtimo)(); 311 callout_reset(&pfslowtimo_ch, hz / 2, pfslowtimo, NULL); 312 } 313 314 void 315 pffasttimo(arg) 316 void *arg; 317 { 318 struct domain *dp; 319 struct protosw *pr; 320 321 pffasttimo_now++; 322 323 for (dp = domains; dp; dp = dp->dom_next) 324 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 325 if (pr->pr_fasttimo) 326 (*pr->pr_fasttimo)(); 327 callout_reset(&pffasttimo_ch, hz / 5, pffasttimo, NULL); 328 } 329