⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ieee80211.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |			    (1 << IEEE80211_RADIOTAP_DATA_RETRIES));	if (!(status->flags & IEEE80211_TX_STATUS_ACK) &&	    !is_multicast_ether_addr(hdr->addr1))		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);	if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) &&	    (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT))		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);	else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS)		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);	rthdr->data_retries = status->retry_count;	rcu_read_lock();	monitors = local->monitors;	list_for_each_entry_rcu(sdata, &local->interfaces, list) {		/*		 * Using the monitors counter is possibly racy, but		 * if the value is wrong we simply either clone the skb		 * once too much or forget sending it to one monitor iface		 * The latter case isn't nice but fixing the race is much		 * more complicated.		 */		if (!monitors || !skb)			goto out;		if (sdata->type == IEEE80211_IF_TYPE_MNTR) {			if (!netif_running(sdata->dev))				continue;			monitors--;			if (monitors)				skb2 = skb_clone(skb, GFP_ATOMIC);			else				skb2 = NULL;			skb->dev = sdata->dev;			/* XXX: is this sufficient for BPF? */			skb_set_mac_header(skb, 0);			skb->ip_summed = CHECKSUM_UNNECESSARY;			skb->pkt_type = PACKET_OTHERHOST;			skb->protocol = htons(ETH_P_802_2);			memset(skb->cb, 0, sizeof(skb->cb));			netif_rx(skb);			skb = skb2;		}	} out:	rcu_read_unlock();	if (skb)		dev_kfree_skb(skb);}EXPORT_SYMBOL(ieee80211_tx_status);struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,					const struct ieee80211_ops *ops){	struct net_device *mdev;	struct ieee80211_local *local;	struct ieee80211_sub_if_data *sdata;	int priv_size;	struct wiphy *wiphy;	/* Ensure 32-byte alignment of our private data and hw private data.	 * We use the wiphy priv data for both our ieee80211_local and for	 * the driver's private data	 *	 * In memory it'll be like this:	 *	 * +-------------------------+	 * | struct wiphy	    |	 * +-------------------------+	 * | struct ieee80211_local  |	 * +-------------------------+	 * | driver's private data   |	 * +-------------------------+	 *	 */	priv_size = ((sizeof(struct ieee80211_local) +		      NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +		    priv_data_len;	wiphy = wiphy_new(&mac80211_config_ops, priv_size);	if (!wiphy)		return NULL;	wiphy->privid = mac80211_wiphy_privid;	local = wiphy_priv(wiphy);	local->hw.wiphy = wiphy;	local->hw.priv = (char *)local +			 ((sizeof(struct ieee80211_local) +			   NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);	BUG_ON(!ops->tx);	BUG_ON(!ops->start);	BUG_ON(!ops->stop);	BUG_ON(!ops->config);	BUG_ON(!ops->add_interface);	BUG_ON(!ops->remove_interface);	BUG_ON(!ops->configure_filter);	local->ops = ops;	/* for now, mdev needs sub_if_data :/ */	mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data),			    "wmaster%d", ether_setup);	if (!mdev) {		wiphy_free(wiphy);		return NULL;	}	sdata = IEEE80211_DEV_TO_SUB_IF(mdev);	mdev->ieee80211_ptr = &sdata->wdev;	sdata->wdev.wiphy = wiphy;	local->hw.queues = 1; /* default */	local->mdev = mdev;	local->rx_pre_handlers = ieee80211_rx_pre_handlers;	local->rx_handlers = ieee80211_rx_handlers;	local->tx_handlers = ieee80211_tx_handlers;	local->bridge_packets = 1;	local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;	local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;	local->short_retry_limit = 7;	local->long_retry_limit = 4;	local->hw.conf.radio_enabled = 1;	local->enabled_modes = ~0;	INIT_LIST_HEAD(&local->modes_list);	INIT_LIST_HEAD(&local->interfaces);	INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);	ieee80211_rx_bss_list_init(mdev);	sta_info_init(local);	mdev->hard_start_xmit = ieee80211_master_start_xmit;	mdev->open = ieee80211_master_open;	mdev->stop = ieee80211_master_stop;	mdev->type = ARPHRD_IEEE80211;	mdev->header_ops = &ieee80211_header_ops;	mdev->set_multicast_list = ieee80211_master_set_multicast_list;	sdata->type = IEEE80211_IF_TYPE_AP;	sdata->dev = mdev;	sdata->local = local;	sdata->u.ap.force_unicast_rateidx = -1;	sdata->u.ap.max_ratectrl_rateidx = -1;	ieee80211_if_sdata_init(sdata);	/* no RCU needed since we're still during init phase */	list_add_tail(&sdata->list, &local->interfaces);	tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,		     (unsigned long)local);	tasklet_disable(&local->tx_pending_tasklet);	tasklet_init(&local->tasklet,		     ieee80211_tasklet_handler,		     (unsigned long) local);	tasklet_disable(&local->tasklet);	skb_queue_head_init(&local->skb_queue);	skb_queue_head_init(&local->skb_queue_unreliable);	return local_to_hw(local);}EXPORT_SYMBOL(ieee80211_alloc_hw);int ieee80211_register_hw(struct ieee80211_hw *hw){	struct ieee80211_local *local = hw_to_local(hw);	const char *name;	int result;	result = wiphy_register(local->hw.wiphy);	if (result < 0)		return result;	name = wiphy_dev(local->hw.wiphy)->driver->name;	local->hw.workqueue = create_singlethread_workqueue(name);	if (!local->hw.workqueue) {		result = -ENOMEM;		goto fail_workqueue;	}	/*	 * The hardware needs headroom for sending the frame,	 * and we need some headroom for passing the frame to monitor	 * interfaces, but never both at the same time.	 */	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,				   sizeof(struct ieee80211_tx_status_rtap_hdr));	debugfs_hw_add(local);	local->hw.conf.beacon_int = 1000;	local->wstats_flags |= local->hw.max_rssi ?			       IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID;	local->wstats_flags |= local->hw.max_signal ?			       IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;	local->wstats_flags |= local->hw.max_noise ?			       IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;	if (local->hw.max_rssi < 0 || local->hw.max_noise < 0)		local->wstats_flags |= IW_QUAL_DBM;	result = sta_info_start(local);	if (result < 0)		goto fail_sta_info;	rtnl_lock();	result = dev_alloc_name(local->mdev, local->mdev->name);	if (result < 0)		goto fail_dev;	memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);	SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));	result = register_netdevice(local->mdev);	if (result < 0)		goto fail_dev;	ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));	ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);	result = ieee80211_init_rate_ctrl_alg(local,					      hw->rate_control_algorithm);	if (result < 0) {		printk(KERN_DEBUG "%s: Failed to initialize rate control "		       "algorithm\n", wiphy_name(local->hw.wiphy));		goto fail_rate;	}	result = ieee80211_wep_init(local);	if (result < 0) {		printk(KERN_DEBUG "%s: Failed to initialize wep\n",		       wiphy_name(local->hw.wiphy));		goto fail_wep;	}	ieee80211_install_qdisc(local->mdev);	/* add one default STA interface */	result = ieee80211_if_add(local->mdev, "wlan%d", NULL,				  IEEE80211_IF_TYPE_STA);	if (result)		printk(KERN_WARNING "%s: Failed to add default virtual iface\n",		       wiphy_name(local->hw.wiphy));	local->reg_state = IEEE80211_DEV_REGISTERED;	rtnl_unlock();	ieee80211_led_init(local);	return 0;fail_wep:	rate_control_deinitialize(local);fail_rate:	ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));	unregister_netdevice(local->mdev);fail_dev:	rtnl_unlock();	sta_info_stop(local);fail_sta_info:	debugfs_hw_del(local);	destroy_workqueue(local->hw.workqueue);fail_workqueue:	wiphy_unregister(local->hw.wiphy);	return result;}EXPORT_SYMBOL(ieee80211_register_hw);int ieee80211_register_hwmode(struct ieee80211_hw *hw,			      struct ieee80211_hw_mode *mode){	struct ieee80211_local *local = hw_to_local(hw);	struct ieee80211_rate *rate;	int i;	INIT_LIST_HEAD(&mode->list);	list_add_tail(&mode->list, &local->modes_list);	local->hw_modes |= (1 << mode->mode);	for (i = 0; i < mode->num_rates; i++) {		rate = &(mode->rates[i]);		rate->rate_inv = CHAN_UTIL_RATE_LCM / rate->rate;	}	ieee80211_prepare_rates(local, mode);	if (!local->oper_hw_mode) {		/* Default to this mode */		local->hw.conf.phymode = mode->mode;		local->oper_hw_mode = local->scan_hw_mode = mode;		local->oper_channel = local->scan_channel = &mode->channels[0];		local->hw.conf.mode = local->oper_hw_mode;		local->hw.conf.chan = local->oper_channel;	}	if (!(hw->flags & IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED))		ieee80211_set_default_regdomain(mode);	return 0;}EXPORT_SYMBOL(ieee80211_register_hwmode);void ieee80211_unregister_hw(struct ieee80211_hw *hw){	struct ieee80211_local *local = hw_to_local(hw);	struct ieee80211_sub_if_data *sdata, *tmp;	int i;	tasklet_kill(&local->tx_pending_tasklet);	tasklet_kill(&local->tasklet);	rtnl_lock();	BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED);	local->reg_state = IEEE80211_DEV_UNREGISTERED;	/*	 * At this point, interface list manipulations are fine	 * because the driver cannot be handing us frames any	 * more and the tasklet is killed.	 */	/*	 * First, we remove all non-master interfaces. Do this because they	 * may have bss pointer dependency on the master, and when we free	 * the master these would be freed as well, breaking our list	 * iteration completely.	 */	list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {		if (sdata->dev == local->mdev)			continue;		list_del(&sdata->list);		__ieee80211_if_del(local, sdata);	}	/* then, finally, remove the master interface */	__ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev));	rtnl_unlock();	ieee80211_rx_bss_list_deinit(local->mdev);	ieee80211_clear_tx_pending(local);	sta_info_stop(local);	rate_control_deinitialize(local);	debugfs_hw_del(local);	for (i = 0; i < NUM_IEEE80211_MODES; i++) {		kfree(local->supp_rates[i]);		kfree(local->basic_rates[i]);	}	if (skb_queue_len(&local->skb_queue)			|| skb_queue_len(&local->skb_queue_unreliable))		printk(KERN_WARNING "%s: skb_queue not empty\n",		       wiphy_name(local->hw.wiphy));	skb_queue_purge(&local->skb_queue);	skb_queue_purge(&local->skb_queue_unreliable);	destroy_workqueue(local->hw.workqueue);	wiphy_unregister(local->hw.wiphy);	ieee80211_wep_free(local);	ieee80211_led_exit(local);}EXPORT_SYMBOL(ieee80211_unregister_hw);void ieee80211_free_hw(struct ieee80211_hw *hw){	struct ieee80211_local *local = hw_to_local(hw);	ieee80211_if_free(local->mdev);	wiphy_free(local->hw.wiphy);}EXPORT_SYMBOL(ieee80211_free_hw);static int __init ieee80211_init(void){	struct sk_buff *skb;	int ret;	BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));#ifdef CONFIG_MAC80211_RCSIMPLE	ret = ieee80211_rate_control_register(&mac80211_rcsimple);	if (ret)		return ret;#endif	ret = ieee80211_wme_register();	if (ret) {#ifdef CONFIG_MAC80211_RCSIMPLE		ieee80211_rate_control_unregister(&mac80211_rcsimple);#endif		printk(KERN_DEBUG "ieee80211_init: failed to "		       "initialize WME (err=%d)\n", ret);		return ret;	}	ieee80211_debugfs_netdev_init();	ieee80211_regdomain_init();	return 0;}static void __exit ieee80211_exit(void){#ifdef CONFIG_MAC80211_RCSIMPLE	ieee80211_rate_control_unregister(&mac80211_rcsimple);#endif	ieee80211_wme_unregister();	ieee80211_debugfs_netdev_exit();}subsys_initcall(ieee80211_init);module_exit(ieee80211_exit);MODULE_DESCRIPTION("IEEE 802.11 subsystem");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -