FreeBSD/sys/kern/uipc_domain.c
/*
 * The caller must make sure that the new protocol is fully set up and ready to
 * accept requests before it is registered.
 */
The caller must make sure that the new protocol is fully set up and ready to
accept requests before it is registered.
The caller must make sure that the new protocol is fully set up and ready to accept requests before it is registered .
int
pf_proto_register(int family, struct protosw *npr)
{
	VNET_ITERATOR_DECL(vnet_iter);
	struct domain *dp;
	struct protosw *pr, *fpr;
	if (family == 0)
		return (EPFNOSUPPORT);
	if (npr->pr_type == 0)
		return (EPROTOTYPE);
	if (npr->pr_protocol == 0)
		return (EPROTONOSUPPORT);
	if (npr->pr_usrreqs == NULL)
		return (ENXIO);
	dp = pffinddomain(family);
	if (dp == NULL)
		return (EPFNOSUPPORT);
	npr->pr_domain = dp;
	fpr = NULL;
	mtx_lock(&dom_mtx);
	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
		if ((pr->pr_type == npr->pr_type) &&
		    (pr->pr_protocol == npr->pr_protocol)) {
			mtx_unlock(&dom_mtx);
			return (EEXIST);	
		}
		if ((fpr == NULL) && (pr->pr_protocol == PROTO_SPACER))
			fpr = pr;
	}
	if (fpr == NULL) {
		mtx_unlock(&dom_mtx);
		return (ENOMEM);
	}
	bcopy(npr, fpr, sizeof(*fpr));
	mtx_unlock(&dom_mtx);
	VNET_LIST_RLOCK();
	VNET_FOREACH(vnet_iter) {
		CURVNET_SET_QUIET(vnet_iter);
		protosw_init(fpr);
		CURVNET_RESTORE();
	}
	VNET_LIST_RUNLOCK();
	return (0);
}
int pf_proto_register ( int family , struct protosw * npr ) { VNET_ITERATOR_DECL ( vnet_iter ) ; struct domain * dp ; struct protosw * pr , * fpr ; if ( family == 0 ) return ( EPFNOSUPPORT ) ; if ( npr -> pr_type == 0 ) return ( EPROTOTYPE ) ; if ( npr -> pr_protocol == 0 ) return ( EPROTONOSUPPORT ) ; if ( npr -> pr_usrreqs == NULL ) return ( ENXIO ) ; dp = pffinddomain ( family ) ; if ( dp == NULL ) return ( EPFNOSUPPORT ) ; npr -> pr_domain = dp ; fpr = NULL ; mtx_lock ( & dom_mtx ) ; for ( pr = dp -> dom_protosw ; pr < dp -> dom_protoswNPROTOSW ; pr ++ ) { if ( ( pr -> pr_type == npr -> pr_type ) && ( pr -> pr_protocol == npr -> pr_protocol ) ) { mtx_unlock ( & dom_mtx ) ; return ( EEXIST ) ; } if ( ( fpr == NULL ) && ( pr -> pr_protocol == PROTO_SPACER ) ) fpr = pr ; } if ( fpr == NULL ) { mtx_unlock ( & dom_mtx ) ; return ( ENOMEM ) ; } bcopy ( npr , fpr , sizeof ( * fpr ) ) ; mtx_unlock ( & dom_mtx ) ; VNET_LIST_RLOCK ( ) ; VNET_FOREACH ( vnet_iter ) { CURVNET_SET_QUIET ( vnet_iter ) ; protosw_init ( fpr ) ; CURVNET_RESTORE ( ) ; } VNET_LIST_RUNLOCK ( ) ; return ( 0 ) ; }
The caller must make sure that the new protocol is fully set up and ready to
 accept requests before it is registered.
The caller must make sure that the new protocol is fully set up and ready to accept requests before it is registered .
/* Sanity checks. */ /* Try to find the specified domain based on the family. */ /* Initialize backpointer to struct domain. */ /*
	 * Protect us against races when two protocol registrations for
	 * the same protocol happen at the same time.
	 */ /* The new protocol must not yet exist. */ /* XXX: Check only protocol? */ /* While here, remember the first free spacer. */ /* If no free spacer is found we can't add the new protocol. */ /* Copy the new struct protosw over the spacer. */ /* Job is done, no more protection required. */ /* Initialize and activate the protocol. */