/* * Returns true if further filtering should be stopped. Only in that case * pass_to_csme and rx_handler_res are set. Otherwise, next level of filters * should be checked.
*/ staticbool iwl_mei_rx_filter_eth(conststruct ethhdr *ethhdr, conststruct iwl_sap_oob_filters *filters, bool *pass_to_csme,
rx_handler_result_t *rx_handler_res)
{ conststruct iwl_sap_eth_filter *filt;
/* This filter is not relevant for UCAST packet */ if (!is_multicast_ether_addr(ethhdr->h_dest) ||
is_broadcast_ether_addr(ethhdr->h_dest)) returnfalse;
for (filt = &filters->eth_filters[0];
filt < &filters->eth_filters[0] + ARRAY_SIZE(filters->eth_filters);
filt++) { /* Assume there are no enabled filter after a disabled one */ if (!(filt->flags & SAP_ETH_FILTER_ENABLED)) break;
if (compare_ether_header(filt->mac_address, ethhdr->h_dest)) continue;
/* Packet needs to reach the host's stack */ if (filt->flags & SAP_ETH_FILTER_COPY)
*rx_handler_res = RX_HANDLER_PASS; else
*rx_handler_res = RX_HANDLER_CONSUMED;
/* We have an authoritative answer, stop filtering */ if (filt->flags & SAP_ETH_FILTER_STOP) {
*pass_to_csme = true; returntrue;
}
returnfalse;
}
/* MCAST frames that don't match layer 2 filters are not sent to ME */
*pass_to_csme = false;
returntrue;
}
/* * Returns true iff the frame should be passed to CSME in which case * rx_handler_res is set.
*/ staticbool iwl_mei_rx_filter_arp(struct sk_buff *skb, conststruct iwl_sap_oob_filters *filters,
rx_handler_result_t *rx_handler_res)
{ conststruct iwl_sap_ipv4_filter *filt = &filters->ipv4_filter; conststruct arphdr *arp; const __be32 *target_ip;
u32 flags = le32_to_cpu(filt->flags);
if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) returnfalse;
arp = arp_hdr(skb);
/* Handle only IPv4 over ethernet ARP frames */ if (arp->ar_hrd != htons(ARPHRD_ETHER) ||
arp->ar_pro != htons(ETH_P_IP)) returnfalse;
/* * After the ARP header, we have: * src MAC address - 6 bytes * src IP address - 4 bytes * target MAC addess - 6 bytes
*/
target_ip = (constvoid *)((const u8 *)(arp + 1) +
ETH_ALEN + sizeof(__be32) + ETH_ALEN);
/* * ARP request is forwarded to ME only if IP address match in the * ARP request's target ip field.
*/ if (arp->ar_op == htons(ARPOP_REQUEST) &&
(filt->flags & cpu_to_le32(SAP_IPV4_FILTER_ARP_REQ_PASS)) &&
(filt->ipv4_addr == 0 || filt->ipv4_addr == *target_ip)) { if (flags & SAP_IPV4_FILTER_ARP_REQ_COPY)
*rx_handler_res = RX_HANDLER_PASS; else
*rx_handler_res = RX_HANDLER_CONSUMED;
returntrue;
}
/* ARP reply is always forwarded to ME regardless of the IP */ if (flags & SAP_IPV4_FILTER_ARP_RESP_PASS &&
arp->ar_op == htons(ARPOP_REPLY)) { if (flags & SAP_IPV4_FILTER_ARP_RESP_COPY)
*rx_handler_res = RX_HANDLER_PASS; else
*rx_handler_res = RX_HANDLER_CONSUMED;
for (filt = &filters->flex_filters[0];
filt < &filters->flex_filters[0] + ARRAY_SIZE(filters->flex_filters);
filt++) { if (!(filt->flags & SAP_FLEX_FILTER_ENABLED)) break;
/* * We are required to have a match on the IP level and we didn't * have such match.
*/ if ((filt->flags &
(SAP_FLEX_FILTER_IPV4 | SAP_FLEX_FILTER_IPV6)) &&
!ip_match) continue;
if ((filt->flags & SAP_FLEX_FILTER_UDP) &&
ip_hdr(skb)->protocol != IPPROTO_UDP) continue;
if ((filt->flags & SAP_FLEX_FILTER_TCP) &&
ip_hdr(skb)->protocol != IPPROTO_TCP) continue;
/* * We must have either a TCP header or a UDP header, both * starts with a source port and then a destination port. * Both are big endian words. * Use a UDP header and that will work for TCP as well.
*/ if ((filt->src_port && filt->src_port != udp_hdr(skb)->source) ||
(filt->dst_port && filt->dst_port != udp_hdr(skb)->dest)) continue;
switch (ip_hdr(skb)->protocol) { case IPPROTO_UDP: case IPPROTO_TCP: /* * UDP header is shorter than TCP header and we look at the first bytes * of the header anyway (see below). * If we have a truncated TCP packet, let CSME handle this.
*/ if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr))) returnfalse;
if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(*icmp))) returnfalse;
icmp = icmp_hdr(skb);
/* * Don't pass echo requests to ME even if it wants it as we * want the host to answer.
*/ if ((filt->flags & cpu_to_le32(SAP_IPV4_FILTER_ICMP_PASS)) &&
match && (icmp->type != ICMP_ECHO || icmp->code != 0)) { if (filt->flags & cpu_to_le32(SAP_IPV4_FILTER_ICMP_COPY))
*rx_handler_res = RX_HANDLER_PASS; else
*rx_handler_res = RX_HANDLER_CONSUMED;
returntrue;
} break;
} case IPPROTO_ICMPV6: /* TODO: Should we have the same ICMP request logic here too? */ if ((filters->icmpv6_flags & cpu_to_le32(SAP_ICMPV6_FILTER_ENABLED) &&
match)) { if (filters->icmpv6_flags &
cpu_to_le32(SAP_ICMPV6_FILTER_COPY))
*rx_handler_res = RX_HANDLER_PASS; else
*rx_handler_res = RX_HANDLER_CONSUMED;
/* CSME wants the MAC header as well, push it back */
skb_push(skb, skb->data - skb_mac_header(skb));
/* * Add the packet that CSME wants to get to the ring. Don't send the * Check Shared Area HECI message since this is not possible from the * Rx context. The caller will schedule a worker to do just that.
*/
iwl_mei_add_data_to_ring(skb, false);
/* * In case we drop the packet, don't free it, the caller will do that * for us
*/ if (ret == RX_HANDLER_PASS)
dev_kfree_skb(skb);
/* * We could be a bit less aggressive here and not copy everything, but * this is very rare anyway, do don't bother much.
*/
skb = skb_copy(origskb, GFP_ATOMIC); if (!skb) return;
/* * Remove the ieee80211 header + IV + SNAP but leave the ethertype * We still have enough headroom for the sap header.
*/
pskb_pull(skb, ieee80211_hdrlen(hdr->frame_control) + ivlen + 6);
eth = skb_push(skb, sizeof(ethhdr.h_dest) + sizeof(ethhdr.h_source));
memcpy(eth, ðhdr, sizeof(ethhdr.h_dest) + sizeof(ethhdr.h_source));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.