int
sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2)
{
	int len, rc;
	struct domain *dom;

	if (sa1->sa_family != sa2->sa_family)
		return sa1->sa_family - sa2->sa_family;

	dom = pffinddomain(sa1->sa_family);

	if (dom != NULL && dom->dom_sockaddr_cmp != NULL)
		return (*dom->dom_sockaddr_cmp)(sa1, sa2);

	len = MIN(sa1->sa_len, sa2->sa_len);

	if (dom == NULL || dom->dom_sa_cmplen == 0) {
		if ((rc = memcmp(sa1, sa2, len)) != 0)
			return rc;
		return sa1->sa_len - sa2->sa_len;
	}

	if ((rc = memcmp((const char *)sa1 + dom->dom_sa_cmpofs,
		         (const char *)sa2 + dom->dom_sa_cmpofs,
			 MIN(dom->dom_sa_cmplen,
			     len - MIN(len, dom->dom_sa_cmpofs)))) != 0)
		return rc;

	return MIN(dom->dom_sa_cmplen + dom->dom_sa_cmpofs, sa1->sa_len) -
	       MIN(dom->dom_sa_cmplen + dom->dom_sa_cmpofs, sa2->sa_len);
}
Exemple #2
0
struct protosw *
pffindproto(int family, int protocol, int type)
{
	struct domain *dp;
	struct protosw *pr;
	struct protosw *maybe;

	maybe = NULL;
	if (family == 0)
		return (NULL);

	dp = pffinddomain(family);
	if (dp == NULL)
		return (NULL);

	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
		if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
			return (pr);

		if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
		    pr->pr_protocol == 0 && maybe == NULL)
			maybe = pr;
	}
	return (maybe);
}
const struct sockaddr *
sockaddr_any_by_family(int family)
{
	const struct domain *dom;

	if ((dom = pffinddomain(family)) == NULL)
		return NULL;

	return dom->dom_sa_any;
}
int
net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
    size_t newlen, struct proc *p)
{
	struct domain *dp;
	struct protosw *pr;
	int family, protocol;

	/*
	 * All sysctl names at this level are nonterminal.
	 * Usually: next two components are protocol family and protocol
	 *	number, then at least one addition component.
	 */
	if (namelen < 2)
		return (EISDIR);		/* overloaded */
	family = name[0];

	if (family == 0)
		return (0);
#if NBPFILTER > 0
	if (family == PF_BPF)
		return (bpf_sysctl(name + 1, namelen - 1, oldp, oldlenp,
		    newp, newlen));
#endif
#if NPFLOW > 0
	if (family == PF_PFLOW)
		return (pflow_sysctl(name + 1, namelen - 1, oldp, oldlenp,
		    newp, newlen));
#endif
#ifdef PIPEX
	if (family == PF_PIPEX)
		return (pipex_sysctl(name + 1, namelen - 1, oldp, oldlenp,
		    newp, newlen));
#endif
	dp = pffinddomain(family);
	if (dp == NULL)
		return (ENOPROTOOPT);
#ifdef MPLS
	/* XXX WARNING: big fat ugly hack */
	/* stupid net.mpls is special as it does not have a protocol */
	if (family == PF_MPLS)
		return (dp->dom_protosw[0].pr_sysctl(name + 1, namelen - 1,
		    oldp, oldlenp, newp, newlen));
#endif

	if (namelen < 3)
		return (EISDIR);		/* overloaded */
	protocol = name[1];
	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
		if (pr->pr_protocol == protocol && pr->pr_sysctl)
			return ((*pr->pr_sysctl)(name + 2, namelen - 2,
			    oldp, oldlenp, newp, newlen));
	return (ENOPROTOOPT);
}
const void *
sockaddr_const_addr(const struct sockaddr *sa, socklen_t *slenp)
{
	const struct domain *dom;

	if ((dom = pffinddomain(sa->sa_family)) == NULL ||
	    dom->dom_sockaddr_const_addr == NULL)
		return NULL;

	return (*dom->dom_sockaddr_const_addr)(sa, slenp);
}
struct sockaddr *
sockaddr_externalize(struct sockaddr *dst, socklen_t socklen,
    const struct sockaddr *src)
{
	struct domain *dom;

	dom = pffinddomain(src->sa_family);

	if (dom != NULL && dom->dom_sockaddr_externalize != NULL)
		return (*dom->dom_sockaddr_externalize)(dst, socklen, src);

	return sockaddr_copy(dst, socklen, src);
}
Exemple #7
0
struct protosw *
pffindtype(int family, int type)
{
	struct domain *dp;
	struct protosw *pr;

	dp = pffinddomain(family);
	if (dp == NULL)
		return (NULL);

	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
		if (pr->pr_type && pr->pr_type == type)
			return (pr);
	return (NULL);
}
Exemple #8
0
/*
 * The caller must make sure the protocol and its functions correctly shut down
 * all sockets and release all locks and memory references.
 */
int
pf_proto_unregister(int family, int protocol, int type)
{
	struct domain *dp;
	struct protosw *pr, *dpr;

	/* Sanity checks. */
	if (family == 0)
		return (EPFNOSUPPORT);
	if (protocol == 0)
		return (EPROTONOSUPPORT);
	if (type == 0)
		return (EPROTOTYPE);

	/* Try to find the specified domain based on the family type. */
	dp = pffinddomain(family);
	if (dp == NULL)
		return (EPFNOSUPPORT);

	dpr = NULL;

	/* Lock out everyone else while we are manipulating the protosw. */
	mtx_lock(&dom_mtx);

	/* The protocol must exist and only once. */
	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
		if ((pr->pr_type == type) && (pr->pr_protocol == protocol)) {
			if (dpr != NULL) {
				mtx_unlock(&dom_mtx);
				return (EMLINK);   /* Should not happen! */
			} else
				dpr = pr;
		}
	}

	/* Protocol does not exist. */
	if (dpr == NULL) {
		mtx_unlock(&dom_mtx);
		return (EPROTONOSUPPORT);
	}

	/* De-orbit the protocol and make the slot available again. */
	dpr->pr_type = 0;
	dpr->pr_domain = dp;
	dpr->pr_protocol = PROTO_SPACER;
	dpr->pr_flags = 0;
	dpr->pr_input = NULL;
	dpr->pr_output = NULL;
	dpr->pr_ctlinput = NULL;
	dpr->pr_ctloutput = NULL;
	dpr->pr_init = NULL;
	dpr->pr_fasttimo = NULL;
	dpr->pr_slowtimo = NULL;
	dpr->pr_drain = NULL;
	dpr->pr_usrreqs = &nousrreqs;

	/* Job is done, not more protection required. */
	mtx_unlock(&dom_mtx);

	return (0);
}
Exemple #9
0
/*
 * 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;

	/* Sanity checks. */
	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);

	/* Try to find the specified domain based on the family. */
	dp = pffinddomain(family);
	if (dp == NULL)
		return (EPFNOSUPPORT);

	/* Initialize backpointer to struct domain. */
	npr->pr_domain = dp;
	fpr = NULL;

	/*
	 * Protect us against races when two protocol registrations for
	 * the same protocol happen at the same time.
	 */
	mtx_lock(&dom_mtx);

	/* The new protocol must not yet exist. */
	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);	/* XXX: Check only protocol? */
		}
		/* While here, remember the first free spacer. */
		if ((fpr == NULL) && (pr->pr_protocol == PROTO_SPACER))
			fpr = pr;
	}

	/* If no free spacer is found we can't add the new protocol. */
	if (fpr == NULL) {
		mtx_unlock(&dom_mtx);
		return (ENOMEM);
	}

	/* Copy the new struct protosw over the spacer. */
	bcopy(npr, fpr, sizeof(*fpr));

	/* Job is done, no more protection required. */
	mtx_unlock(&dom_mtx);

	/* Initialize and activate the protocol. */
	VNET_LIST_RLOCK();
	VNET_FOREACH(vnet_iter) {
		CURVNET_SET_QUIET(vnet_iter);
		protosw_init(fpr);
		CURVNET_RESTORE();
	}
	VNET_LIST_RUNLOCK();

	return (0);
}