1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 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. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #include <sys/param.h> 34 #include <sys/socket.h> 35 #include <sys/protosw.h> 36 #include <sys/domain.h> 37 #include <sys/eventhandler.h> 38 #include <sys/epoch.h> 39 #include <sys/mbuf.h> 40 #include <sys/kernel.h> 41 #include <sys/lock.h> 42 #include <sys/mutex.h> 43 #include <sys/rmlock.h> 44 #include <sys/socketvar.h> 45 #include <sys/systm.h> 46 47 #include <machine/atomic.h> 48 49 #include <net/vnet.h> 50 51 struct domainhead domains = SLIST_HEAD_INITIALIZER(&domains); 52 int domain_init_status = 1; 53 static struct mtx dom_mtx; /* domain list lock */ 54 MTX_SYSINIT(domain, &dom_mtx, "domain list", MTX_DEF); 55 56 static int 57 pr_accept_notsupp(struct socket *so, struct sockaddr **nam) 58 { 59 return (EOPNOTSUPP); 60 } 61 62 static int 63 pr_aio_queue_notsupp(struct socket *so, struct kaiocb *job) 64 { 65 return (EOPNOTSUPP); 66 } 67 68 static int 69 pr_bind_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td) 70 { 71 return (EOPNOTSUPP); 72 } 73 74 static int 75 pr_bindat_notsupp(int fd, struct socket *so, struct sockaddr *nam, 76 struct thread *td) 77 { 78 return (EOPNOTSUPP); 79 } 80 81 static int 82 pr_connect_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td) 83 { 84 return (EOPNOTSUPP); 85 } 86 87 static int 88 pr_connectat_notsupp(int fd, struct socket *so, struct sockaddr *nam, 89 struct thread *td) 90 { 91 return (EOPNOTSUPP); 92 } 93 94 static int 95 pr_connect2_notsupp(struct socket *so1, struct socket *so2) 96 { 97 return (EOPNOTSUPP); 98 } 99 100 static int 101 pr_control_notsupp(struct socket *so, u_long cmd, void *data, 102 struct ifnet *ifp, struct thread *td) 103 { 104 return (EOPNOTSUPP); 105 } 106 107 static int 108 pr_disconnect_notsupp(struct socket *so) 109 { 110 return (EOPNOTSUPP); 111 } 112 113 static int 114 pr_listen_notsupp(struct socket *so, int backlog, struct thread *td) 115 { 116 return (EOPNOTSUPP); 117 } 118 119 static int 120 pr_peeraddr_notsupp(struct socket *so, struct sockaddr **nam) 121 { 122 return (EOPNOTSUPP); 123 } 124 125 static int 126 pr_rcvd_notsupp(struct socket *so, int flags) 127 { 128 return (EOPNOTSUPP); 129 } 130 131 static int 132 pr_rcvoob_notsupp(struct socket *so, struct mbuf *m, int flags) 133 { 134 return (EOPNOTSUPP); 135 } 136 137 static int 138 pr_send_notsupp(struct socket *so, int flags, struct mbuf *m, 139 struct sockaddr *addr, struct mbuf *control, struct thread *td) 140 { 141 if (control != NULL) 142 m_freem(control); 143 if ((flags & PRUS_NOTREADY) == 0) 144 m_freem(m); 145 return (EOPNOTSUPP); 146 } 147 148 static int 149 pr_ready_notsupp(struct socket *so, struct mbuf *m, int count) 150 { 151 return (EOPNOTSUPP); 152 } 153 154 static int 155 pr_shutdown_notsupp(struct socket *so) 156 { 157 return (EOPNOTSUPP); 158 } 159 160 static int 161 pr_sockaddr_notsupp(struct socket *so, struct sockaddr **nam) 162 { 163 return (EOPNOTSUPP); 164 } 165 166 static int 167 pr_sosend_notsupp(struct socket *so, struct sockaddr *addr, struct uio *uio, 168 struct mbuf *top, struct mbuf *control, int flags, struct thread *td) 169 { 170 return (EOPNOTSUPP); 171 } 172 173 static int 174 pr_soreceive_notsupp(struct socket *so, struct sockaddr **paddr, 175 struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp) 176 { 177 return (EOPNOTSUPP); 178 } 179 180 static int 181 pr_sopoll_notsupp(struct socket *so, int events, struct ucred *cred, 182 struct thread *td) 183 { 184 return (EOPNOTSUPP); 185 } 186 187 static void 188 pr_init(struct domain *dom, struct protosw *pr) 189 { 190 191 KASSERT(pr->pr_attach != NULL, 192 ("%s: protocol doesn't have pr_attach", __func__)); 193 194 pr->pr_domain = dom; 195 196 #define DEFAULT(foo, bar) if (pr->foo == NULL) pr->foo = bar 197 DEFAULT(pr_sosend, sosend_generic); 198 DEFAULT(pr_soreceive, soreceive_generic); 199 DEFAULT(pr_sopoll, sopoll_generic); 200 DEFAULT(pr_setsbopt, sbsetopt); 201 202 #define NOTSUPP(foo) if (pr->foo == NULL) pr->foo = foo ## _notsupp 203 NOTSUPP(pr_accept); 204 NOTSUPP(pr_aio_queue); 205 NOTSUPP(pr_bind); 206 NOTSUPP(pr_bindat); 207 NOTSUPP(pr_connect); 208 NOTSUPP(pr_connect2); 209 NOTSUPP(pr_connectat); 210 NOTSUPP(pr_control); 211 NOTSUPP(pr_disconnect); 212 NOTSUPP(pr_listen); 213 NOTSUPP(pr_peeraddr); 214 NOTSUPP(pr_rcvd); 215 NOTSUPP(pr_rcvoob); 216 NOTSUPP(pr_send); 217 NOTSUPP(pr_shutdown); 218 NOTSUPP(pr_sockaddr); 219 NOTSUPP(pr_sosend); 220 NOTSUPP(pr_soreceive); 221 NOTSUPP(pr_sopoll); 222 NOTSUPP(pr_ready); 223 } 224 225 /* 226 * Add a new protocol domain to the list of supported domains 227 * Note: you cant unload it again because a socket may be using it. 228 * XXX can't fail at this time. 229 */ 230 void 231 domain_add(struct domain *dp) 232 { 233 struct protosw *pr; 234 235 MPASS(IS_DEFAULT_VNET(curvnet)); 236 237 if (dp->dom_probe != NULL && (*dp->dom_probe)() != 0) 238 return; 239 240 for (int i = 0; i < dp->dom_nprotosw; i++) 241 if ((pr = dp->dom_protosw[i]) != NULL) 242 pr_init(dp, pr); 243 244 mtx_lock(&dom_mtx); 245 #ifdef INVARIANTS 246 struct domain *tmp; 247 SLIST_FOREACH(tmp, &domains, dom_next) 248 MPASS(tmp->dom_family != dp->dom_family); 249 #endif 250 SLIST_INSERT_HEAD(&domains, dp, dom_next); 251 mtx_unlock(&dom_mtx); 252 } 253 254 void 255 domain_remove(struct domain *dp) 256 { 257 258 if ((dp->dom_flags & DOMF_UNLOADABLE) == 0) 259 return; 260 261 mtx_lock(&dom_mtx); 262 SLIST_REMOVE(&domains, dp, domain, dom_next); 263 mtx_unlock(&dom_mtx); 264 } 265 266 static void 267 domainfinalize(void *dummy) 268 { 269 270 mtx_lock(&dom_mtx); 271 KASSERT(domain_init_status == 1, ("domainfinalize called too late!")); 272 domain_init_status = 2; 273 mtx_unlock(&dom_mtx); 274 } 275 SYSINIT(domainfin, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST, domainfinalize, 276 NULL); 277 278 struct domain * 279 pffinddomain(int family) 280 { 281 struct domain *dp; 282 283 SLIST_FOREACH(dp, &domains, dom_next) 284 if (dp->dom_family == family) 285 return (dp); 286 return (NULL); 287 } 288 289 struct protosw * 290 pffindproto(int family, int type, int proto) 291 { 292 struct domain *dp; 293 struct protosw *pr; 294 295 dp = pffinddomain(family); 296 if (dp == NULL) 297 return (NULL); 298 299 for (int i = 0; i < dp->dom_nprotosw; i++) 300 if ((pr = dp->dom_protosw[i]) != NULL && pr->pr_type == type && 301 (pr->pr_protocol == 0 || proto == 0 || 302 pr->pr_protocol == proto)) 303 return (pr); 304 305 return (NULL); 306 } 307 308 /* 309 * The caller must make sure that the new protocol is fully set up and ready to 310 * accept requests before it is registered. 311 */ 312 int 313 protosw_register(struct domain *dp, struct protosw *npr) 314 { 315 struct protosw **prp; 316 317 MPASS(dp); 318 MPASS(npr && npr->pr_type > 0 && npr->pr_protocol > 0); 319 320 prp = NULL; 321 /* 322 * Protect us against races when two protocol registrations for 323 * the same protocol happen at the same time. 324 */ 325 mtx_lock(&dom_mtx); 326 for (int i = 0; i < dp->dom_nprotosw; i++) { 327 if (dp->dom_protosw[i] == NULL) { 328 /* Remember the first free spacer. */ 329 if (prp == NULL) 330 prp = &dp->dom_protosw[i]; 331 } else { 332 /* 333 * The new protocol must not yet exist. 334 * XXXAO: Check only protocol? 335 * XXXGL: Maybe assert that it doesn't exist? 336 */ 337 if ((dp->dom_protosw[i]->pr_type == npr->pr_type) && 338 (dp->dom_protosw[i]->pr_protocol == 339 npr->pr_protocol)) { 340 mtx_unlock(&dom_mtx); 341 return (EEXIST); 342 } 343 344 } 345 } 346 347 /* If no free spacer is found we can't add the new protocol. */ 348 if (prp == NULL) { 349 mtx_unlock(&dom_mtx); 350 return (ENOMEM); 351 } 352 353 pr_init(dp, npr); 354 *prp = npr; 355 mtx_unlock(&dom_mtx); 356 357 return (0); 358 } 359 360 /* 361 * The caller must make sure the protocol and its functions correctly shut down 362 * all sockets and release all locks and memory references. 363 */ 364 int 365 protosw_unregister(struct protosw *pr) 366 { 367 struct domain *dp; 368 struct protosw **prp; 369 370 dp = pr->pr_domain; 371 prp = NULL; 372 373 mtx_lock(&dom_mtx); 374 /* The protocol must exist and only once. */ 375 for (int i = 0; i < dp->dom_nprotosw; i++) { 376 if (dp->dom_protosw[i] == pr) { 377 KASSERT(prp == NULL, 378 ("%s: domain %p protocol %p registered twice\n", 379 __func__, dp, pr)); 380 prp = &dp->dom_protosw[i]; 381 } 382 } 383 384 /* Protocol does not exist. XXXGL: assert that it does? */ 385 if (prp == NULL) { 386 mtx_unlock(&dom_mtx); 387 return (EPROTONOSUPPORT); 388 } 389 390 /* De-orbit the protocol and make the slot available again. */ 391 *prp = NULL; 392 mtx_unlock(&dom_mtx); 393 394 return (0); 395 } 396