aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-02-10 02:30:44 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-10 02:30:44 -0500
commit4b53b361e0fbb2390f1d98ed9eede8e0c9a887b6 (patch)
treebf4b8635de66f50eb1d28f2d9e93a04adc4053f5 /net
parent4cdc44a231f906a6ec586637e6e4c4c216679da4 (diff)
parent99e0fca6740b98aed1f604fc2e0acbdbc9e7578a (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.c47
-rw-r--r--net/mac80211/main.c29
-rw-r--r--net/mac80211/mlme.c48
-rw-r--r--net/mac80211/rx.c19
-rw-r--r--net/mac80211/tx.c21
-rw-r--r--net/mac80211/wext.c3
-rw-r--r--net/wireless/nl80211.c81
-rw-r--r--net/wireless/reg.c2
-rw-r--r--net/wireless/reg.h2
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
594static 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
661static 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
671static 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
681static 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}
792EXPORT_SYMBOL(ieee80211_alloc_hw); 792EXPORT_SYMBOL(ieee80211_alloc_hw);
793 793
794static 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
802static 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
794int ieee80211_register_hw(struct ieee80211_hw *hw) 811int 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
2096static 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 = &reg_rule->freq_range;
2135 power_rule = &reg_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
2163nla_put_failure:
2164 genlmsg_cancel(msg, hdr);
2165 err = -EMSGSIZE;
2166out:
2167 mutex_unlock(&cfg80211_drv_mutex);
2168 return err;
2169}
2170
2096static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) 2171static 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 */
60static const struct ieee80211_regdomain *cfg80211_regdomain; 60const 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
4extern const struct ieee80211_regdomain *cfg80211_regdomain;
5
4bool is_world_regdom(const char *alpha2); 6bool is_world_regdom(const char *alpha2);
5bool reg_is_valid_request(const char *alpha2); 7bool reg_is_valid_request(const char *alpha2);
6 8