* The caller must make sure that the new protocol is fully set up and ready to * accept requests before it is registered. */
| 329 | * accept requests before it is registered. |
| 330 | */ |
| 331 | int |
| 332 | pf_proto_register(int family, struct protosw *npr) |
| 333 | { |
| 334 | VNET_ITERATOR_DECL(vnet_iter); |
| 335 | struct domain *dp; |
| 336 | struct protosw *pr, *fpr; |
| 337 | |
| 338 | /* Sanity checks. */ |
| 339 | if (family == 0) |
| 340 | return (EPFNOSUPPORT); |
| 341 | if (npr->pr_type == 0) |
| 342 | return (EPROTOTYPE); |
| 343 | if (npr->pr_protocol == 0) |
| 344 | return (EPROTONOSUPPORT); |
| 345 | if (npr->pr_usrreqs == NULL) |
| 346 | return (ENXIO); |
| 347 | |
| 348 | /* Try to find the specified domain based on the family. */ |
| 349 | dp = pffinddomain(family); |
| 350 | if (dp == NULL) |
| 351 | return (EPFNOSUPPORT); |
| 352 | |
| 353 | /* Initialize backpointer to struct domain. */ |
| 354 | npr->pr_domain = dp; |
| 355 | fpr = NULL; |
| 356 | |
| 357 | /* |
| 358 | * Protect us against races when two protocol registrations for |
| 359 | * the same protocol happen at the same time. |
| 360 | */ |
| 361 | mtx_lock(&dom_mtx); |
| 362 | |
| 363 | /* The new protocol must not yet exist. */ |
| 364 | for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { |
| 365 | if ((pr->pr_type == npr->pr_type) && |
| 366 | (pr->pr_protocol == npr->pr_protocol)) { |
| 367 | mtx_unlock(&dom_mtx); |
| 368 | return (EEXIST); /* XXX: Check only protocol? */ |
| 369 | } |
| 370 | /* While here, remember the first free spacer. */ |
| 371 | if ((fpr == NULL) && (pr->pr_protocol == PROTO_SPACER)) |
| 372 | fpr = pr; |
| 373 | } |
| 374 | |
| 375 | /* If no free spacer is found we can't add the new protocol. */ |
| 376 | if (fpr == NULL) { |
| 377 | mtx_unlock(&dom_mtx); |
| 378 | return (ENOMEM); |
| 379 | } |
| 380 | |
| 381 | /* Copy the new struct protosw over the spacer. */ |
| 382 | bcopy(npr, fpr, sizeof(*fpr)); |
| 383 | |
| 384 | /* Job is done, no more protection required. */ |
| 385 | mtx_unlock(&dom_mtx); |
| 386 | |
| 387 | /* Initialize and activate the protocol. */ |
| 388 | VNET_LIST_RLOCK(); |
no test coverage detected