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); }
/* * 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); }