/** * p80211_convert_to_ether - conversion from 802.11 frame to ethernet frame * @wlandev: pointer to WLAN device * @skb: pointer to socket buffer * * Returns: 0 if conversion succeeded * CONV_TO_ETHER_FAILED if conversion failed * CONV_TO_ETHER_SKIPPED if frame is ignored */ static int p80211_convert_to_ether(struct wlandevice *wlandev, struct sk_buff *skb) { struct p80211_hdr_a3 *hdr; hdr = (struct p80211_hdr_a3 *)skb->data; if (p80211_rx_typedrop(wlandev, le16_to_cpu(hdr->fc))) return CONV_TO_ETHER_SKIPPED; /* perform mcast filtering: allow my local address through but reject * anything else that isn't multicast */ if (wlandev->netdev->flags & IFF_ALLMULTI) { if (!ether_addr_equal_unaligned(wlandev->netdev->dev_addr, hdr->a1)) { if (!is_multicast_ether_addr(hdr->a1)) return CONV_TO_ETHER_SKIPPED; } } if (skb_p80211_to_ether(wlandev, wlandev->ethconv, skb) == 0) { wlandev->netdev->stats.rx_packets++; wlandev->netdev->stats.rx_bytes += skb->len; netif_rx_ni(skb); return 0; } netdev_dbg(wlandev->netdev, "%s failed.\n", __func__); return CONV_TO_ETHER_FAILED; }
void rtl_cam_del_entry( struct ieee80211_hw *hw, u8 *sta_addr ) { struct rtl_priv *rtlpriv = rtl_priv( hw ); u32 bitmap; u8 i, *addr; if ( NULL == sta_addr ) { RT_TRACE( rtlpriv, COMP_SEC, DBG_EMERG, "sta_addr is NULL.\n" ); return; } if ( is_zero_ether_addr( sta_addr ) ) { RT_TRACE( rtlpriv, COMP_SEC, DBG_EMERG, "sta_addr is %pM\n", sta_addr ); return; } /* Does STA already exist? */ for ( i = 4; i < TOTAL_CAM_ENTRY; i++ ) { addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; bitmap = ( rtlpriv->sec.hwsec_cam_bitmap ) >> i; if ( ( ( bitmap & BIT( 0 ) ) == BIT( 0 ) ) && ( ether_addr_equal_unaligned( addr, sta_addr ) ) ) { /* Remove from HW Security CAM */ eth_zero_addr( rtlpriv->sec.hwsec_cam_sta_addr[i] ); rtlpriv->sec.hwsec_cam_bitmap &= ~( BIT( 0 ) << i ); RT_TRACE( rtlpriv, COMP_SEC, DBG_DMESG, "&&&&&&&&&del entry %d\n", i ); } } return; }
u8 rtl_cam_get_free_entry( struct ieee80211_hw *hw, u8 *sta_addr ) { struct rtl_priv *rtlpriv = rtl_priv( hw ); u32 bitmap = ( rtlpriv->sec.hwsec_cam_bitmap ) >> 4; u8 entry_idx = 0; u8 i, *addr; if ( NULL == sta_addr ) { RT_TRACE( rtlpriv, COMP_SEC, DBG_EMERG, "sta_addr is NULL.\n" ); return TOTAL_CAM_ENTRY; } /* Does STA already exist? */ for ( i = 4; i < TOTAL_CAM_ENTRY; i++ ) { addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; if ( ether_addr_equal_unaligned( addr, sta_addr ) ) return i; } /* Get a free CAM entry. */ for ( entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY; entry_idx++ ) { if ( ( bitmap & BIT( 0 ) ) == 0 ) { RT_TRACE( rtlpriv, COMP_SEC, DBG_EMERG, "-----hwsec_cam_bitmap: 0x%x entry_idx=%d\n", rtlpriv->sec.hwsec_cam_bitmap, entry_idx ); rtlpriv->sec.hwsec_cam_bitmap |= BIT( 0 ) << entry_idx; memcpy( rtlpriv->sec.hwsec_cam_sta_addr[entry_idx], sta_addr, ETH_ALEN ); return entry_idx; } bitmap = bitmap >> 1; } return TOTAL_CAM_ENTRY; }
static int wl1251_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wl1251 *wl = hw->priv; int ret = 0; vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | IEEE80211_VIF_SUPPORTS_UAPSD | IEEE80211_VIF_SUPPORTS_CQM_RSSI; wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", vif->type, vif->addr); mutex_lock(&wl->mutex); if (wl->vif) { ret = -EBUSY; goto out; } wl->vif = vif; switch (vif->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; break; case NL80211_IFTYPE_ADHOC: wl->bss_type = BSS_TYPE_IBSS; break; default: ret = -EOPNOTSUPP; goto out; } if (!ether_addr_equal_unaligned(wl->mac_addr, vif->addr)) { memcpy(wl->mac_addr, vif->addr, ETH_ALEN); SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); ret = wl1251_acx_station_id(wl); if (ret < 0) goto out; } out: mutex_unlock(&wl->mutex); return ret; }
/* * CFG802.11 network device handler for data transmission. */ static int mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); struct sk_buff *new_skb; struct mwifiex_txinfo *tx_info; bool multicast; dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n", jiffies, priv->bss_type, priv->bss_num); if (priv->adapter->surprise_removed) { kfree_skb(skb); priv->stats.tx_dropped++; return 0; } if (!skb->len || (skb->len > ETH_FRAME_LEN)) { dev_err(priv->adapter->dev, "Tx: bad skb len %d\n", skb->len); kfree_skb(skb); priv->stats.tx_dropped++; return 0; } if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) { dev_dbg(priv->adapter->dev, "data: Tx: insufficient skb headroom %d\n", skb_headroom(skb)); /* Insufficient skb headroom - allocate a new skb */ new_skb = skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN); if (unlikely(!new_skb)) { dev_err(priv->adapter->dev, "Tx: cannot alloca new_skb\n"); kfree_skb(skb); priv->stats.tx_dropped++; return 0; } kfree_skb(skb); skb = new_skb; dev_dbg(priv->adapter->dev, "info: new skb headroomd %d\n", skb_headroom(skb)); } tx_info = MWIFIEX_SKB_TXCB(skb); memset(tx_info, 0, sizeof(*tx_info)); tx_info->bss_num = priv->bss_num; tx_info->bss_type = priv->bss_type; tx_info->pkt_len = skb->len; multicast = is_multicast_ether_addr(skb->data); if (unlikely(!multicast && skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS && priv->adapter->fw_api_ver == MWIFIEX_FW_V15)) skb = mwifiex_clone_skb_for_tx_status(priv, skb, MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS, NULL); /* Record the current time the packet was queued; used to * determine the amount of time the packet was queued in * the driver before it was sent to the firmware. * The delay is then sent along with the packet to the * firmware for aggregate delay calculation for stats and * MSDU lifetime expiry. */ __net_timestamp(skb); if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && priv->bss_type == MWIFIEX_BSS_TYPE_STA && !ether_addr_equal_unaligned(priv->cfg_bssid, skb->data)) { if (priv->adapter->auto_tdls && priv->check_tdls_tx) mwifiex_tdls_check_tx(priv, skb); } mwifiex_queue_tx_pkt(priv, skb); return 0; }
/* * This function processes the received buffer. * * The function looks into the RxPD and performs sanity tests on the * received buffer to ensure its a valid packet, before processing it * further. If the packet is determined to be aggregated, it is * de-aggregated accordingly. Non-unicast packets are sent directly to * the kernel/upper layers. Unicast packets are handed over to the * Rx reordering routine if 11n is enabled. * * The completion callback is called after processing in complete. */ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, struct sk_buff *skb) { struct mwifiex_adapter *adapter = priv->adapter; int ret = 0; struct rxpd *local_rx_pd; struct rx_packet_hdr *rx_pkt_hdr; u8 ta[ETH_ALEN]; u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num; struct mwifiex_sta_node *sta_ptr; local_rx_pd = (struct rxpd *) (skb->data); rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type); rx_pkt_offset = le16_to_cpu(local_rx_pd->rx_pkt_offset); rx_pkt_length = le16_to_cpu(local_rx_pd->rx_pkt_length); seq_num = le16_to_cpu(local_rx_pd->seq_num); rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset; if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) { dev_err(adapter->dev, "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n", skb->len, rx_pkt_offset, rx_pkt_length); priv->stats.rx_dropped++; dev_kfree_skb_any(skb); return ret; } if (rx_pkt_type == PKT_TYPE_MGMT) { ret = mwifiex_process_mgmt_packet(priv, skb); if (ret) dev_err(adapter->dev, "Rx of mgmt packet failed"); dev_kfree_skb_any(skb); return ret; } /* * If the packet is not an unicast packet then send the packet * directly to os. Don't pass thru rx reordering */ if ((!IS_11N_ENABLED(priv) && !(ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && !(local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET))) || !ether_addr_equal_unaligned(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest)) { mwifiex_process_rx_packet(priv, skb); return ret; } if (mwifiex_queuing_ra_based(priv) || (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET)) { memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); if (local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET && local_rx_pd->priority < MAX_NUM_TID) { sta_ptr = mwifiex_get_sta_entry(priv, ta); if (sta_ptr) sta_ptr->rx_seq[local_rx_pd->priority] = le16_to_cpu(local_rx_pd->seq_num); } } else { if (rx_pkt_type != PKT_TYPE_BAR) priv->rx_seq[local_rx_pd->priority] = seq_num; memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN); } /* Reorder and send to OS */ ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority, ta, (u8) rx_pkt_type, skb); if (ret || (rx_pkt_type == PKT_TYPE_BAR)) dev_kfree_skb_any(skb); if (ret) priv->stats.rx_dropped++; return ret; }
/* * This function processes the received buffer. * * The function looks into the RxPD and performs sanity tests on the * received buffer to ensure its a valid packet, before processing it * further. If the packet is determined to be aggregated, it is * de-aggregated accordingly. Non-unicast packets are sent directly to * the kernel/upper layers. Unicast packets are handed over to the * Rx reordering routine if 11n is enabled. * * The completion callback is called after processing in complete. */ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, struct sk_buff *skb) { struct mwifiex_adapter *adapter = priv->adapter; int ret = 0; struct rxpd *local_rx_pd; struct rx_packet_hdr *rx_pkt_hdr; u8 ta[ETH_ALEN]; u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num; local_rx_pd = (struct rxpd *) (skb->data); rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type); rx_pkt_offset = le16_to_cpu(local_rx_pd->rx_pkt_offset); rx_pkt_length = le16_to_cpu(local_rx_pd->rx_pkt_length); seq_num = le16_to_cpu(local_rx_pd->seq_num); rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset; if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) { dev_err(adapter->dev, "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n", skb->len, rx_pkt_offset, rx_pkt_length); priv->stats.rx_dropped++; dev_kfree_skb_any(skb); return ret; } if (rx_pkt_type == PKT_TYPE_AMSDU) { struct sk_buff_head list; struct sk_buff *rx_skb; __skb_queue_head_init(&list); skb_pull(skb, rx_pkt_offset); skb_trim(skb, rx_pkt_length); ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, priv->wdev->iftype, 0, false); while (!skb_queue_empty(&list)) { rx_skb = __skb_dequeue(&list); ret = mwifiex_recv_packet(priv, rx_skb); if (ret == -1) dev_err(adapter->dev, "Rx of A-MSDU failed"); } return 0; } else if (rx_pkt_type == PKT_TYPE_MGMT) { ret = mwifiex_process_mgmt_packet(priv, skb); if (ret) dev_err(adapter->dev, "Rx of mgmt packet failed"); dev_kfree_skb_any(skb); return ret; } /* * If the packet is not an unicast packet then send the packet * directly to os. Don't pass thru rx reordering */ if (!IS_11N_ENABLED(priv) || !ether_addr_equal_unaligned(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest)) { mwifiex_process_rx_packet(priv, skb); return ret; } if (mwifiex_queuing_ra_based(priv)) { memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); } else { if (rx_pkt_type != PKT_TYPE_BAR) priv->rx_seq[local_rx_pd->priority] = seq_num; memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN); } /* Reorder and send to OS */ ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority, ta, (u8) rx_pkt_type, skb); if (ret || (rx_pkt_type == PKT_TYPE_BAR)) dev_kfree_skb_any(skb); if (ret) priv->stats.rx_dropped++; return ret; }