Exemple #1
0
static bool
npf_log(npf_cache_t *npc, nbuf_t *nbuf, void *meta, int *decision)
{
	struct mbuf *m = nbuf_head_mbuf(nbuf);
	const npf_ext_log_t *log = meta;
	ifnet_t *ifp;
	int family;

	/* Set the address family. */
	if (npf_iscached(npc, NPC_IP4)) {
		family = AF_INET;
	} else if (npf_iscached(npc, NPC_IP6)) {
		family = AF_INET6;
	} else {
		family = AF_UNSPEC;
	}

	KERNEL_LOCK(1, NULL);

	/* Find a pseudo-interface to log. */
	ifp = if_byindex(log->if_idx);
	if (ifp == NULL) {
		/* No interface. */
		KERNEL_UNLOCK_ONE(NULL);
		return true;
	}

	/* Pass through BPF. */
	ifp->if_opackets++;
	ifp->if_obytes += m->m_pkthdr.len;
	bpf_mtap_af(ifp, family, m);
	KERNEL_UNLOCK_ONE(NULL);

	return true;
}
Exemple #2
0
/*
 * generate standard sockaddr_in6 from embedded form.
 */
int
sa6_recoverscope(struct sockaddr_in6 *sin6)
{
	uint32_t zoneid;

	if (sin6->sin6_scope_id != 0) {
		log(LOG_NOTICE,
		    "sa6_recoverscope: assumption failure (non 0 ID): %s%%%d\n",
		    ip6_sprintf(&sin6->sin6_addr), sin6->sin6_scope_id);
		/* XXX: proceed anyway... */
	}
	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) ||
	    IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr)) {
		/*
		 * KAME assumption: link id == interface id
		 */
		zoneid = ntohs(sin6->sin6_addr.s6_addr16[1]);
		if (zoneid) {
			int s = pserialize_read_enter();
			if (!if_byindex(zoneid)) {
				pserialize_read_exit(s);
				return (ENXIO);
			}
			pserialize_read_exit(s);
			sin6->sin6_addr.s6_addr16[1] = 0;
			sin6->sin6_scope_id = zoneid;
		}
	}

	return 0;
}
Exemple #3
0
/*
 * Validate the specified scope zone ID in the sin6_scope_id field.  If the ID
 * is unspecified (=0), needs to be specified, and the default zone ID can be
 * used, the default value will be used.
 * This routine then generates the kernel-internal form: if the address scope
 * of is interface-local or link-local, embed the interface index in the
 * address.
 */
int
sa6_embedscope(struct sockaddr_in6 *sin6, int defaultok)
{
	struct ifnet *ifp;
	uint32_t zoneid;

	if ((zoneid = sin6->sin6_scope_id) == 0 && defaultok)
		zoneid = scope6_addr2default(&sin6->sin6_addr);

	if (zoneid != 0 &&
	    (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) ||
	    IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr))) {
		int s;
		/*
		 * At this moment, we only check interface-local and
		 * link-local scope IDs, and use interface indices as the
		 * zone IDs assuming a one-to-one mapping between interfaces
		 * and links.
		 */
		s = pserialize_read_enter();
		ifp = if_byindex(zoneid);
		if (ifp == NULL) {
			pserialize_read_exit(s);
			return (ENXIO);
		}
		pserialize_read_exit(s);

		/* XXX assignment to 16bit from 32bit variable */
		sin6->sin6_addr.s6_addr16[1] = htons(zoneid & 0xffff);

		sin6->sin6_scope_id = 0;
	}

	return 0;
}
Exemple #4
0
int
scope6_set(struct ifnet *ifp, const struct scope6_id *idlist)
{
	int i;
	int error = 0;
	struct scope6_id *sid = SID(ifp);

	if (!sid)	/* paranoid? */
		return (EINVAL);

	/*
	 * XXX: We need more consistency checks of the relationship among
	 * scopes (e.g. an organization should be larger than a site).
	 */

	/*
	 * TODO(XXX): after setting, we should reflect the changes to
	 * interface addresses, routing table entries, PCB entries...
	 */

	for (i = 0; i < 16; i++) {
		if (idlist->s6id_list[i] &&
		    idlist->s6id_list[i] != sid->s6id_list[i]) {
			int s;
			/*
			 * An interface zone ID must be the corresponding
			 * interface index by definition.
			 */
			if (i == IPV6_ADDR_SCOPE_INTFACELOCAL &&
			    idlist->s6id_list[i] != ifp->if_index)
				return (EINVAL);

			s = pserialize_read_enter();
			if (i == IPV6_ADDR_SCOPE_LINKLOCAL &&
			    !if_byindex(idlist->s6id_list[i])) {
				/*
				 * XXX: theoretically, there should be no
				 * relationship between link IDs and interface
				 * IDs, but we check the consistency for
				 * safety in later use.
				 */
				pserialize_read_exit(s);
				return (EINVAL);
			}
			pserialize_read_exit(s);

			/*
			 * XXX: we must need lots of work in this case,
			 * but we simply set the new value in this initial
			 * implementation.
			 */
			sid->s6id_list[i] = idlist->s6id_list[i];
		}
	}

	return (error);
}
Exemple #5
0
/*
 * Add a mif to the mif table
 */
static int
add_m6if(struct mif6ctl *mifcp)
{
	struct mif6 *mifp;
	struct ifnet *ifp;
	struct sockaddr_in6 sin6;
	int error, s;
#ifdef notyet
	struct tbf *m_tbf = tbftable + mifcp->mif6c_mifi;
#endif

	if (mifcp->mif6c_mifi >= MAXMIFS)
		return EINVAL;
	mifp = mif6table + mifcp->mif6c_mifi;
	if (mifp->m6_ifp)
		return EADDRINUSE; /* XXX: is it appropriate? */
	if (!mifcp->mif6c_pifi || (ifp = if_byindex(mifcp->mif6c_pifi)) == NULL)
		return ENXIO;

	if (mifcp->mif6c_flags & MIFF_REGISTER) {
		ifp = &multicast_register_if6;

		if (reg_mif_num == (mifi_t)-1) {
			strlcpy(ifp->if_xname, "register_mif", 
			    sizeof(ifp->if_xname));
			ifp->if_flags |= IFF_LOOPBACK;
			ifp->if_index = mifcp->mif6c_mifi;
			reg_mif_num = mifcp->mif6c_mifi;
			if_attach(ifp);
		}

	} /* if REGISTER */
	else {
		/* Make sure the interface supports multicast */
		if ((ifp->if_flags & IFF_MULTICAST) == 0)
			return EOPNOTSUPP;

		s = splsoftnet();
		/*
		 * Enable promiscuous reception of all IPv6 multicasts
		 * from the interface.
		 */
		sin6.sin6_family = AF_INET6;
		sin6.sin6_addr = in6addr_any;
		error = if_mcast_op(ifp, SIOCADDMULTI, sin6tosa(&sin6));
		splx(s);
		if (error)
			return error;
	}

	s = splsoftnet();
	mifp->m6_flags     = mifcp->mif6c_flags;
	mifp->m6_ifp       = ifp;
#ifdef notyet
	/* scaling up here allows division by 1024 in critical code */
	mifp->m6_rate_limit = mifcp->mif6c_rate_limit * 1024 / 1000;
#endif
	/* initialize per mif pkt counters */
	mifp->m6_pkt_in    = 0;
	mifp->m6_pkt_out   = 0;
	mifp->m6_bytes_in  = 0;
	mifp->m6_bytes_out = 0;
	splx(s);

	/* Adjust nummifs up if the mifi is higher than nummifs */
	if (nummifs <= mifcp->mif6c_mifi)
		nummifs = mifcp->mif6c_mifi + 1;

#ifdef MRT6DEBUG
	if (mrt6debug)
		log(LOG_DEBUG,
		    "add_mif #%d, phyint %s\n",
		    mifcp->mif6c_mifi, ifp->if_xname);
#endif

	return 0;
}