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