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