0001
0002
0003
0004
0005
0006
0007
0008 #include <uapi/linux/ipv6.h>
0009 #include <net/ndisc.h>
0010 #include "decl.h"
0011 #include "ioctl.h"
0012 #include "util.h"
0013 #include "fw.h"
0014 #include "main.h"
0015 #include "11n_aggr.h"
0016 #include "11n_rxreorder.h"
0017
0018
0019
0020
0021
0022 static bool
0023 mwifiex_discard_gratuitous_arp(struct mwifiex_private *priv,
0024 struct sk_buff *skb)
0025 {
0026 const struct mwifiex_arp_eth_header *arp;
0027 struct ethhdr *eth;
0028 struct ipv6hdr *ipv6;
0029 struct icmp6hdr *icmpv6;
0030
0031 eth = (struct ethhdr *)skb->data;
0032 switch (ntohs(eth->h_proto)) {
0033 case ETH_P_ARP:
0034 arp = (void *)(skb->data + sizeof(struct ethhdr));
0035 if (arp->hdr.ar_op == htons(ARPOP_REPLY) ||
0036 arp->hdr.ar_op == htons(ARPOP_REQUEST)) {
0037 if (!memcmp(arp->ar_sip, arp->ar_tip, 4))
0038 return true;
0039 }
0040 break;
0041 case ETH_P_IPV6:
0042 ipv6 = (void *)(skb->data + sizeof(struct ethhdr));
0043 icmpv6 = (void *)(skb->data + sizeof(struct ethhdr) +
0044 sizeof(struct ipv6hdr));
0045 if (NDISC_NEIGHBOUR_ADVERTISEMENT == icmpv6->icmp6_type) {
0046 if (!memcmp(&ipv6->saddr, &ipv6->daddr,
0047 sizeof(struct in6_addr)))
0048 return true;
0049 }
0050 break;
0051 default:
0052 break;
0053 }
0054
0055 return false;
0056 }
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 int mwifiex_process_rx_packet(struct mwifiex_private *priv,
0072 struct sk_buff *skb)
0073 {
0074 int ret;
0075 struct rx_packet_hdr *rx_pkt_hdr;
0076 struct rxpd *local_rx_pd;
0077 int hdr_chop;
0078 struct ethhdr *eth;
0079 u16 rx_pkt_off, rx_pkt_len;
0080 u8 *offset;
0081 u8 adj_rx_rate = 0;
0082
0083 local_rx_pd = (struct rxpd *) (skb->data);
0084
0085 rx_pkt_off = le16_to_cpu(local_rx_pd->rx_pkt_offset);
0086 rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length);
0087 rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off;
0088
0089 if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
0090 sizeof(bridge_tunnel_header))) ||
0091 (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
0092 sizeof(rfc1042_header)) &&
0093 ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
0094 ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 eth = (struct ethhdr *)
0105 ((u8 *) &rx_pkt_hdr->eth803_hdr
0106 + sizeof(rx_pkt_hdr->eth803_hdr) +
0107 sizeof(rx_pkt_hdr->rfc1042_hdr)
0108 - sizeof(rx_pkt_hdr->eth803_hdr.h_dest)
0109 - sizeof(rx_pkt_hdr->eth803_hdr.h_source)
0110 - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type));
0111
0112 memcpy(eth->h_source, rx_pkt_hdr->eth803_hdr.h_source,
0113 sizeof(eth->h_source));
0114 memcpy(eth->h_dest, rx_pkt_hdr->eth803_hdr.h_dest,
0115 sizeof(eth->h_dest));
0116
0117
0118
0119 hdr_chop = (u8 *) eth - (u8 *) local_rx_pd;
0120 } else {
0121
0122 hdr_chop = (u8 *) &rx_pkt_hdr->eth803_hdr -
0123 (u8 *) local_rx_pd;
0124 }
0125
0126
0127
0128 skb_pull(skb, hdr_chop);
0129
0130 if (priv->hs2_enabled &&
0131 mwifiex_discard_gratuitous_arp(priv, skb)) {
0132 mwifiex_dbg(priv->adapter, INFO, "Bypassed Gratuitous ARP\n");
0133 dev_kfree_skb_any(skb);
0134 return 0;
0135 }
0136
0137 if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
0138 ntohs(rx_pkt_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) {
0139 offset = (u8 *)local_rx_pd + rx_pkt_off;
0140 mwifiex_process_tdls_action_frame(priv, offset, rx_pkt_len);
0141 }
0142
0143
0144 if (likely(!is_multicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest))) {
0145 priv->rxpd_rate = local_rx_pd->rx_rate;
0146 priv->rxpd_htinfo = local_rx_pd->ht_info;
0147 }
0148
0149 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
0150 GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
0151 adj_rx_rate = mwifiex_adjust_data_rate(priv,
0152 local_rx_pd->rx_rate,
0153 local_rx_pd->ht_info);
0154 mwifiex_hist_data_add(priv, adj_rx_rate, local_rx_pd->snr,
0155 local_rx_pd->nf);
0156 }
0157
0158 ret = mwifiex_recv_packet(priv, skb);
0159 if (ret == -1)
0160 mwifiex_dbg(priv->adapter, ERROR,
0161 "recv packet failed\n");
0162
0163 return ret;
0164 }
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178 int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
0179 struct sk_buff *skb)
0180 {
0181 struct mwifiex_adapter *adapter = priv->adapter;
0182 int ret = 0;
0183 struct rxpd *local_rx_pd;
0184 struct rx_packet_hdr *rx_pkt_hdr;
0185 u8 ta[ETH_ALEN];
0186 u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
0187 struct mwifiex_sta_node *sta_ptr;
0188
0189 local_rx_pd = (struct rxpd *) (skb->data);
0190 rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
0191 rx_pkt_offset = le16_to_cpu(local_rx_pd->rx_pkt_offset);
0192 rx_pkt_length = le16_to_cpu(local_rx_pd->rx_pkt_length);
0193 seq_num = le16_to_cpu(local_rx_pd->seq_num);
0194
0195 rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset;
0196
0197 if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) {
0198 mwifiex_dbg(adapter, ERROR,
0199 "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
0200 skb->len, rx_pkt_offset, rx_pkt_length);
0201 priv->stats.rx_dropped++;
0202 dev_kfree_skb_any(skb);
0203 return ret;
0204 }
0205
0206 if (rx_pkt_type == PKT_TYPE_MGMT) {
0207 ret = mwifiex_process_mgmt_packet(priv, skb);
0208 if (ret)
0209 mwifiex_dbg(adapter, DATA, "Rx of mgmt packet failed");
0210 dev_kfree_skb_any(skb);
0211 return ret;
0212 }
0213
0214
0215
0216
0217
0218 if ((!IS_11N_ENABLED(priv) &&
0219 !(ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
0220 !(local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET))) ||
0221 !ether_addr_equal_unaligned(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest)) {
0222 mwifiex_process_rx_packet(priv, skb);
0223 return ret;
0224 }
0225
0226 if (mwifiex_queuing_ra_based(priv) ||
0227 (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
0228 local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET)) {
0229 memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
0230 if (local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET &&
0231 local_rx_pd->priority < MAX_NUM_TID) {
0232 sta_ptr = mwifiex_get_sta_entry(priv, ta);
0233 if (sta_ptr)
0234 sta_ptr->rx_seq[local_rx_pd->priority] =
0235 le16_to_cpu(local_rx_pd->seq_num);
0236 mwifiex_auto_tdls_update_peer_signal(priv, ta,
0237 local_rx_pd->snr,
0238 local_rx_pd->nf);
0239 }
0240 } else {
0241 if (rx_pkt_type != PKT_TYPE_BAR &&
0242 local_rx_pd->priority < MAX_NUM_TID)
0243 priv->rx_seq[local_rx_pd->priority] = seq_num;
0244 memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address,
0245 ETH_ALEN);
0246 }
0247
0248
0249 ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority,
0250 ta, (u8) rx_pkt_type, skb);
0251
0252 if (ret || (rx_pkt_type == PKT_TYPE_BAR))
0253 dev_kfree_skb_any(skb);
0254
0255 if (ret)
0256 priv->stats.rx_dropped++;
0257
0258 return ret;
0259 }