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