Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2021 Intel Corporation
0004  */
0005 
0006 #include <uapi/linux/if_ether.h>
0007 #include <uapi/linux/if_arp.h>
0008 #include <uapi/linux/icmp.h>
0009 
0010 #include <linux/etherdevice.h>
0011 #include <linux/netdevice.h>
0012 #include <linux/skbuff.h>
0013 #include <linux/ieee80211.h>
0014 
0015 #include <net/cfg80211.h>
0016 #include <net/ip.h>
0017 
0018 #include <linux/if_arp.h>
0019 #include <linux/icmp.h>
0020 #include <linux/udp.h>
0021 #include <linux/ip.h>
0022 #include <linux/mm.h>
0023 
0024 #include "internal.h"
0025 #include "sap.h"
0026 #include "iwl-mei.h"
0027 
0028 /*
0029  * Returns true if further filtering should be stopped. Only in that case
0030  * pass_to_csme and rx_handler_res are set. Otherwise, next level of filters
0031  * should be checked.
0032  */
0033 static bool iwl_mei_rx_filter_eth(const struct ethhdr *ethhdr,
0034                   const struct iwl_sap_oob_filters *filters,
0035                   bool *pass_to_csme,
0036                   rx_handler_result_t *rx_handler_res)
0037 {
0038     const struct iwl_sap_eth_filter *filt;
0039 
0040     /* This filter is not relevant for UCAST packet */
0041     if (!is_multicast_ether_addr(ethhdr->h_dest) ||
0042         is_broadcast_ether_addr(ethhdr->h_dest))
0043         return false;
0044 
0045     for (filt = &filters->eth_filters[0];
0046          filt < &filters->eth_filters[0] + ARRAY_SIZE(filters->eth_filters);
0047          filt++) {
0048         /* Assume there are no enabled filter after a disabled one */
0049         if (!(filt->flags & SAP_ETH_FILTER_ENABLED))
0050             break;
0051 
0052         if (compare_ether_header(filt->mac_address, ethhdr->h_dest))
0053             continue;
0054 
0055         /* Packet needs to reach the host's stack */
0056         if (filt->flags & SAP_ETH_FILTER_COPY)
0057             *rx_handler_res = RX_HANDLER_PASS;
0058         else
0059             *rx_handler_res = RX_HANDLER_CONSUMED;
0060 
0061         /* We have an authoritative answer, stop filtering */
0062         if (filt->flags & SAP_ETH_FILTER_STOP) {
0063             *pass_to_csme = true;
0064             return true;
0065         }
0066 
0067         return false;
0068     }
0069 
0070      /* MCAST frames that don't match layer 2 filters are not sent to ME */
0071     *pass_to_csme  = false;
0072 
0073     return true;
0074 }
0075 
0076 /*
0077  * Returns true iff the frame should be passed to CSME in which case
0078  * rx_handler_res is set.
0079  */
0080 static bool iwl_mei_rx_filter_arp(struct sk_buff *skb,
0081                   const struct iwl_sap_oob_filters *filters,
0082                   rx_handler_result_t *rx_handler_res)
0083 {
0084     const struct iwl_sap_ipv4_filter *filt = &filters->ipv4_filter;
0085     const struct arphdr *arp;
0086     const __be32 *target_ip;
0087     u32 flags = le32_to_cpu(filt->flags);
0088 
0089     if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
0090         return false;
0091 
0092     arp = arp_hdr(skb);
0093 
0094     /* Handle only IPv4 over ethernet ARP frames */
0095     if (arp->ar_hrd != htons(ARPHRD_ETHER) ||
0096         arp->ar_pro != htons(ETH_P_IP))
0097         return false;
0098 
0099     /*
0100      * After the ARP header, we have:
0101      * src MAC address   - 6 bytes
0102      * src IP address    - 4 bytes
0103      * target MAC addess - 6 bytes
0104      */
0105     target_ip = (const void *)((const u8 *)(arp + 1) +
0106                    ETH_ALEN + sizeof(__be32) + ETH_ALEN);
0107 
0108     /*
0109      * ARP request is forwarded to ME only if IP address match in the
0110      * ARP request's target ip field.
0111      */
0112     if (arp->ar_op == htons(ARPOP_REQUEST) &&
0113         (filt->flags & cpu_to_le32(SAP_IPV4_FILTER_ARP_REQ_PASS)) &&
0114         (filt->ipv4_addr == 0 || filt->ipv4_addr == *target_ip)) {
0115         if (flags & SAP_IPV4_FILTER_ARP_REQ_COPY)
0116             *rx_handler_res = RX_HANDLER_PASS;
0117         else
0118             *rx_handler_res = RX_HANDLER_CONSUMED;
0119 
0120         return true;
0121     }
0122 
0123     /* ARP reply is always forwarded to ME regardless of the IP */
0124     if (flags & SAP_IPV4_FILTER_ARP_RESP_PASS &&
0125         arp->ar_op == htons(ARPOP_REPLY)) {
0126         if (flags & SAP_IPV4_FILTER_ARP_RESP_COPY)
0127             *rx_handler_res = RX_HANDLER_PASS;
0128         else
0129             *rx_handler_res = RX_HANDLER_CONSUMED;
0130 
0131         return true;
0132     }
0133 
0134     return false;
0135 }
0136 
0137 static bool
0138 iwl_mei_rx_filter_tcp_udp(struct sk_buff *skb, bool  ip_match,
0139               const struct iwl_sap_oob_filters *filters,
0140               rx_handler_result_t *rx_handler_res)
0141 {
0142     const struct iwl_sap_flex_filter *filt;
0143 
0144     for (filt = &filters->flex_filters[0];
0145          filt < &filters->flex_filters[0] + ARRAY_SIZE(filters->flex_filters);
0146          filt++) {
0147         if (!(filt->flags & SAP_FLEX_FILTER_ENABLED))
0148             break;
0149 
0150         /*
0151          * We are required to have a match on the IP level and we didn't
0152          * have such match.
0153          */
0154         if ((filt->flags &
0155              (SAP_FLEX_FILTER_IPV4 | SAP_FLEX_FILTER_IPV6)) &&
0156             !ip_match)
0157             continue;
0158 
0159         if ((filt->flags & SAP_FLEX_FILTER_UDP) &&
0160             ip_hdr(skb)->protocol != IPPROTO_UDP)
0161             continue;
0162 
0163         if ((filt->flags & SAP_FLEX_FILTER_TCP) &&
0164             ip_hdr(skb)->protocol != IPPROTO_TCP)
0165             continue;
0166 
0167         /*
0168          * We must have either a TCP header or a UDP header, both
0169          * starts with a source port and then a destination port.
0170          * Both are big endian words.
0171          * Use a UDP header and that will work for TCP as well.
0172          */
0173         if ((filt->src_port && filt->src_port != udp_hdr(skb)->source) ||
0174             (filt->dst_port && filt->dst_port != udp_hdr(skb)->dest))
0175             continue;
0176 
0177         if (filt->flags & SAP_FLEX_FILTER_COPY)
0178             *rx_handler_res = RX_HANDLER_PASS;
0179         else
0180             *rx_handler_res = RX_HANDLER_CONSUMED;
0181 
0182         return true;
0183     }
0184 
0185     return false;
0186 }
0187 
0188 static bool iwl_mei_rx_filter_ipv4(struct sk_buff *skb,
0189                    const struct iwl_sap_oob_filters *filters,
0190                    rx_handler_result_t *rx_handler_res)
0191 {
0192     const struct iwl_sap_ipv4_filter *filt = &filters->ipv4_filter;
0193     const struct iphdr *iphdr;
0194     unsigned int iphdrlen;
0195     bool match;
0196 
0197     if (!pskb_may_pull(skb, skb_network_offset(skb) + sizeof(*iphdr)) ||
0198         !pskb_may_pull(skb, skb_network_offset(skb) + ip_hdrlen(skb)))
0199         return false;
0200 
0201     iphdrlen = ip_hdrlen(skb);
0202     iphdr = ip_hdr(skb);
0203     match = !filters->ipv4_filter.ipv4_addr ||
0204         filters->ipv4_filter.ipv4_addr == iphdr->daddr;
0205 
0206     skb_set_transport_header(skb, skb_network_offset(skb) + iphdrlen);
0207 
0208     switch (ip_hdr(skb)->protocol) {
0209     case IPPROTO_UDP:
0210     case IPPROTO_TCP:
0211         /*
0212          * UDP header is shorter than TCP header and we look at the first bytes
0213          * of the header anyway (see below).
0214          * If we have a truncated TCP packet, let CSME handle this.
0215          */
0216         if (!pskb_may_pull(skb, skb_transport_offset(skb) +
0217                    sizeof(struct udphdr)))
0218             return false;
0219 
0220         return iwl_mei_rx_filter_tcp_udp(skb, match,
0221                          filters, rx_handler_res);
0222 
0223     case IPPROTO_ICMP: {
0224         struct icmphdr *icmp;
0225 
0226         if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(*icmp)))
0227             return false;
0228 
0229         icmp = icmp_hdr(skb);
0230 
0231         /*
0232          * Don't pass echo requests to ME even if it wants it as we
0233          * want the host to answer.
0234          */
0235         if ((filt->flags & cpu_to_le32(SAP_IPV4_FILTER_ICMP_PASS)) &&
0236             match && (icmp->type != ICMP_ECHO || icmp->code != 0)) {
0237             if (filt->flags & cpu_to_le32(SAP_IPV4_FILTER_ICMP_COPY))
0238                 *rx_handler_res = RX_HANDLER_PASS;
0239             else
0240                 *rx_handler_res = RX_HANDLER_CONSUMED;
0241 
0242             return true;
0243         }
0244         break;
0245         }
0246     case IPPROTO_ICMPV6:
0247         /* TODO: Should we have the same ICMP request logic here too? */
0248         if ((filters->icmpv6_flags & cpu_to_le32(SAP_ICMPV6_FILTER_ENABLED) &&
0249              match)) {
0250             if (filters->icmpv6_flags &
0251                 cpu_to_le32(SAP_ICMPV6_FILTER_COPY))
0252                 *rx_handler_res = RX_HANDLER_PASS;
0253             else
0254                 *rx_handler_res = RX_HANDLER_CONSUMED;
0255 
0256             return true;
0257         }
0258         break;
0259     default:
0260         return false;
0261     }
0262 
0263     return false;
0264 }
0265 
0266 static bool iwl_mei_rx_filter_ipv6(struct sk_buff *skb,
0267                    const struct iwl_sap_oob_filters *filters,
0268                    rx_handler_result_t *rx_handler_res)
0269 {
0270     *rx_handler_res = RX_HANDLER_PASS;
0271 
0272     /* TODO */
0273 
0274     return false;
0275 }
0276 
0277 static rx_handler_result_t
0278 iwl_mei_rx_pass_to_csme(struct sk_buff *skb,
0279             const struct iwl_sap_oob_filters *filters,
0280             bool *pass_to_csme)
0281 {
0282     const struct ethhdr *ethhdr = (void *)skb_mac_header(skb);
0283     rx_handler_result_t rx_handler_res = RX_HANDLER_PASS;
0284     bool (*filt_handler)(struct sk_buff *skb,
0285                  const struct iwl_sap_oob_filters *filters,
0286                  rx_handler_result_t *rx_handler_res);
0287 
0288     /*
0289      * skb->data points the IP header / ARP header and the ETH header
0290      * is in the headroom.
0291      */
0292     skb_reset_network_header(skb);
0293 
0294     /*
0295      * MCAST IP packets sent by us are received again here without
0296      * an ETH header. Drop them here.
0297      */
0298     if (!skb_mac_offset(skb))
0299         return RX_HANDLER_PASS;
0300 
0301     if (skb_headroom(skb) < sizeof(*ethhdr))
0302         return RX_HANDLER_PASS;
0303 
0304     if (iwl_mei_rx_filter_eth(ethhdr, filters,
0305                   pass_to_csme, &rx_handler_res))
0306         return rx_handler_res;
0307 
0308     switch (skb->protocol) {
0309     case htons(ETH_P_IP):
0310         filt_handler = iwl_mei_rx_filter_ipv4;
0311         break;
0312     case htons(ETH_P_ARP):
0313         filt_handler = iwl_mei_rx_filter_arp;
0314         break;
0315     case htons(ETH_P_IPV6):
0316         filt_handler = iwl_mei_rx_filter_ipv6;
0317         break;
0318     default:
0319         *pass_to_csme = false;
0320         return rx_handler_res;
0321     }
0322 
0323     *pass_to_csme = filt_handler(skb, filters, &rx_handler_res);
0324 
0325     return rx_handler_res;
0326 }
0327 
0328 rx_handler_result_t iwl_mei_rx_filter(struct sk_buff *orig_skb,
0329                       const struct iwl_sap_oob_filters *filters,
0330                       bool *pass_to_csme)
0331 {
0332     rx_handler_result_t ret;
0333     struct sk_buff *skb;
0334 
0335     ret = iwl_mei_rx_pass_to_csme(orig_skb, filters, pass_to_csme);
0336 
0337     if (!*pass_to_csme)
0338         return RX_HANDLER_PASS;
0339 
0340     if (ret == RX_HANDLER_PASS)
0341         skb = skb_copy(orig_skb, GFP_ATOMIC);
0342     else
0343         skb = orig_skb;
0344 
0345     /* CSME wants the MAC header as well, push it back */
0346     skb_push(skb, skb->data - skb_mac_header(skb));
0347 
0348     /*
0349      * Add the packet that CSME wants to get to the ring. Don't send the
0350      * Check Shared Area HECI message since this is not possible from the
0351      * Rx context. The caller will schedule a worker to do just that.
0352      */
0353     iwl_mei_add_data_to_ring(skb, false);
0354 
0355     /*
0356      * In case we drop the packet, don't free it, the caller will do that
0357      * for us
0358      */
0359     if (ret == RX_HANDLER_PASS)
0360         dev_kfree_skb(skb);
0361 
0362     return ret;
0363 }
0364 
0365 #define DHCP_SERVER_PORT 67
0366 #define DHCP_CLIENT_PORT 68
0367 void iwl_mei_tx_copy_to_csme(struct sk_buff *origskb, unsigned int ivlen)
0368 {
0369     struct ieee80211_hdr *hdr;
0370     struct sk_buff *skb;
0371     struct ethhdr ethhdr;
0372     struct ethhdr *eth;
0373 
0374     /* Catch DHCP packets */
0375     if (origskb->protocol != htons(ETH_P_IP) ||
0376         ip_hdr(origskb)->protocol != IPPROTO_UDP ||
0377         udp_hdr(origskb)->source != htons(DHCP_CLIENT_PORT) ||
0378         udp_hdr(origskb)->dest != htons(DHCP_SERVER_PORT))
0379         return;
0380 
0381     /*
0382      * We could be a bit less aggressive here and not copy everything, but
0383      * this is very rare anyway, do don't bother much.
0384      */
0385     skb = skb_copy(origskb, GFP_ATOMIC);
0386     if (!skb)
0387         return;
0388 
0389     skb->protocol = origskb->protocol;
0390 
0391     hdr = (void *)skb->data;
0392 
0393     memcpy(ethhdr.h_dest, ieee80211_get_DA(hdr), ETH_ALEN);
0394     memcpy(ethhdr.h_source, ieee80211_get_SA(hdr), ETH_ALEN);
0395 
0396     /*
0397      * Remove the ieee80211 header + IV + SNAP but leave the ethertype
0398      * We still have enough headroom for the sap header.
0399      */
0400     pskb_pull(skb, ieee80211_hdrlen(hdr->frame_control) + ivlen + 6);
0401     eth = skb_push(skb, sizeof(ethhdr.h_dest) + sizeof(ethhdr.h_source));
0402     memcpy(eth, &ethhdr, sizeof(ethhdr.h_dest) + sizeof(ethhdr.h_source));
0403 
0404     iwl_mei_add_data_to_ring(skb, true);
0405 
0406     dev_kfree_skb(skb);
0407 }
0408 EXPORT_SYMBOL_GPL(iwl_mei_tx_copy_to_csme);