Exemple #1
0
static int
ng_iface_output_serialized(struct ifnet *ifp, struct mbuf *m,
			   struct sockaddr *dst, struct rtentry *rt0)
{
	const priv_p priv = (priv_p) ifp->if_softc;
	const iffam_p iffam = get_iffam_from_af(dst->sa_family);
	meta_p meta = NULL;
	int len, error = 0;

	/* Check interface flags */
	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
		m_freem(m);
		return (ENETDOWN);
	}

	/* BPF writes need to be handled specially */
	if (dst->sa_family == AF_UNSPEC) {
		if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL)
			return (ENOBUFS);
		dst->sa_family = (sa_family_t)*mtod(m, int32_t *);
		m->m_data += 4;
		m->m_len -= 4;
		m->m_pkthdr.len -= 4;
	}

	/* Berkeley packet filter */
	ng_iface_bpftap(ifp, m, dst->sa_family);

	/* Check address family to determine hook (if known) */
	if (iffam == NULL) {
		m_freem(m);
		log(LOG_WARNING, "%s: can't handle af%d\n",
		       ifp->if_xname, (int)dst->sa_family);
		return (EAFNOSUPPORT);
	}

	/* Copy length before the mbuf gets invalidated */
	len = m->m_pkthdr.len;

	/* Send packet; if hook is not connected, mbuf will get freed. */
	NG_SEND_DATA(error, *get_hook_from_iffam(priv, iffam), m, meta);

	/* Update stats */
	if (error == 0) {
		IFNET_STAT_INC(ifp, obytes, len);
		IFNET_STAT_INC(ifp, opackets, 1);
	}
	return (error);
}
Exemple #2
0
/*
 * Receive data on a hook
 *
 * If data comes in the right link send a copy out right2left, and then
 * send the original onwards out through the left link.
 * Do the opposite for data coming in from the left link.
 * Data coming in right2left or left2right is forwarded
 * on through the appropriate destination hook as if it had come
 * from the other side.
 */
static int
ngt_rcvdata(hook_p hook, item_p item)
{
	const sc_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
	struct hookinfo *const hinfo = NG_HOOK_PRIVATE(hook);
	struct hookinfo *dest;
	struct hookinfo *dup;
	int error = 0;
	struct mbuf *m;
	meta_p meta;

	m = NGI_M(item);
	meta = NGI_META(item); /* leave these owned by the item */
	/* Which hook? */
	if (hinfo == &sc->left) {
		dup = &sc->left2right;
		dest = &sc->right;
	} else if (hinfo == &sc->right) {
		dup = &sc->right2left;
		dest = &sc->left;
	} else if (hinfo == &sc->right2left) {
		dup = NULL;
		dest = &sc->right;
	} else if (hinfo == &sc->left2right) {
		dup = NULL;
		dest = &sc->left;
	} else {
		panic("%s: no hook!", __func__);
#ifdef	RESTARTABLE_PANICS
		return(EINVAL);
#endif
	}

	/* Update stats on incoming hook */
	hinfo->stats.inOctets += m->m_pkthdr.len;
	hinfo->stats.inFrames++;

	/*
	 * Don't make a copy if only the dup hook exists.
	 */
	if ((dup && dup->hook) && (dest->hook == NULL)) {
		dest = dup;
		dup = NULL;
	}

	/* Duplicate packet and meta info if requried */
	if (dup != NULL) {
		struct mbuf *m2;
		meta_p meta2;

		/* Copy packet (failure will not stop the original)*/
		m2 = m_dup(m, M_NOWAIT);
		if (m2) {

			/* Copy meta info */
			/* If we can't get a copy, tough.. */
			if (meta != NULL) {
				meta2 = ng_copy_meta(meta);
			} else
				meta2 = NULL;

			/* Deliver duplicate */
			dup->stats.outOctets += m->m_pkthdr.len;
			dup->stats.outFrames++;
			NG_SEND_DATA(error, dup->hook, m2, meta2);
		}
	}
	/* Deliver frame out destination hook */
	dest->stats.outOctets += m->m_pkthdr.len;
	dest->stats.outFrames++;
	if (dest->hook)
		NG_FWD_ITEM_HOOK(error, item, dest->hook);
	else
		NG_FREE_ITEM(item);
	return (0);
}