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