0001
0002
0003
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
0030
0031
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
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
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
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
0062 if (filt->flags & SAP_ETH_FILTER_STOP) {
0063 *pass_to_csme = true;
0064 return true;
0065 }
0066
0067 return false;
0068 }
0069
0070
0071 *pass_to_csme = false;
0072
0073 return true;
0074 }
0075
0076
0077
0078
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
0095 if (arp->ar_hrd != htons(ARPHRD_ETHER) ||
0096 arp->ar_pro != htons(ETH_P_IP))
0097 return false;
0098
0099
0100
0101
0102
0103
0104
0105 target_ip = (const void *)((const u8 *)(arp + 1) +
0106 ETH_ALEN + sizeof(__be32) + ETH_ALEN);
0107
0108
0109
0110
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
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
0152
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
0169
0170
0171
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
0213
0214
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
0233
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
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
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
0290
0291
0292 skb_reset_network_header(skb);
0293
0294
0295
0296
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
0346 skb_push(skb, skb->data - skb_mac_header(skb));
0347
0348
0349
0350
0351
0352
0353 iwl_mei_add_data_to_ring(skb, false);
0354
0355
0356
0357
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
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
0383
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
0398
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, ðhdr, 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);