1 /* $NetBSD: uipc_domain.c,v 1.34 2001/02/11 06:38:46 itojun 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 "opt_inet.h" 39 #include "opt_ipsec.h" 40 #include "opt_atalk.h" 41 #include "opt_ccitt.h" 42 #include "opt_iso.h" 43 #include "opt_ns.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 <uvm/uvm_extern.h> 58 #include <sys/sysctl.h> 59 60 void pffasttimo __P((void *)); 61 void pfslowtimo __P((void *)); 62 63 struct callout pffasttimo_ch, pfslowtimo_ch; 64 65 /* 66 * Current time values for fast and slow timeouts. We can use u_int 67 * relatively safely. The fast timer will roll over in 27 years and 68 * the slow timer in 68 years. 69 */ 70 u_int pfslowtimo_now; 71 u_int pffasttimo_now; 72 73 #define ADDDOMAIN(x) { \ 74 extern struct domain __CONCAT(x,domain); \ 75 __CONCAT(x,domain.dom_next) = domains; \ 76 domains = &__CONCAT(x,domain); \ 77 } 78 79 void 80 domaininit() 81 { 82 struct domain *dp; 83 struct protosw *pr; 84 85 #undef unix 86 /* 87 * KAME NOTE: ADDDOMAIN(route) is moved to the last part so that 88 * it will be initialized as the *first* element. confusing! 89 */ 90 #ifndef lint 91 ADDDOMAIN(unix); 92 #ifdef INET 93 ADDDOMAIN(inet); 94 #endif 95 #ifdef INET6 96 ADDDOMAIN(inet6); 97 #endif 98 #ifdef NS 99 ADDDOMAIN(ns); 100 #endif 101 #ifdef ISO 102 ADDDOMAIN(iso); 103 #endif 104 #ifdef CCITT 105 ADDDOMAIN(ccitt); 106 #endif 107 #ifdef NATM 108 ADDDOMAIN(natm); 109 #endif 110 #ifdef NETATALK 111 ADDDOMAIN(atalk); 112 #endif 113 #ifdef IPSEC 114 ADDDOMAIN(key); 115 #endif 116 #ifdef INET 117 #if NARP > 0 118 ADDDOMAIN(arp); 119 #endif 120 #endif 121 ADDDOMAIN(route); 122 #endif /* ! lint */ 123 124 for (dp = domains; dp; dp = dp->dom_next) { 125 if (dp->dom_init) 126 (*dp->dom_init)(); 127 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 128 if (pr->pr_init) 129 (*pr->pr_init)(); 130 } 131 132 if (max_linkhdr < 16) /* XXX */ 133 max_linkhdr = 16; 134 max_hdr = max_linkhdr + max_protohdr; 135 max_datalen = MHLEN - max_hdr; 136 137 callout_init(&pffasttimo_ch); 138 callout_init(&pfslowtimo_ch); 139 140 callout_reset(&pffasttimo_ch, 1, pffasttimo, NULL); 141 callout_reset(&pfslowtimo_ch, 1, pfslowtimo, NULL); 142 } 143 144 struct domain * 145 pffinddomain(family) 146 int family; 147 { 148 struct domain *dp; 149 150 for (dp = domains; dp != NULL; dp = dp->dom_next) 151 if (dp->dom_family == family) 152 return (dp); 153 return (NULL); 154 } 155 156 struct protosw * 157 pffindtype(family, type) 158 int family, type; 159 { 160 struct domain *dp; 161 struct protosw *pr; 162 163 dp = pffinddomain(family); 164 if (dp == NULL) 165 return (NULL); 166 167 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 168 if (pr->pr_type && pr->pr_type == type) 169 return (pr); 170 171 return (NULL); 172 } 173 174 struct protosw * 175 pffindproto(family, protocol, type) 176 int family, protocol, type; 177 { 178 struct domain *dp; 179 struct protosw *pr; 180 struct protosw *maybe = NULL; 181 182 if (family == 0) 183 return (NULL); 184 185 dp = pffinddomain(family); 186 if (dp == NULL) 187 return (NULL); 188 189 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { 190 if ((pr->pr_protocol == protocol) && (pr->pr_type == type)) 191 return (pr); 192 193 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW && 194 pr->pr_protocol == 0 && maybe == NULL) 195 maybe = pr; 196 } 197 return (maybe); 198 } 199 200 int 201 net_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 202 int *name; 203 u_int namelen; 204 void *oldp; 205 size_t *oldlenp; 206 void *newp; 207 size_t newlen; 208 struct proc *p; 209 { 210 struct domain *dp; 211 struct protosw *pr; 212 int family, protocol; 213 214 /* 215 * All sysctl names at this level are nonterminal. 216 * PF_KEY: next component is protocol family, and then at least one 217 * additional component. 218 * usually: next two components are protocol family and protocol 219 * number, then at least one addition component. 220 */ 221 if (namelen < 2) 222 return (EISDIR); /* overloaded */ 223 family = name[0]; 224 225 if (family == 0) 226 return (0); 227 228 dp = pffinddomain(family); 229 if (dp == NULL) 230 return (ENOPROTOOPT); 231 232 switch (family) { 233 #ifdef IPSEC 234 case PF_KEY: 235 pr = dp->dom_protosw; 236 if (pr->pr_sysctl) 237 return ((*pr->pr_sysctl)(name + 1, namelen - 1, 238 oldp, oldlenp, newp, newlen)); 239 return (ENOPROTOOPT); 240 #endif 241 default: 242 break; 243 } 244 if (namelen < 3) 245 return (EISDIR); /* overloaded */ 246 protocol = name[1]; 247 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 248 if (pr->pr_protocol == protocol && pr->pr_sysctl) 249 return ((*pr->pr_sysctl)(name + 2, namelen - 2, 250 oldp, oldlenp, newp, newlen)); 251 return (ENOPROTOOPT); 252 } 253 254 void 255 pfctlinput(cmd, sa) 256 int cmd; 257 struct sockaddr *sa; 258 { 259 struct domain *dp; 260 struct protosw *pr; 261 262 for (dp = domains; dp; dp = dp->dom_next) 263 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 264 if (pr->pr_ctlinput) 265 (*pr->pr_ctlinput)(cmd, sa, NULL); 266 } 267 268 void 269 pfctlinput2(cmd, sa, ctlparam) 270 int cmd; 271 struct sockaddr *sa; 272 void *ctlparam; 273 { 274 struct domain *dp; 275 struct protosw *pr; 276 277 if (!sa) 278 return; 279 for (dp = domains; dp; dp = dp->dom_next) { 280 /* 281 * the check must be made by xx_ctlinput() anyways, to 282 * make sure we use data item pointed to by ctlparam in 283 * correct way. the following check is made just for safety. 284 */ 285 if (dp->dom_family != sa->sa_family) 286 continue; 287 288 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 289 if (pr->pr_ctlinput) 290 (*pr->pr_ctlinput)(cmd, sa, ctlparam); 291 } 292 } 293 294 void 295 pfslowtimo(arg) 296 void *arg; 297 { 298 struct domain *dp; 299 struct protosw *pr; 300 301 pfslowtimo_now++; 302 303 for (dp = domains; dp; dp = dp->dom_next) 304 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 305 if (pr->pr_slowtimo) 306 (*pr->pr_slowtimo)(); 307 callout_reset(&pfslowtimo_ch, hz / 2, pfslowtimo, NULL); 308 } 309 310 void 311 pffasttimo(arg) 312 void *arg; 313 { 314 struct domain *dp; 315 struct protosw *pr; 316 317 pffasttimo_now++; 318 319 for (dp = domains; dp; dp = dp->dom_next) 320 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 321 if (pr->pr_fasttimo) 322 (*pr->pr_fasttimo)(); 323 callout_reset(&pffasttimo_ch, hz / 5, pffasttimo, NULL); 324 } 325