Esempio n. 1
0
/**
 * 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;
}
Esempio n. 2
0
/*----------------------------------------------------------------
* p80211netdev_rx_bh
*
* Deferred processing of all received frames.
*
* Arguments:
*	wlandev		WLAN network device structure
*	skb		skbuff containing a full 802.11 frame.
* Returns:
*	nothing
* Side effects:
*
----------------------------------------------------------------*/
static void p80211netdev_rx_bh(unsigned long arg)
{
	wlandevice_t *wlandev = (wlandevice_t *) arg;
	struct sk_buff *skb = NULL;
	netdevice_t     *dev = wlandev->netdev;
	p80211_hdr_a3_t *hdr;
	UINT16 fc;

        DBFENTER;

	/* Let's empty our our queue */
	while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) {
		if (wlandev->state == WLAN_DEVICE_OPEN) {

			if (dev->type != ARPHRD_ETHER) {
				/* RAW frame; we shouldn't convert it */
				// XXX Append the Prism Header here instead.

				/* set up various data fields */
				skb->dev = dev;
				skb_reset_mac_header(skb);
				skb->ip_summed = CHECKSUM_NONE;
				skb->pkt_type = PACKET_OTHERHOST;
				skb->protocol = htons(ETH_P_80211_RAW);
				dev->last_rx = jiffies;

				wlandev->linux_stats.rx_packets++;
				wlandev->linux_stats.rx_bytes += skb->len;
				netif_rx_ni(skb);
				continue;
			} else {
				hdr = (p80211_hdr_a3_t *)skb->data;
				fc = ieee2host16(hdr->fc);
				if (p80211_rx_typedrop(wlandev, fc)) {
					dev_kfree_skb(skb);
					continue;
				}

				/* perform mcast filtering */
				if (wlandev->netdev->flags & IFF_ALLMULTI) {
					/* allow my local address through */
					if (memcmp(hdr->a1, wlandev->netdev->dev_addr, WLAN_ADDR_LEN) != 0) {
						/* but reject anything else that isn't multicast */
						if (!(hdr->a1[0] & 0x01)) {
							dev_kfree_skb(skb);
							continue;
						}
					}
				}

				if ( skb_p80211_to_ether(wlandev, wlandev->ethconv, skb) == 0 ) {
					skb->dev->last_rx = jiffies;
					wlandev->linux_stats.rx_packets++;
					wlandev->linux_stats.rx_bytes += skb->len;
					netif_rx_ni(skb);
					continue;
				}
				WLAN_LOG_DEBUG(1, "p80211_to_ether failed.\n");
			}
		}
		dev_kfree_skb(skb);
	}

        DBFEXIT;
}