static int __init ieee80211_init(void)
{
#ifdef CONFIG_IEEE80211_DEBUG
	struct proc_dir_entry *e;

	ieee80211_debug_level = debug;
	ieee80211_proc = proc_mkdir(DRV_NAME, proc_net);
	if (ieee80211_proc == NULL) {
		IEEE80211_ERROR("Unable to create " DRV_NAME
				" proc directory\n");
		return -EIO;
	}
	e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
			      ieee80211_proc);
	if (!e) {
		remove_proc_entry(DRV_NAME, proc_net);
		ieee80211_proc = NULL;
		return -EIO;
	}
	e->read_proc = show_debug_level;
	e->write_proc = store_debug_level;
	e->data = NULL;
#endif				/* CONFIG_IEEE80211_DEBUG */

	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");

	return 0;
}
Ejemplo n.º 2
0
int ieee80211_debug_init(void)
{
	struct proc_dir_entry *e;

	ieee80211_debug_level = debug;

	ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
	if (ieee80211_proc == NULL) {
		IEEE80211_ERROR("Unable to create " DRV_NAME
				" proc directory\n");
		return -EIO;
	}
	e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
			      ieee80211_proc);
	if (!e) {
		remove_proc_entry(DRV_NAME, init_net.proc_net);
		ieee80211_proc = NULL;
		return -EIO;
	}
	e->read_proc = show_debug_level;
	e->write_proc = store_debug_level;
	e->data = NULL;

	return 0;
}
Ejemplo n.º 3
0
int __init ieee80211_rtl_init(void)
{
	struct proc_dir_entry *e;
	int retval;

	retval = ieee80211_crypto_init();
	if (retval)
		return retval;
	retval = ieee80211_crypto_tkip_init();
	if (retval) {
		ieee80211_crypto_deinit();
		return retval;
	}
	retval = ieee80211_crypto_ccmp_init();
	if (retval) {
		ieee80211_crypto_tkip_exit();
		ieee80211_crypto_deinit();
		return retval;
	}
	retval = ieee80211_crypto_wep_init();
	if (retval) {
		ieee80211_crypto_ccmp_exit();
		ieee80211_crypto_tkip_exit();
		ieee80211_crypto_deinit();
		return retval;
	}

	ieee80211_debug_level = debug;
	ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
	if (ieee80211_proc == NULL) {
		IEEE80211_ERROR("Unable to create " DRV_NAME
				" proc directory\n");
		return -EIO;
	}
	e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
			ieee80211_proc);
	if (!e) {
		remove_proc_entry(DRV_NAME, init_net.proc_net);
		ieee80211_proc = NULL;
		return -EIO;
	}
	e->read_proc = show_debug_level;
	e->write_proc = store_debug_level;
	e->data = NULL;

	return 0;
}
Ejemplo n.º 4
0
int __init ieee80211_debug_init(void)
{
	struct proc_dir_entry *e;

	ieee80211_debug_level = debug;

	ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
	if (ieee80211_proc == NULL) {
		IEEE80211_ERROR("Unable to create " DRV_NAME
				" proc directory\n");
		return -EIO;
	}
	e = proc_create("debug_level", S_IRUGO | S_IWUSR, 
			      ieee80211_proc, &fops);
	if (!e) {
		remove_proc_entry(DRV_NAME, init_net.proc_net);
		ieee80211_proc = NULL;
		return -EIO;
	}
	return 0;
}
Ejemplo n.º 5
0
/* Incoming skb is converted to a txb which consists of
 * a block of 802.11 fragment packets (stored as skbs) */
int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
{
    struct ieee80211_device *ieee = netdev_priv(dev);
    struct ieee80211_txb *txb = NULL;
    struct ieee80211_hdr_3addrqos *frag_hdr;
    int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
        rts_required;
    unsigned long flags;
    struct net_device_stats *stats = &ieee->stats;
    int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
    int bytes, fc, hdr_len;
    struct sk_buff *skb_frag;
    struct ieee80211_hdr_3addrqos header = {/* Ensure zero initialized */
        .duration_id = 0,
        .seq_ctl = 0,
        .qos_ctl = 0
    };
    u8 dest[ETH_ALEN], src[ETH_ALEN];
    struct ieee80211_crypt_data *crypt;
    int priority = skb->priority;
    int snapped = 0;

    if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority))
        return NETDEV_TX_BUSY;

    spin_lock_irqsave(&ieee->lock, flags);

    /* If there is no driver handler to take the TXB, dont' bother
     * creating it... */
    if (!ieee->hard_start_xmit) {
        printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
        goto success;
    }

    if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
        printk(KERN_WARNING "%s: skb too small (%d).\n",
               ieee->dev->name, skb->len);
        goto success;
    }

    ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);

    crypt = ieee->crypt[ieee->tx_keyidx];

    encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
              ieee->sec.encrypt;

    host_encrypt = ieee->host_encrypt && encrypt && crypt;
    host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt;
    host_build_iv = ieee->host_build_iv && encrypt && crypt;

    if (!encrypt && ieee->ieee802_1x &&
            ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
        stats->tx_dropped++;
        goto success;
    }

    /* Save source and destination addresses */
    memcpy(dest, skb->data, ETH_ALEN);
    memcpy(src, skb->data + ETH_ALEN, ETH_ALEN);

    if (host_encrypt || host_build_iv)
        fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
             IEEE80211_FCTL_PROTECTED;
    else
        fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;

    if (ieee->iw_mode == IW_MODE_INFRA) {
        fc |= IEEE80211_FCTL_TODS;
        /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
        memcpy(header.addr1, ieee->bssid, ETH_ALEN);
        memcpy(header.addr2, src, ETH_ALEN);
        memcpy(header.addr3, dest, ETH_ALEN);
    } else if (ieee->iw_mode == IW_MODE_ADHOC) {
        /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
        memcpy(header.addr1, dest, ETH_ALEN);
        memcpy(header.addr2, src, ETH_ALEN);
        memcpy(header.addr3, ieee->bssid, ETH_ALEN);
    }
    hdr_len = IEEE80211_3ADDR_LEN;

    if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) {
        fc |= IEEE80211_STYPE_QOS_DATA;
        hdr_len += 2;

        skb->priority = ieee80211_classify(skb);
        header.qos_ctl |= skb->priority & IEEE80211_QCTL_TID;
    }
    header.frame_ctl = cpu_to_le16(fc);

    /* Advance the SKB to the start of the payload */
    skb_pull(skb, sizeof(struct ethhdr));

    /* Determine total amount of storage required for TXB packets */
    bytes = skb->len + SNAP_SIZE + sizeof(u16);

    /* Encrypt msdu first on the whole data packet. */
    if ((host_encrypt || host_encrypt_msdu) &&
            crypt && crypt->ops && crypt->ops->encrypt_msdu) {
        int res = 0;
        int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
                  crypt->ops->extra_msdu_postfix_len;
        struct sk_buff *skb_new = dev_alloc_skb(len);

        if (unlikely(!skb_new))
            goto failed;

        skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
        memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
        snapped = 1;
        ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
                            ether_type);
        memcpy(skb_put(skb_new, skb->len), skb->data, skb->len);
        res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);
        if (res < 0) {
            IEEE80211_ERROR("msdu encryption failed\n");
            dev_kfree_skb_any(skb_new);
            goto failed;
        }
        dev_kfree_skb_any(skb);
        skb = skb_new;
        bytes += crypt->ops->extra_msdu_prefix_len +
                 crypt->ops->extra_msdu_postfix_len;
        skb_pull(skb, hdr_len);
    }

    if (host_encrypt || ieee->host_open_frag) {
        /* Determine fragmentation size based on destination (multicast
         * and broadcast are not fragmented) */
        if (is_multicast_ether_addr(dest) ||
                is_broadcast_ether_addr(dest))
            frag_size = MAX_FRAG_THRESHOLD;
        else
            frag_size = ieee->fts;

        /* Determine amount of payload per fragment.  Regardless of if
         * this stack is providing the full 802.11 header, one will
         * eventually be affixed to this fragment -- so we must account
         * for it when determining the amount of payload space. */
        bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
        if (ieee->config &
                (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
            bytes_per_frag -= IEEE80211_FCS_LEN;

        /* Each fragment may need to have room for encryptiong
         * pre/postfix */
        if (host_encrypt)
            bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
                              crypt->ops->extra_mpdu_postfix_len;

        /* Number of fragments is the total
         * bytes_per_frag / payload_per_fragment */
        nr_frags = bytes / bytes_per_frag;
        bytes_last_frag = bytes % bytes_per_frag;
        if (bytes_last_frag)
            nr_frags++;
        else
            bytes_last_frag = bytes_per_frag;
    } else {
        nr_frags = 1;
        bytes_per_frag = bytes_last_frag = bytes;
        frag_size = bytes + IEEE80211_3ADDR_LEN;
    }

    rts_required = (frag_size > ieee->rts
                    && ieee->config & CFG_IEEE80211_RTS);
    if (rts_required)
        nr_frags++;

    /* When we allocate the TXB we allocate enough space for the reserve
     * and full fragment bytes (bytes_per_frag doesn't include prefix,
     * postfix, header, FCS, etc.) */
    txb = ieee80211_alloc_txb(nr_frags, frag_size,
                              ieee->tx_headroom, GFP_ATOMIC);
    if (unlikely(!txb)) {
        printk(KERN_WARNING "%s: Could not allocate TXB\n",
               ieee->dev->name);
        goto failed;
    }
    txb->encrypted = encrypt;
    if (host_encrypt)
        txb->payload_size = frag_size * (nr_frags - 1) +
                            bytes_last_frag;
    else
        txb->payload_size = bytes;

    if (rts_required) {
        skb_frag = txb->fragments[0];
        frag_hdr =
            (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);

        /*
         * Set header frame_ctl to the RTS.
         */
        header.frame_ctl =
            cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
        memcpy(frag_hdr, &header, hdr_len);

        /*
         * Restore header frame_ctl to the original data setting.
         */
        header.frame_ctl = cpu_to_le16(fc);

        if (ieee->config &
                (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
            skb_put(skb_frag, 4);

        txb->rts_included = 1;
        i = 1;
    } else
        i = 0;

    for (; i < nr_frags; i++) {
        skb_frag = txb->fragments[i];

        if (host_encrypt || host_build_iv)
            skb_reserve(skb_frag,
                        crypt->ops->extra_mpdu_prefix_len);

        frag_hdr =
            (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
        memcpy(frag_hdr, &header, hdr_len);

        /* If this is not the last fragment, then add the MOREFRAGS
         * bit to the frame control */
        if (i != nr_frags - 1) {
            frag_hdr->frame_ctl =
                cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS);
            bytes = bytes_per_frag;
        } else {
            /* The last fragment takes the remaining length */
            bytes = bytes_last_frag;
        }

        if (i == 0 && !snapped) {
            ieee80211_copy_snap(skb_put
                                (skb_frag, SNAP_SIZE + sizeof(u16)),
                                ether_type);
            bytes -= SNAP_SIZE + sizeof(u16);
        }

        memcpy(skb_put(skb_frag, bytes), skb->data, bytes);

        /* Advance the SKB... */
        skb_pull(skb, bytes);

        /* Encryption routine will move the header forward in order
         * to insert the IV between the header and the payload */
        if (host_encrypt)
            ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
        else if (host_build_iv) {
            struct ieee80211_crypt_data *crypt;

            crypt = ieee->crypt[ieee->tx_keyidx];
            atomic_inc(&crypt->refcnt);
            if (crypt->ops->build_iv)
                crypt->ops->build_iv(skb_frag, hdr_len,
                                     ieee->sec.keys[ieee->sec.active_key],
                                     ieee->sec.key_sizes[ieee->sec.active_key],
                                     crypt->priv);
            atomic_dec(&crypt->refcnt);
        }

        if (ieee->config &
                (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
            skb_put(skb_frag, 4);
    }

success:
    spin_unlock_irqrestore(&ieee->lock, flags);

    dev_kfree_skb_any(skb);

    if (txb) {
        int ret = (*ieee->hard_start_xmit) (txb, dev, priority);
        if (ret == 0) {
            stats->tx_packets++;
            stats->tx_bytes += txb->payload_size;
            return 0;
        }

        if (ret == NETDEV_TX_BUSY) {
            printk(KERN_ERR "%s: NETDEV_TX_BUSY returned; "
                   "driver should report queue full via "
                   "ieee_device->is_queue_full.\n",
                   ieee->dev->name);
        }

        ieee80211_txb_free(txb);
    }

    return 0;

failed:
    spin_unlock_irqrestore(&ieee->lock, flags);
    netif_stop_queue(dev);
    stats->tx_errors++;
    return 1;
}

/* Incoming 802.11 strucure is converted to a TXB
 * a block of 802.11 fragment packets (stored as skbs) */
int ieee80211_tx_frame(struct ieee80211_device *ieee,
                       struct ieee80211_hdr *frame, int hdr_len, int total_len,
                       int encrypt_mpdu)
{
    struct ieee80211_txb *txb = NULL;
    unsigned long flags;
    struct net_device_stats *stats = &ieee->stats;
    struct sk_buff *skb_frag;
    int priority = -1;
    int fraglen = total_len;
    int headroom = ieee->tx_headroom;
    struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];

    spin_lock_irqsave(&ieee->lock, flags);

    if (encrypt_mpdu && (!ieee->sec.encrypt || !crypt))
        encrypt_mpdu = 0;

    /* If there is no driver handler to take the TXB, dont' bother
     * creating it... */
    if (!ieee->hard_start_xmit) {
        printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
        goto success;
    }

    if (unlikely(total_len < 24)) {
        printk(KERN_WARNING "%s: skb too small (%d).\n",
               ieee->dev->name, total_len);
        goto success;
    }

    if (encrypt_mpdu) {
        frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
        fraglen += crypt->ops->extra_mpdu_prefix_len +
                   crypt->ops->extra_mpdu_postfix_len;
        headroom += crypt->ops->extra_mpdu_prefix_len;
    }

    /* When we allocate the TXB we allocate enough space for the reserve
     * and full fragment bytes (bytes_per_frag doesn't include prefix,
     * postfix, header, FCS, etc.) */
    txb = ieee80211_alloc_txb(1, fraglen, headroom, GFP_ATOMIC);
    if (unlikely(!txb)) {
        printk(KERN_WARNING "%s: Could not allocate TXB\n",
               ieee->dev->name);
        goto failed;
    }
    txb->encrypted = 0;
    txb->payload_size = fraglen;

    skb_frag = txb->fragments[0];

    memcpy(skb_put(skb_frag, total_len), frame, total_len);

    if (ieee->config &
            (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
        skb_put(skb_frag, 4);

    /* To avoid overcomplicating things, we do the corner-case frame
     * encryption in software. The only real situation where encryption is
     * needed here is during software-based shared key authentication. */
    if (encrypt_mpdu)
        ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);

success:
    spin_unlock_irqrestore(&ieee->lock, flags);

    if (txb) {
        if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) {
            stats->tx_packets++;
            stats->tx_bytes += txb->payload_size;
            return 0;
        }
        ieee80211_txb_free(txb);
    }
    return 0;

failed:
    spin_unlock_irqrestore(&ieee->lock, flags);
    stats->tx_errors++;
    return 1;
}

EXPORT_SYMBOL(ieee80211_tx_frame);
EXPORT_SYMBOL(ieee80211_txb_free);
struct net_device *alloc_ieee80211(int sizeof_priv)
{
	struct ieee80211_device *ieee;
	struct net_device *dev;
	int err;

	IEEE80211_DEBUG_INFO("Initializing...\n");

	dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
	if (!dev) {
		IEEE80211_ERROR("Unable to network device.\n");
		goto failed;
	}
	ieee = netdev_priv(dev);
	dev->hard_start_xmit = ieee80211_xmit;
	dev->change_mtu = ieee80211_change_mtu;

	/* Drivers are free to override this if the generic implementation
	 * does not meet their needs. */
	dev->get_stats = ieee80211_generic_get_stats;

	ieee->dev = dev;

	err = ieee80211_networks_allocate(ieee);
	if (err) {
		IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
		goto failed;
	}
	ieee80211_networks_initialize(ieee);

	/* Default fragmentation threshold is maximum payload size */
	ieee->fts = DEFAULT_FTS;
	ieee->rts = DEFAULT_FTS;
	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
	ieee->open_wep = 1;

	/* Default to enabling full open WEP with host based encrypt/decrypt */
	ieee->host_encrypt = 1;
	ieee->host_decrypt = 1;
	ieee->host_mc_decrypt = 1;

	/* Host fragementation in Open mode. Default is enabled.
	 * Note: host fragmentation is always enabled if host encryption
	 * is enabled. For cards can do hardware encryption, they must do
	 * hardware fragmentation as well. So we don't need a variable
	 * like host_enc_frag. */
	ieee->host_open_frag = 1;
	ieee->ieee802_1x = 1;	/* Default to supporting 802.1x */

	INIT_LIST_HEAD(&ieee->crypt_deinit_list);
	setup_timer(&ieee->crypt_deinit_timer, ieee80211_crypt_deinit_handler,
			(unsigned long)ieee);
	ieee->crypt_quiesced = 0;

	spin_lock_init(&ieee->lock);

	ieee->wpa_enabled = 0;
	ieee->drop_unencrypted = 0;
	ieee->privacy_invoked = 0;

	return dev;

      failed:
	if (dev)
		free_netdev(dev);
	return NULL;
}
Ejemplo n.º 7
0
struct net_device *alloc_ieee80211(int sizeof_priv)
{
	struct ieee80211_device *ieee;
	struct net_device *dev;
	int i,err;

	IEEE80211_DEBUG_INFO("Initializing...\n");

	dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
	if (!dev) {
		IEEE80211_ERROR("Unable to network device.\n");
		goto failed;
	}

	ieee = netdev_priv(dev);
	memset(ieee, 0, sizeof(struct ieee80211_device)+sizeof_priv);
	ieee->dev = dev;

	err = ieee80211_networks_allocate(ieee);
	if (err) {
		IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
				err);
		goto failed;
	}
	ieee80211_networks_initialize(ieee);


	/* Default fragmentation threshold is maximum payload size */
	ieee->fts = DEFAULT_FTS;
	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
	ieee->open_wep = 1;

	/* Default to enabling full open WEP with host based encrypt/decrypt */
	ieee->host_encrypt = 1;
	ieee->host_decrypt = 1;
	ieee->ieee802_1x = 1; /* Default to supporting 802.1x */

	INIT_LIST_HEAD(&ieee->crypt_deinit_list);
	init_timer(&ieee->crypt_deinit_timer);
	ieee->crypt_deinit_timer.data = (unsigned long)ieee;
	ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;

	spin_lock_init(&ieee->lock);
	spin_lock_init(&ieee->wpax_suitlist_lock);
	spin_lock_init(&ieee->bw_spinlock);
	spin_lock_init(&ieee->reorder_spinlock);
	atomic_set(&(ieee->atm_chnlop), 0);
	atomic_set(&(ieee->atm_swbw), 0);

	ieee->wpax_type_set = 0;
 	ieee->wpa_enabled = 0;
 	ieee->tkip_countermeasures = 0;
 	ieee->drop_unencrypted = 0;
 	ieee->privacy_invoked = 0;
 	ieee->ieee802_1x = 1;
	ieee->raw_tx = 0;
	ieee->hwsec_active = 0; //disable hwsec, switch it on when necessary.

	ieee80211_softmac_init(ieee);

	ieee->pHTInfo = kzalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
	if (ieee->pHTInfo == NULL)
	{
		IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for HTInfo\n");
		return NULL;
	}
	HTUpdateDefaultSetting(ieee);
	HTInitializeHTInfo(ieee); //may move to other place.
	TSInitialize(ieee);

	for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
		INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);

	for (i = 0; i < 17; i++) {
	  ieee->last_rxseq_num[i] = -1;
	  ieee->last_rxfrag_num[i] = -1;
	  ieee->last_packet_time[i] = 0;
	}

//These function were added to load crypte module autoly
	ieee80211_tkip_null();
	ieee80211_wep_null();
	ieee80211_ccmp_null();

	return dev;

 failed:
	if (dev)
		free_netdev(dev);

	return NULL;
}