diff options
author | David S. Miller <davem@davemloft.net> | 2009-02-10 02:30:44 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-10 02:30:44 -0500 |
commit | 4b53b361e0fbb2390f1d98ed9eede8e0c9a887b6 (patch) | |
tree | bf4b8635de66f50eb1d28f2d9e93a04adc4053f5 /net | |
parent | 4cdc44a231f906a6ec586637e6e4c4c216679da4 (diff) | |
parent | 99e0fca6740b98aed1f604fc2e0acbdbc9e7578a (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/iface.c | 47 | ||||
-rw-r--r-- | net/mac80211/main.c | 29 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 48 | ||||
-rw-r--r-- | net/mac80211/rx.c | 19 | ||||
-rw-r--r-- | net/mac80211/tx.c | 21 | ||||
-rw-r--r-- | net/mac80211/wext.c | 3 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 81 | ||||
-rw-r--r-- | net/wireless/reg.c | 2 | ||||
-rw-r--r-- | net/wireless/reg.h | 2 |
9 files changed, 194 insertions, 58 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 00562a8b99cf..915d04323a32 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -591,19 +591,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
591 | dev_mc_sync(local->mdev, dev); | 591 | dev_mc_sync(local->mdev, dev); |
592 | } | 592 | } |
593 | 593 | ||
594 | static void ieee80211_if_setup(struct net_device *dev) | ||
595 | { | ||
596 | ether_setup(dev); | ||
597 | dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
598 | dev->wireless_handlers = &ieee80211_iw_handler_def; | ||
599 | dev->set_multicast_list = ieee80211_set_multicast_list; | ||
600 | dev->change_mtu = ieee80211_change_mtu; | ||
601 | dev->open = ieee80211_open; | ||
602 | dev->stop = ieee80211_stop; | ||
603 | dev->destructor = free_netdev; | ||
604 | /* we will validate the address ourselves in ->open */ | ||
605 | dev->validate_addr = NULL; | ||
606 | } | ||
607 | /* | 594 | /* |
608 | * Called when the netdev is removed or, by the code below, before | 595 | * Called when the netdev is removed or, by the code below, before |
609 | * the interface type changes. | 596 | * the interface type changes. |
@@ -671,6 +658,34 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
671 | WARN_ON(flushed); | 658 | WARN_ON(flushed); |
672 | } | 659 | } |
673 | 660 | ||
661 | static const struct net_device_ops ieee80211_dataif_ops = { | ||
662 | .ndo_open = ieee80211_open, | ||
663 | .ndo_stop = ieee80211_stop, | ||
664 | .ndo_uninit = ieee80211_teardown_sdata, | ||
665 | .ndo_start_xmit = ieee80211_subif_start_xmit, | ||
666 | .ndo_set_multicast_list = ieee80211_set_multicast_list, | ||
667 | .ndo_change_mtu = ieee80211_change_mtu, | ||
668 | .ndo_set_mac_address = eth_mac_addr, | ||
669 | }; | ||
670 | |||
671 | static const struct net_device_ops ieee80211_monitorif_ops = { | ||
672 | .ndo_open = ieee80211_open, | ||
673 | .ndo_stop = ieee80211_stop, | ||
674 | .ndo_uninit = ieee80211_teardown_sdata, | ||
675 | .ndo_start_xmit = ieee80211_monitor_start_xmit, | ||
676 | .ndo_set_multicast_list = ieee80211_set_multicast_list, | ||
677 | .ndo_change_mtu = ieee80211_change_mtu, | ||
678 | .ndo_set_mac_address = eth_mac_addr, | ||
679 | }; | ||
680 | |||
681 | static void ieee80211_if_setup(struct net_device *dev) | ||
682 | { | ||
683 | ether_setup(dev); | ||
684 | dev->netdev_ops = &ieee80211_dataif_ops; | ||
685 | dev->wireless_handlers = &ieee80211_iw_handler_def; | ||
686 | dev->destructor = free_netdev; | ||
687 | } | ||
688 | |||
674 | /* | 689 | /* |
675 | * Helper function to initialise an interface to a specific type. | 690 | * Helper function to initialise an interface to a specific type. |
676 | */ | 691 | */ |
@@ -682,7 +697,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
682 | 697 | ||
683 | /* and set some type-dependent values */ | 698 | /* and set some type-dependent values */ |
684 | sdata->vif.type = type; | 699 | sdata->vif.type = type; |
685 | sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; | 700 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; |
686 | sdata->wdev.iftype = type; | 701 | sdata->wdev.iftype = type; |
687 | 702 | ||
688 | /* only monitor differs */ | 703 | /* only monitor differs */ |
@@ -703,7 +718,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
703 | break; | 718 | break; |
704 | case NL80211_IFTYPE_MONITOR: | 719 | case NL80211_IFTYPE_MONITOR: |
705 | sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; | 720 | sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; |
706 | sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit; | 721 | sdata->dev->netdev_ops = &ieee80211_monitorif_ops; |
707 | sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | | 722 | sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | |
708 | MONITOR_FLAG_OTHER_BSS; | 723 | MONITOR_FLAG_OTHER_BSS; |
709 | break; | 724 | break; |
@@ -809,8 +824,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
809 | if (ret) | 824 | if (ret) |
810 | goto fail; | 825 | goto fail; |
811 | 826 | ||
812 | ndev->uninit = ieee80211_teardown_sdata; | ||
813 | |||
814 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 827 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
815 | params && params->mesh_id_len) | 828 | params && params->mesh_id_len) |
816 | ieee80211_sdata_set_mesh_id(sdata, | 829 | ieee80211_sdata_set_mesh_id(sdata, |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index a109c06e8e4e..caf92424c76d 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -791,6 +791,23 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
791 | } | 791 | } |
792 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 792 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
793 | 793 | ||
794 | static const struct net_device_ops ieee80211_master_ops = { | ||
795 | .ndo_start_xmit = ieee80211_master_start_xmit, | ||
796 | .ndo_open = ieee80211_master_open, | ||
797 | .ndo_stop = ieee80211_master_stop, | ||
798 | .ndo_set_multicast_list = ieee80211_master_set_multicast_list, | ||
799 | .ndo_select_queue = ieee80211_select_queue, | ||
800 | }; | ||
801 | |||
802 | static void ieee80211_master_setup(struct net_device *mdev) | ||
803 | { | ||
804 | mdev->type = ARPHRD_IEEE80211; | ||
805 | mdev->netdev_ops = &ieee80211_master_ops; | ||
806 | mdev->header_ops = &ieee80211_header_ops; | ||
807 | mdev->tx_queue_len = 1000; | ||
808 | mdev->addr_len = ETH_ALEN; | ||
809 | } | ||
810 | |||
794 | int ieee80211_register_hw(struct ieee80211_hw *hw) | 811 | int ieee80211_register_hw(struct ieee80211_hw *hw) |
795 | { | 812 | { |
796 | struct ieee80211_local *local = hw_to_local(hw); | 813 | struct ieee80211_local *local = hw_to_local(hw); |
@@ -840,7 +857,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
840 | hw->ampdu_queues = 0; | 857 | hw->ampdu_queues = 0; |
841 | 858 | ||
842 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), | 859 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), |
843 | "wmaster%d", ether_setup, | 860 | "wmaster%d", ieee80211_master_setup, |
844 | ieee80211_num_queues(hw)); | 861 | ieee80211_num_queues(hw)); |
845 | if (!mdev) | 862 | if (!mdev) |
846 | goto fail_mdev_alloc; | 863 | goto fail_mdev_alloc; |
@@ -851,13 +868,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
851 | 868 | ||
852 | ieee80211_rx_bss_list_init(local); | 869 | ieee80211_rx_bss_list_init(local); |
853 | 870 | ||
854 | mdev->hard_start_xmit = ieee80211_master_start_xmit; | ||
855 | mdev->open = ieee80211_master_open; | ||
856 | mdev->stop = ieee80211_master_stop; | ||
857 | mdev->type = ARPHRD_IEEE80211; | ||
858 | mdev->header_ops = &ieee80211_header_ops; | ||
859 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; | ||
860 | |||
861 | local->hw.workqueue = | 871 | local->hw.workqueue = |
862 | create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); | 872 | create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); |
863 | if (!local->hw.workqueue) { | 873 | if (!local->hw.workqueue) { |
@@ -884,7 +894,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
884 | local->hw.conf.listen_interval = local->hw.max_listen_interval; | 894 | local->hw.conf.listen_interval = local->hw.max_listen_interval; |
885 | 895 | ||
886 | local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC | | 896 | local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC | |
887 | IEEE80211_HW_SIGNAL_DB | | ||
888 | IEEE80211_HW_SIGNAL_DBM) ? | 897 | IEEE80211_HW_SIGNAL_DBM) ? |
889 | IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID; | 898 | IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID; |
890 | local->wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ? | 899 | local->wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ? |
@@ -924,8 +933,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
924 | goto fail_wep; | 933 | goto fail_wep; |
925 | } | 934 | } |
926 | 935 | ||
927 | local->mdev->select_queue = ieee80211_select_queue; | ||
928 | |||
929 | /* add one default STA interface if supported */ | 936 | /* add one default STA interface if supported */ |
930 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { | 937 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { |
931 | result = ieee80211_if_add(local, "wlan%d", NULL, | 938 | result = ieee80211_if_add(local, "wlan%d", NULL, |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9d51e278c1e5..57967d32e5fd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1042,6 +1042,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, | |||
1042 | struct ieee80211_local *local = sdata->local; | 1042 | struct ieee80211_local *local = sdata->local; |
1043 | struct sta_info *sta; | 1043 | struct sta_info *sta; |
1044 | int disassoc; | 1044 | int disassoc; |
1045 | bool remove_bss = false; | ||
1045 | 1046 | ||
1046 | /* TODO: start monitoring current AP signal quality and number of | 1047 | /* TODO: start monitoring current AP signal quality and number of |
1047 | * missed beacons. Scan other channels every now and then and search | 1048 | * missed beacons. Scan other channels every now and then and search |
@@ -1067,6 +1068,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, | |||
1067 | "range\n", | 1068 | "range\n", |
1068 | sdata->dev->name, ifsta->bssid); | 1069 | sdata->dev->name, ifsta->bssid); |
1069 | disassoc = 1; | 1070 | disassoc = 1; |
1071 | remove_bss = true; | ||
1070 | } else | 1072 | } else |
1071 | ieee80211_send_probe_req(sdata, ifsta->bssid, | 1073 | ieee80211_send_probe_req(sdata, ifsta->bssid, |
1072 | ifsta->ssid, | 1074 | ifsta->ssid, |
@@ -1086,12 +1088,24 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, | |||
1086 | 1088 | ||
1087 | rcu_read_unlock(); | 1089 | rcu_read_unlock(); |
1088 | 1090 | ||
1089 | if (disassoc) | 1091 | if (disassoc) { |
1090 | ieee80211_set_disassoc(sdata, ifsta, true, true, | 1092 | ieee80211_set_disassoc(sdata, ifsta, true, true, |
1091 | WLAN_REASON_PREV_AUTH_NOT_VALID); | 1093 | WLAN_REASON_PREV_AUTH_NOT_VALID); |
1092 | else | 1094 | if (remove_bss) { |
1095 | struct ieee80211_bss *bss; | ||
1096 | |||
1097 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, | ||
1098 | local->hw.conf.channel->center_freq, | ||
1099 | ifsta->ssid, ifsta->ssid_len); | ||
1100 | if (bss) { | ||
1101 | atomic_dec(&bss->users); | ||
1102 | ieee80211_rx_bss_put(local, bss); | ||
1103 | } | ||
1104 | } | ||
1105 | } else { | ||
1093 | mod_timer(&ifsta->timer, jiffies + | 1106 | mod_timer(&ifsta->timer, jiffies + |
1094 | IEEE80211_MONITORING_INTERVAL); | 1107 | IEEE80211_MONITORING_INTERVAL); |
1108 | } | ||
1095 | } | 1109 | } |
1096 | 1110 | ||
1097 | 1111 | ||
@@ -1503,13 +1517,22 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1503 | struct ieee80211_bss *bss) | 1517 | struct ieee80211_bss *bss) |
1504 | { | 1518 | { |
1505 | struct ieee80211_local *local = sdata->local; | 1519 | struct ieee80211_local *local = sdata->local; |
1506 | int res, rates, i, j; | 1520 | int res = 0, rates, i, j; |
1507 | struct sk_buff *skb; | 1521 | struct sk_buff *skb; |
1508 | struct ieee80211_mgmt *mgmt; | 1522 | struct ieee80211_mgmt *mgmt; |
1509 | u8 *pos; | 1523 | u8 *pos; |
1510 | struct ieee80211_supported_band *sband; | 1524 | struct ieee80211_supported_band *sband; |
1511 | union iwreq_data wrqu; | 1525 | union iwreq_data wrqu; |
1512 | 1526 | ||
1527 | if (local->ops->reset_tsf) { | ||
1528 | /* Reset own TSF to allow time synchronization work. */ | ||
1529 | local->ops->reset_tsf(local_to_hw(local)); | ||
1530 | } | ||
1531 | |||
1532 | if ((ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) && | ||
1533 | memcmp(ifsta->bssid, bss->bssid, ETH_ALEN) == 0) | ||
1534 | return res; | ||
1535 | |||
1513 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + | 1536 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + |
1514 | sdata->u.sta.ie_proberesp_len); | 1537 | sdata->u.sta.ie_proberesp_len); |
1515 | if (!skb) { | 1538 | if (!skb) { |
@@ -1520,13 +1543,11 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1520 | 1543 | ||
1521 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1544 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
1522 | 1545 | ||
1523 | /* Remove possible STA entries from other IBSS networks. */ | 1546 | if (!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) { |
1524 | sta_info_flush_delayed(sdata); | 1547 | /* Remove possible STA entries from other IBSS networks. */ |
1525 | 1548 | sta_info_flush_delayed(sdata); | |
1526 | if (local->ops->reset_tsf) { | ||
1527 | /* Reset own TSF to allow time synchronization work. */ | ||
1528 | local->ops->reset_tsf(local_to_hw(local)); | ||
1529 | } | 1549 | } |
1550 | |||
1530 | memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); | 1551 | memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); |
1531 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); | 1552 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); |
1532 | if (res) | 1553 | if (res) |
@@ -2415,8 +2436,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, | |||
2415 | ifsta->ssid_len); | 2436 | ifsta->ssid_len); |
2416 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; | 2437 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; |
2417 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); | 2438 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); |
2418 | } else | 2439 | } else { |
2440 | ifsta->assoc_scan_tries = 0; | ||
2419 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | 2441 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
2442 | } | ||
2420 | } | 2443 | } |
2421 | return -1; | 2444 | return -1; |
2422 | } | 2445 | } |
@@ -2720,9 +2743,8 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | |||
2720 | 2743 | ||
2721 | if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 2744 | if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
2722 | ifsta = &sdata->u.sta; | 2745 | ifsta = &sdata->u.sta; |
2723 | if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || | 2746 | if ((!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) || |
2724 | (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && | 2747 | !ieee80211_sta_active_ibss(sdata)) |
2725 | !ieee80211_sta_active_ibss(sdata))) | ||
2726 | ieee80211_sta_find_ibss(sdata, ifsta); | 2748 | ieee80211_sta_find_ibss(sdata, ifsta); |
2727 | } | 2749 | } |
2728 | 2750 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 19ffc8ef1d1d..8e8ddbfcd236 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -86,8 +86,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
86 | 86 | ||
87 | if (status->flag & RX_FLAG_TSFT) | 87 | if (status->flag & RX_FLAG_TSFT) |
88 | len += 8; | 88 | len += 8; |
89 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DB || | 89 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
90 | local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | ||
91 | len += 1; | 90 | len += 1; |
92 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) | 91 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) |
93 | len += 1; | 92 | len += 1; |
@@ -199,14 +198,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
199 | *pos = status->antenna; | 198 | *pos = status->antenna; |
200 | pos++; | 199 | pos++; |
201 | 200 | ||
202 | /* IEEE80211_RADIOTAP_DB_ANTSIGNAL */ | ||
203 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DB) { | ||
204 | *pos = status->signal; | ||
205 | rthdr->it_present |= | ||
206 | cpu_to_le32(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL); | ||
207 | pos++; | ||
208 | } | ||
209 | |||
210 | /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */ | 201 | /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */ |
211 | 202 | ||
212 | /* IEEE80211_RADIOTAP_RX_FLAGS */ | 203 | /* IEEE80211_RADIOTAP_RX_FLAGS */ |
@@ -1225,12 +1216,12 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1225 | 1216 | ||
1226 | switch (hdr->frame_control & | 1217 | switch (hdr->frame_control & |
1227 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { | 1218 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { |
1228 | case __constant_cpu_to_le16(IEEE80211_FCTL_TODS): | 1219 | case cpu_to_le16(IEEE80211_FCTL_TODS): |
1229 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP && | 1220 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP && |
1230 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) | 1221 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) |
1231 | return -1; | 1222 | return -1; |
1232 | break; | 1223 | break; |
1233 | case __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): | 1224 | case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): |
1234 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && | 1225 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && |
1235 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) | 1226 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) |
1236 | return -1; | 1227 | return -1; |
@@ -1244,13 +1235,13 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1244 | } | 1235 | } |
1245 | } | 1236 | } |
1246 | break; | 1237 | break; |
1247 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): | 1238 | case cpu_to_le16(IEEE80211_FCTL_FROMDS): |
1248 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | 1239 | if (sdata->vif.type != NL80211_IFTYPE_STATION || |
1249 | (is_multicast_ether_addr(dst) && | 1240 | (is_multicast_ether_addr(dst) && |
1250 | !compare_ether_addr(src, dev->dev_addr))) | 1241 | !compare_ether_addr(src, dev->dev_addr))) |
1251 | return -1; | 1242 | return -1; |
1252 | break; | 1243 | break; |
1253 | case __constant_cpu_to_le16(0): | 1244 | case cpu_to_le16(0): |
1254 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | 1245 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1255 | return -1; | 1246 | return -1; |
1256 | break; | 1247 | break; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 7b013fb0d27f..f1c726d94f47 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1433,10 +1433,31 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1433 | struct net_device *dev) | 1433 | struct net_device *dev) |
1434 | { | 1434 | { |
1435 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1435 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1436 | struct ieee80211_channel *chan = local->hw.conf.channel; | ||
1436 | struct ieee80211_radiotap_header *prthdr = | 1437 | struct ieee80211_radiotap_header *prthdr = |
1437 | (struct ieee80211_radiotap_header *)skb->data; | 1438 | (struct ieee80211_radiotap_header *)skb->data; |
1438 | u16 len_rthdr; | 1439 | u16 len_rthdr; |
1439 | 1440 | ||
1441 | /* | ||
1442 | * Frame injection is not allowed if beaconing is not allowed | ||
1443 | * or if we need radar detection. Beaconing is usually not allowed when | ||
1444 | * the mode or operation (Adhoc, AP, Mesh) does not support DFS. | ||
1445 | * Passive scan is also used in world regulatory domains where | ||
1446 | * your country is not known and as such it should be treated as | ||
1447 | * NO TX unless the channel is explicitly allowed in which case | ||
1448 | * your current regulatory domain would not have the passive scan | ||
1449 | * flag. | ||
1450 | * | ||
1451 | * Since AP mode uses monitor interfaces to inject/TX management | ||
1452 | * frames we can make AP mode the exception to this rule once it | ||
1453 | * supports radar detection as its implementation can deal with | ||
1454 | * radar detection by itself. We can do that later by adding a | ||
1455 | * monitor flag interfaces used for AP support. | ||
1456 | */ | ||
1457 | if ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR | | ||
1458 | IEEE80211_CHAN_PASSIVE_SCAN))) | ||
1459 | goto fail; | ||
1460 | |||
1440 | /* check for not even having the fixed radiotap header part */ | 1461 | /* check for not even having the fixed radiotap header part */ |
1441 | if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) | 1462 | if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) |
1442 | goto fail; /* too short to be possibly valid */ | 1463 | goto fail; /* too short to be possibly valid */ |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 5c88b8246bbb..bad1cfbfdf18 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -173,8 +173,7 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, | |||
173 | range->num_encoding_sizes = 2; | 173 | range->num_encoding_sizes = 2; |
174 | range->max_encoding_tokens = NUM_DEFAULT_KEYS; | 174 | range->max_encoding_tokens = NUM_DEFAULT_KEYS; |
175 | 175 | ||
176 | if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC || | 176 | if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) |
177 | local->hw.flags & IEEE80211_HW_SIGNAL_DB) | ||
178 | range->max_qual.level = local->hw.max_signal; | 177 | range->max_qual.level = local->hw.max_signal; |
179 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 178 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
180 | range->max_qual.level = -110; | 179 | range->max_qual.level = -110; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e69da8d20474..d452396006ee 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2093,6 +2093,81 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) | |||
2093 | 2093 | ||
2094 | #undef FILL_IN_MESH_PARAM_IF_SET | 2094 | #undef FILL_IN_MESH_PARAM_IF_SET |
2095 | 2095 | ||
2096 | static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | ||
2097 | { | ||
2098 | struct sk_buff *msg; | ||
2099 | void *hdr = NULL; | ||
2100 | struct nlattr *nl_reg_rules; | ||
2101 | unsigned int i; | ||
2102 | int err = -EINVAL; | ||
2103 | |||
2104 | mutex_lock(&cfg80211_drv_mutex); | ||
2105 | |||
2106 | if (!cfg80211_regdomain) | ||
2107 | goto out; | ||
2108 | |||
2109 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
2110 | if (!msg) { | ||
2111 | err = -ENOBUFS; | ||
2112 | goto out; | ||
2113 | } | ||
2114 | |||
2115 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | ||
2116 | NL80211_CMD_GET_REG); | ||
2117 | if (!hdr) | ||
2118 | goto nla_put_failure; | ||
2119 | |||
2120 | NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, | ||
2121 | cfg80211_regdomain->alpha2); | ||
2122 | |||
2123 | nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES); | ||
2124 | if (!nl_reg_rules) | ||
2125 | goto nla_put_failure; | ||
2126 | |||
2127 | for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) { | ||
2128 | struct nlattr *nl_reg_rule; | ||
2129 | const struct ieee80211_reg_rule *reg_rule; | ||
2130 | const struct ieee80211_freq_range *freq_range; | ||
2131 | const struct ieee80211_power_rule *power_rule; | ||
2132 | |||
2133 | reg_rule = &cfg80211_regdomain->reg_rules[i]; | ||
2134 | freq_range = ®_rule->freq_range; | ||
2135 | power_rule = ®_rule->power_rule; | ||
2136 | |||
2137 | nl_reg_rule = nla_nest_start(msg, i); | ||
2138 | if (!nl_reg_rule) | ||
2139 | goto nla_put_failure; | ||
2140 | |||
2141 | NLA_PUT_U32(msg, NL80211_ATTR_REG_RULE_FLAGS, | ||
2142 | reg_rule->flags); | ||
2143 | NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_START, | ||
2144 | freq_range->start_freq_khz); | ||
2145 | NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_END, | ||
2146 | freq_range->end_freq_khz); | ||
2147 | NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, | ||
2148 | freq_range->max_bandwidth_khz); | ||
2149 | NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, | ||
2150 | power_rule->max_antenna_gain); | ||
2151 | NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, | ||
2152 | power_rule->max_eirp); | ||
2153 | |||
2154 | nla_nest_end(msg, nl_reg_rule); | ||
2155 | } | ||
2156 | |||
2157 | nla_nest_end(msg, nl_reg_rules); | ||
2158 | |||
2159 | genlmsg_end(msg, hdr); | ||
2160 | err = genlmsg_unicast(msg, info->snd_pid); | ||
2161 | goto out; | ||
2162 | |||
2163 | nla_put_failure: | ||
2164 | genlmsg_cancel(msg, hdr); | ||
2165 | err = -EMSGSIZE; | ||
2166 | out: | ||
2167 | mutex_unlock(&cfg80211_drv_mutex); | ||
2168 | return err; | ||
2169 | } | ||
2170 | |||
2096 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | 2171 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) |
2097 | { | 2172 | { |
2098 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; | 2173 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; |
@@ -2333,6 +2408,12 @@ static struct genl_ops nl80211_ops[] = { | |||
2333 | .flags = GENL_ADMIN_PERM, | 2408 | .flags = GENL_ADMIN_PERM, |
2334 | }, | 2409 | }, |
2335 | { | 2410 | { |
2411 | .cmd = NL80211_CMD_GET_REG, | ||
2412 | .doit = nl80211_get_reg, | ||
2413 | .policy = nl80211_policy, | ||
2414 | /* can be retrieved by unprivileged users */ | ||
2415 | }, | ||
2416 | { | ||
2336 | .cmd = NL80211_CMD_SET_REG, | 2417 | .cmd = NL80211_CMD_SET_REG, |
2337 | .doit = nl80211_set_reg, | 2418 | .doit = nl80211_set_reg, |
2338 | .policy = nl80211_policy, | 2419 | .policy = nl80211_policy, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f643d3981102..2323644330cd 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -57,7 +57,7 @@ static u32 supported_bandwidths[] = { | |||
57 | /* Central wireless core regulatory domains, we only need two, | 57 | /* Central wireless core regulatory domains, we only need two, |
58 | * the current one and a world regulatory domain in case we have no | 58 | * the current one and a world regulatory domain in case we have no |
59 | * information to give us an alpha2 */ | 59 | * information to give us an alpha2 */ |
60 | static const struct ieee80211_regdomain *cfg80211_regdomain; | 60 | const struct ieee80211_regdomain *cfg80211_regdomain; |
61 | 61 | ||
62 | /* We use this as a place for the rd structure built from the | 62 | /* We use this as a place for the rd structure built from the |
63 | * last parsed country IE to rest until CRDA gets back to us with | 63 | * last parsed country IE to rest until CRDA gets back to us with |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index eb1dd5bc9b27..fe8c83f34fb7 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef __NET_WIRELESS_REG_H | 1 | #ifndef __NET_WIRELESS_REG_H |
2 | #define __NET_WIRELESS_REG_H | 2 | #define __NET_WIRELESS_REG_H |
3 | 3 | ||
4 | extern const struct ieee80211_regdomain *cfg80211_regdomain; | ||
5 | |||
4 | bool is_world_regdom(const char *alpha2); | 6 | bool is_world_regdom(const char *alpha2); |
5 | bool reg_is_valid_request(const char *alpha2); | 7 | bool reg_is_valid_request(const char *alpha2); |
6 | 8 | ||