/* * Process a received Ethernet packet; the packet is in the * mbuf chain m with the ethernet header at the front. */ static void ether_input_internal(struct ifnet *ifp, struct mbuf *m) { struct ether_header *eh; u_short etype; if ((ifp->if_flags & IFF_UP) == 0) { m_freem(m); return; } #ifdef DIAGNOSTIC if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { if_printf(ifp, "discard frame at !IFF_DRV_RUNNING\n"); m_freem(m); return; } #endif /* * Do consistency checks to verify assumptions * made by code past this point. */ if ((m->m_flags & M_PKTHDR) == 0) { if_printf(ifp, "discard frame w/o packet header\n"); ifp->if_ierrors++; m_freem(m); return; } if (m->m_len < ETHER_HDR_LEN) { /* XXX maybe should pullup? */ if_printf(ifp, "discard frame w/o leading ethernet " "header (len %u pkt len %u)\n", m->m_len, m->m_pkthdr.len); ifp->if_ierrors++; m_freem(m); return; } eh = mtod(m, struct ether_header *); etype = ntohs(eh->ether_type); if (m->m_pkthdr.rcvif == NULL) { if_printf(ifp, "discard frame w/o interface pointer\n"); ifp->if_ierrors++; m_freem(m); return; } #ifdef DIAGNOSTIC if (m->m_pkthdr.rcvif != ifp) { if_printf(ifp, "Warning, frame marked as received on %s\n", m->m_pkthdr.rcvif->if_xname); } #endif CURVNET_SET_QUIET(ifp->if_vnet); if (ETHER_IS_MULTICAST(eh->ether_dhost)) { if (ETHER_IS_BROADCAST(eh->ether_dhost)) m->m_flags |= M_BCAST; else m->m_flags |= M_MCAST; ifp->if_imcasts++; } #ifdef MAC /* * Tag the mbuf with an appropriate MAC label before any other * consumers can get to it. */ mac_ifnet_create_mbuf(ifp, m); #endif /* * Give bpf a chance at the packet. */ ETHER_BPF_MTAP(ifp, m); /* * If the CRC is still on the packet, trim it off. We do this once * and once only in case we are re-entered. Nothing else on the * Ethernet receive path expects to see the FCS. */ if (m->m_flags & M_HASFCS) { m_adj(m, -ETHER_CRC_LEN); m->m_flags &= ~M_HASFCS; } if (!(ifp->if_capenable & IFCAP_HWSTATS)) ifp->if_ibytes += m->m_pkthdr.len; /* Allow monitor mode to claim this frame, after stats are updated. */ if (ifp->if_flags & IFF_MONITOR) { m_freem(m); CURVNET_RESTORE(); return; } /* Handle input from a lagg(4) port */ if (ifp->if_type == IFT_IEEE8023ADLAG) { KASSERT(lagg_input_p != NULL, ("%s: if_lagg not loaded!", __func__)); m = (*lagg_input_p)(ifp, m); if (m != NULL) ifp = m->m_pkthdr.rcvif; else { CURVNET_RESTORE(); return; } } /* * If the hardware did not process an 802.1Q tag, do this now, * to allow 802.1P priority frames to be passed to the main input * path correctly. * TODO: Deal with Q-in-Q frames, but not arbitrary nesting levels. */ if ((m->m_flags & M_VLANTAG) == 0 && etype == ETHERTYPE_VLAN) { struct ether_vlan_header *evl; if (m->m_len < sizeof(*evl) && (m = m_pullup(m, sizeof(*evl))) == NULL) { #ifdef DIAGNOSTIC if_printf(ifp, "cannot pullup VLAN header\n"); #endif ifp->if_ierrors++; m_freem(m); CURVNET_RESTORE(); return; } evl = mtod(m, struct ether_vlan_header *); m->m_pkthdr.ether_vtag = ntohs(evl->evl_tag); m->m_flags |= M_VLANTAG; bcopy((char *)evl, (char *)evl + ETHER_VLAN_ENCAP_LEN, ETHER_HDR_LEN - ETHER_TYPE_LEN); m_adj(m, ETHER_VLAN_ENCAP_LEN); eh = mtod(m, struct ether_header *); } M_SETFIB(m, ifp->if_fib); /* Allow ng_ether(4) to claim this frame. */ if (IFP2AC(ifp)->ac_netgraph != NULL) { KASSERT(ng_ether_input_p != NULL, ("%s: ng_ether_input_p is NULL", __func__)); m->m_flags &= ~M_PROMISC; (*ng_ether_input_p)(ifp, &m); if (m == NULL) { CURVNET_RESTORE(); return; } eh = mtod(m, struct ether_header *); }
/* * Process a received ATM packet; * the packet is in the mbuf chain m. */ void atm_input(struct ifnet *ifp, struct atm_pseudohdr *ah, struct mbuf *m, void *rxhand) { int isr; u_int16_t etype = ETHERTYPE_IP; /* default */ if ((ifp->if_flags & IFF_UP) == 0) { m_freem(m); return; } #ifdef MAC mac_ifnet_create_mbuf(ifp, m); #endif ifp->if_ibytes += m->m_pkthdr.len; if (ng_atm_input_p != NULL) { (*ng_atm_input_p)(ifp, &m, ah, rxhand); if (m == NULL) return; } /* not eaten by ng_atm. Maybe it's a pseudo-harp PDU? */ if (atm_harp_input_p != NULL) { (*atm_harp_input_p)(ifp, &m, ah, rxhand); if (m == NULL) return; } if (rxhand) { #ifdef NATM struct natmpcb *npcb; /* * XXXRW: this use of 'rxhand' is not a very good idea, and * was subject to races even before SMPng due to the release * of spl here. */ NATM_LOCK(); npcb = rxhand; npcb->npcb_inq++; /* count # in queue */ isr = NETISR_NATM; m->m_pkthdr.rcvif = rxhand; /* XXX: overload */ NATM_UNLOCK(); #else printf("atm_input: NATM detected but not " "configured in kernel\n"); goto dropit; #endif } else { /* * handle LLC/SNAP header, if present */ if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) { struct atmllc *alc; if (m->m_len < sizeof(*alc) && (m = m_pullup(m, sizeof(*alc))) == 0) return; /* failed */ alc = mtod(m, struct atmllc *); if (bcmp(alc, ATMLLC_HDR, 6)) { printf("%s: recv'd invalid LLC/SNAP frame " "[vp=%d,vc=%d]\n", ifp->if_xname, ATM_PH_VPI(ah), ATM_PH_VCI(ah)); m_freem(m); return; } etype = ATM_LLC_TYPE(alc); m_adj(m, sizeof(*alc)); } switch (etype) { #ifdef INET case ETHERTYPE_IP: isr = NETISR_IP; break; #endif #ifdef INET6 case ETHERTYPE_IPV6: isr = NETISR_IPV6; break; #endif default: #ifndef NATM dropit: #endif if (ng_atm_input_orphan_p != NULL) (*ng_atm_input_orphan_p)(ifp, m, ah, rxhand); else m_freem(m); return; } } M_SETFIB(m, ifp->if_fib); netisr_dispatch(isr, m); }