1 /* $OpenBSD: uipc_domain.c,v 1.59 2021/05/25 22:45:09 bluhm 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/time.h> 41 #include <sys/systm.h> 42 #include <sys/sysctl.h> 43 #include <sys/timeout.h> 44 45 #include "bpfilter.h" 46 #include "pflow.h" 47 48 const struct domain *const domains[] = { 49 #ifdef MPLS 50 &mplsdomain, 51 #endif 52 #if defined (IPSEC) || defined (TCP_SIGNATURE) 53 &pfkeydomain, 54 #endif 55 #ifdef INET6 56 &inet6domain, 57 #endif /* INET6 */ 58 &inetdomain, 59 &unixdomain, 60 &routedomain, 61 NULL 62 }; 63 64 void pffasttimo(void *); 65 void pfslowtimo(void *); 66 const struct domain * pffinddomain(int); 67 68 void 69 domaininit(void) 70 { 71 const struct domain *dp; 72 const struct protosw *pr; 73 static struct timeout pffast_timeout; 74 static struct timeout pfslow_timeout; 75 int i; 76 77 for (i = 0; (dp = domains[i]) != NULL; i++) { 78 if (dp->dom_init) 79 (*dp->dom_init)(); 80 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 81 if (pr->pr_init) 82 (*pr->pr_init)(); 83 } 84 85 /* 86 * max_linkhdr of 64 was chosen to encompass tunnelling 87 * traffic in IP payloads, eg, by etherip(4) or gif(4), 88 * without needing to prepend an mbuf to fit those 89 * headers. 90 */ 91 if (max_linkhdr < 64) 92 max_linkhdr = 64; 93 94 max_hdr = max_linkhdr + max_protohdr; 95 timeout_set_proc(&pffast_timeout, pffasttimo, &pffast_timeout); 96 timeout_set_proc(&pfslow_timeout, pfslowtimo, &pfslow_timeout); 97 timeout_add(&pffast_timeout, 1); 98 timeout_add(&pfslow_timeout, 1); 99 } 100 101 const struct domain * 102 pffinddomain(int family) 103 { 104 const struct domain *dp; 105 int i; 106 107 for (i = 0; (dp = domains[i]) != NULL; i++) { 108 if (dp->dom_family == family) 109 return (dp); 110 } 111 return (NULL); 112 } 113 114 const struct protosw * 115 pffindtype(int family, int type) 116 { 117 const struct domain *dp; 118 const struct protosw *pr; 119 120 dp = pffinddomain(family); 121 if (dp == NULL) 122 return (NULL); 123 124 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 125 if (pr->pr_type && pr->pr_type == type) 126 return (pr); 127 return (NULL); 128 } 129 130 const struct protosw * 131 pffindproto(int family, int protocol, int type) 132 { 133 const struct domain *dp; 134 const struct protosw *pr; 135 const struct protosw *maybe = NULL; 136 137 if (family == PF_UNSPEC) 138 return (NULL); 139 140 dp = pffinddomain(family); 141 if (dp == NULL) 142 return (NULL); 143 144 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { 145 if ((pr->pr_protocol == protocol) && (pr->pr_type == type)) 146 return (pr); 147 148 if (type == SOCK_RAW && pr->pr_type == SOCK_RAW && 149 pr->pr_protocol == 0 && maybe == NULL) 150 maybe = pr; 151 } 152 return (maybe); 153 } 154 155 static int 156 net_link_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 157 void *newp, size_t newlen) 158 { 159 int node; 160 int error; 161 162 /* 163 * All sysctl names at this level are nonterminal. 164 */ 165 if (namelen < 2) 166 return (EISDIR); /* overloaded */ 167 node = name[0]; 168 169 namelen--; 170 name++; 171 172 switch (node) { 173 case NET_LINK_IFRXQ: 174 error = net_ifiq_sysctl(name, namelen, oldp, oldlenp, 175 newp, newlen); 176 break; 177 178 default: 179 error = ENOPROTOOPT; 180 break; 181 } 182 183 return (error); 184 } 185 186 int 187 net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 188 size_t newlen, struct proc *p) 189 { 190 const struct domain *dp; 191 const struct protosw *pr; 192 int error, family, protocol; 193 194 /* 195 * All sysctl names at this level are nonterminal. 196 * Usually: next two components are protocol family and protocol 197 * number, then at least one addition component. 198 */ 199 if (namelen < 2) 200 return (EISDIR); /* overloaded */ 201 family = name[0]; 202 203 if (family == PF_UNSPEC) 204 return (0); 205 if (family == PF_LINK) 206 return (net_link_sysctl(name + 1, namelen - 1, oldp, oldlenp, 207 newp, newlen)); 208 if (family == PF_UNIX) 209 return (uipc_sysctl(name + 1, namelen - 1, oldp, oldlenp, 210 newp, newlen)); 211 #if NBPFILTER > 0 212 if (family == PF_BPF) 213 return (bpf_sysctl(name + 1, namelen - 1, oldp, oldlenp, 214 newp, newlen)); 215 #endif 216 #if NPFLOW > 0 217 if (family == PF_PFLOW) 218 return (pflow_sysctl(name + 1, namelen - 1, oldp, oldlenp, 219 newp, newlen)); 220 #endif 221 #ifdef PIPEX 222 if (family == PF_PIPEX) 223 return (pipex_sysctl(name + 1, namelen - 1, oldp, oldlenp, 224 newp, newlen)); 225 #endif 226 #ifdef MPLS 227 if (family == PF_MPLS) 228 return (mpls_sysctl(name + 1, namelen - 1, oldp, oldlenp, 229 newp, newlen)); 230 #endif 231 dp = pffinddomain(family); 232 if (dp == NULL) 233 return (ENOPROTOOPT); 234 235 if (namelen < 3) 236 return (EISDIR); /* overloaded */ 237 protocol = name[1]; 238 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 239 if (pr->pr_protocol == protocol && pr->pr_sysctl) { 240 error = (*pr->pr_sysctl)(name + 2, namelen - 2, 241 oldp, oldlenp, newp, newlen); 242 return (error); 243 } 244 return (ENOPROTOOPT); 245 } 246 247 void 248 pfctlinput(int cmd, struct sockaddr *sa) 249 { 250 const struct domain *dp; 251 const struct protosw *pr; 252 int i; 253 254 NET_ASSERT_LOCKED(); 255 256 for (i = 0; (dp = domains[i]) != NULL; i++) { 257 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 258 if (pr->pr_ctlinput) 259 (*pr->pr_ctlinput)(cmd, sa, 0, NULL); 260 } 261 } 262 263 void 264 pfslowtimo(void *arg) 265 { 266 struct timeout *to = (struct timeout *)arg; 267 const struct domain *dp; 268 const struct protosw *pr; 269 int i; 270 271 for (i = 0; (dp = domains[i]) != NULL; i++) { 272 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 273 if (pr->pr_slowtimo) 274 (*pr->pr_slowtimo)(); 275 } 276 timeout_add_msec(to, 500); 277 } 278 279 void 280 pffasttimo(void *arg) 281 { 282 struct timeout *to = (struct timeout *)arg; 283 const struct domain *dp; 284 const struct protosw *pr; 285 int i; 286 287 for (i = 0; (dp = domains[i]) != NULL; i++) { 288 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 289 if (pr->pr_fasttimo) 290 (*pr->pr_fasttimo)(); 291 } 292 timeout_add_msec(to, 200); 293 } 294