1 /* $OpenBSD: uipc_domain.c,v 1.60 2022/08/14 01:58:28 jsg Exp $ */ 2 /* $NetBSD: uipc_domain.c,v 1.14 1996/02/09 19:00:44 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)uipc_domain.c 8.2 (Berkeley) 10/18/93 33 */ 34 35 #include <sys/param.h> 36 #include <sys/socket.h> 37 #include <sys/protosw.h> 38 #include <sys/domain.h> 39 #include <sys/mbuf.h> 40 #include <sys/systm.h> 41 #include <sys/sysctl.h> 42 #include <sys/timeout.h> 43 44 #include "bpfilter.h" 45 #include "pflow.h" 46 47 const struct domain *const domains[] = { 48 #ifdef MPLS 49 &mplsdomain, 50 #endif 51 #if defined (IPSEC) || defined (TCP_SIGNATURE) 52 &pfkeydomain, 53 #endif 54 #ifdef INET6 55 &inet6domain, 56 #endif /* INET6 */ 57 &inetdomain, 58 &unixdomain, 59 &routedomain, 60 NULL 61 }; 62 63 void pffasttimo(void *); 64 void pfslowtimo(void *); 65 const struct domain * pffinddomain(int); 66 67 void 68 domaininit(void) 69 { 70 const struct domain *dp; 71 const struct protosw *pr; 72 static struct timeout pffast_timeout; 73 static struct timeout pfslow_timeout; 74 int i; 75 76 for (i = 0; (dp = domains[i]) != NULL; i++) { 77 if (dp->dom_init) 78 (*dp->dom_init)(); 79 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 80 if (pr->pr_init) 81 (*pr->pr_init)(); 82 } 83 84 /* 85 * max_linkhdr of 64 was chosen to encompass tunnelling 86 * traffic in IP payloads, eg, by etherip(4) or gif(4), 87 * without needing to prepend an mbuf to fit those 88 * headers. 89 */ 90 if (max_linkhdr < 64) 91 max_linkhdr = 64; 92 93 max_hdr = max_linkhdr + max_protohdr; 94 timeout_set_proc(&pffast_timeout, pffasttimo, &pffast_timeout); 95 timeout_set_proc(&pfslow_timeout, pfslowtimo, &pfslow_timeout); 96 timeout_add(&pffast_timeout, 1); 97 timeout_add(&pfslow_timeout, 1); 98 } 99 100 const struct domain * 101 pffinddomain(int family) 102 { 103 const struct domain *dp; 104 int i; 105 106 for (i = 0; (dp = domains[i]) != NULL; i++) { 107 if (dp->dom_family == family) 108 return (dp); 109 } 110 return (NULL); 111 } 112 113 const struct protosw * 114 pffindtype(int family, int type) 115 { 116 const struct domain *dp; 117 const struct protosw *pr; 118 119 dp = pffinddomain(family); 120 if (dp == NULL) 121 return (NULL); 122 123 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 124 if (pr->pr_type && pr->pr_type == type) 125 return (pr); 126 return (NULL); 127 } 128 129 const struct protosw * 130 pffindproto(int family, int protocol, int type) 131 { 132 const struct domain *dp; 133 const struct protosw *pr; 134 const struct protosw *maybe = NULL; 135 136 if (family == PF_UNSPEC) 137 return (NULL); 138 139 dp = pffinddomain(family); 140 if (dp == NULL) 141 return (NULL); 142 143 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { 144 if ((pr->pr_protocol == protocol) && (pr->pr_type == type)) 145 return (pr); 146 147 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW && 148 pr->pr_protocol == 0 && maybe == NULL) 149 maybe = pr; 150 } 151 return (maybe); 152 } 153 154 static int 155 net_link_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 156 void *newp, size_t newlen) 157 { 158 int node; 159 int error; 160 161 /* 162 * All sysctl names at this level are nonterminal. 163 */ 164 if (namelen < 2) 165 return (EISDIR); /* overloaded */ 166 node = name[0]; 167 168 namelen--; 169 name++; 170 171 switch (node) { 172 case NET_LINK_IFRXQ: 173 error = net_ifiq_sysctl(name, namelen, oldp, oldlenp, 174 newp, newlen); 175 break; 176 177 default: 178 error = ENOPROTOOPT; 179 break; 180 } 181 182 return (error); 183 } 184 185 int 186 net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 187 size_t newlen, struct proc *p) 188 { 189 const struct domain *dp; 190 const struct protosw *pr; 191 int error, family, protocol; 192 193 /* 194 * All sysctl names at this level are nonterminal. 195 * Usually: next two components are protocol family and protocol 196 * number, then at least one addition component. 197 */ 198 if (namelen < 2) 199 return (EISDIR); /* overloaded */ 200 family = name[0]; 201 202 if (family == PF_UNSPEC) 203 return (0); 204 if (family == PF_LINK) 205 return (net_link_sysctl(name + 1, namelen - 1, oldp, oldlenp, 206 newp, newlen)); 207 if (family == PF_UNIX) 208 return (uipc_sysctl(name + 1, namelen - 1, oldp, oldlenp, 209 newp, newlen)); 210 #if NBPFILTER > 0 211 if (family == PF_BPF) 212 return (bpf_sysctl(name + 1, namelen - 1, oldp, oldlenp, 213 newp, newlen)); 214 #endif 215 #if NPFLOW > 0 216 if (family == PF_PFLOW) 217 return (pflow_sysctl(name + 1, namelen - 1, oldp, oldlenp, 218 newp, newlen)); 219 #endif 220 #ifdef PIPEX 221 if (family == PF_PIPEX) 222 return (pipex_sysctl(name + 1, namelen - 1, oldp, oldlenp, 223 newp, newlen)); 224 #endif 225 #ifdef MPLS 226 if (family == PF_MPLS) 227 return (mpls_sysctl(name + 1, namelen - 1, oldp, oldlenp, 228 newp, newlen)); 229 #endif 230 dp = pffinddomain(family); 231 if (dp == NULL) 232 return (ENOPROTOOPT); 233 234 if (namelen < 3) 235 return (EISDIR); /* overloaded */ 236 protocol = name[1]; 237 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 238 if (pr->pr_protocol == protocol && pr->pr_sysctl) { 239 error = (*pr->pr_sysctl)(name + 2, namelen - 2, 240 oldp, oldlenp, newp, newlen); 241 return (error); 242 } 243 return (ENOPROTOOPT); 244 } 245 246 void 247 pfctlinput(int cmd, struct sockaddr *sa) 248 { 249 const struct domain *dp; 250 const struct protosw *pr; 251 int i; 252 253 NET_ASSERT_LOCKED(); 254 255 for (i = 0; (dp = domains[i]) != NULL; i++) { 256 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 257 if (pr->pr_ctlinput) 258 (*pr->pr_ctlinput)(cmd, sa, 0, NULL); 259 } 260 } 261 262 void 263 pfslowtimo(void *arg) 264 { 265 struct timeout *to = (struct timeout *)arg; 266 const struct domain *dp; 267 const struct protosw *pr; 268 int i; 269 270 for (i = 0; (dp = domains[i]) != NULL; i++) { 271 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 272 if (pr->pr_slowtimo) 273 (*pr->pr_slowtimo)(); 274 } 275 timeout_add_msec(to, 500); 276 } 277 278 void 279 pffasttimo(void *arg) 280 { 281 struct timeout *to = (struct timeout *)arg; 282 const struct domain *dp; 283 const struct protosw *pr; 284 int i; 285 286 for (i = 0; (dp = domains[i]) != NULL; i++) { 287 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 288 if (pr->pr_fasttimo) 289 (*pr->pr_fasttimo)(); 290 } 291 timeout_add_msec(to, 200); 292 } 293