+ if (m->m_flags & M_HASFCS) {
+ /*
+ * If the M_HASFCS is set by the driver we want to make sure
+ * that we strip off the trailing FCS data before handing it
+ * up the stack.
+ */
+ m_adj(m, -ETHER_CRC_LEN);
+ m->m_flags &= ~M_HASFCS;
+ }
+
+ if ((eh->ether_dhost[0] & 1) == 0) {
+ /*
+ * When the driver is put into promiscuous mode we may receive
+ * unicast frames that are not intended for our interfaces.
+ * They are marked here as being promiscuous so the caller may
+ * dispose of them after passing the packets to any interface
+ * filters.
+ */
+ if (_ether_cmp(eh->ether_dhost, IF_LLADDR(ifp))) {
+ m->m_flags |= M_PROMISC;
+ }
+ }
+
+ /* check for IEEE 802.15.4 */
+ if (ether_type == htons(ETHERTYPE_IEEE802154)) {
+ *protocol_family = PF_802154;
+ return 0;
+ }
+
+ /* check for VLAN */
+ if ((m->m_pkthdr.csum_flags & CSUM_VLAN_TAG_VALID) != 0) {
+ if (EVL_VLANOFTAG(m->m_pkthdr.vlan_tag) != 0) {
+ *protocol_family = PF_VLAN;
+ return 0;
+ }
+ /* the packet is just priority-tagged, clear the bit */
+ m->m_pkthdr.csum_flags &= ~CSUM_VLAN_TAG_VALID;
+ } else if (ether_type == htons(ETHERTYPE_VLAN)) {
+ struct ether_vlan_header * evl;
+
+ evl = (struct ether_vlan_header *)(void *)frame_header;
+ if (m->m_len < ETHER_VLAN_ENCAP_LEN ||
+ ntohs(evl->evl_proto) == ETHERTYPE_VLAN ||
+ EVL_VLANOFTAG(ntohs(evl->evl_tag)) != 0) {
+ *protocol_family = PF_VLAN;
+ return 0;
+ }
+ /* the packet is just priority-tagged */
+
+ /* make the encapsulated ethertype the actual ethertype */
+ ether_type = evl->evl_encap_proto = evl->evl_proto;
+
+ /* remove the encapsulation header */
+ m->m_len -= ETHER_VLAN_ENCAP_LEN;
+ m->m_data += ETHER_VLAN_ENCAP_LEN;
+ m->m_pkthdr.len -= ETHER_VLAN_ENCAP_LEN;
+ m->m_pkthdr.csum_flags = 0; /* can't trust hardware checksum */
+ } else if (ether_type == htons(ETHERTYPE_ARP)) {
+ m->m_pkthdr.pkt_flags |= PKTF_INET_RESOLVE; /* ARP packet */
+ }
+ data = mtod(m, u_int8_t*);
+
+ /*
+ * Determine the packet's protocol type and stuff the protocol into
+ * longs for quick compares.
+ */
+ if (ntohs(ether_type) <= 1500) {
+ bcopy(data, &extProto1, sizeof(u_int32_t));
+
+ /* SAP or SNAP */
+ if ((extProto1 & htonl(0xFFFFFF00)) == htonl(0xAAAA0300)) {
+ /* SNAP */
+ type = DLIL_DESC_SNAP;
+ bcopy(data + sizeof(u_int32_t), &extProto2,
+ sizeof(u_int32_t));
+ extProto1 &= htonl(0x000000FF);
+ } else {
+ type = DLIL_DESC_SAP;
+ extProto1 &= htonl(0xFFFFFF00);
+ }
+ } else {
+ type = DLIL_DESC_ETYPE2;
+ }
+
+ /*
+ * Search through the connected protocols for a match.
+ */
+ switch (type) {
+ case DLIL_DESC_ETYPE2:
+ for (i = 0; i < maxd; i++) {
+ if ((ed[i].type == type) &&
+ (ed[i].data[0] == ether_type)) {
+ *protocol_family = ed[i].protocol_family;
+ return 0;
+ }
+ }
+ break;
+
+ case DLIL_DESC_SAP:
+ for (i = 0; i < maxd; i++) {
+ if ((ed[i].type == type) &&
+ (ed[i].data[0] == extProto1)) {
+ *protocol_family = ed[i].protocol_family;
+ return 0;
+ }
+ }
+ break;
+
+ case DLIL_DESC_SNAP:
+ for (i = 0; i < maxd; i++) {
+ if ((ed[i].type == type) &&
+ (ed[i].data[0] == extProto1) &&
+ (ed[i].data[1] == extProto2)) {
+ *protocol_family = ed[i].protocol_family;
+ return 0;
+ }
+ }
+ break;
+ }