Johannes Berg says: ==================== Work continues in various areas: * port authorized event for 4-way-HS offload (Avi) * enable MFP optional for such devices (Emmanuel) * Kees's timer setup patch for mac80211 mesh (the part that isn't trivially scripted) * improve VLAN vs. TXQ handling (myself) * load regulatory database as firmware file (myself) * with various other small improvements and cleanups I merged net-next once in the meantime to allow Kees's timer setup patch to go in. ====================
Unified · Split
| @@ -299,9 +299,6 @@ Data path helpers · 298 unmodified lines | |||
| 299 | .. kernel-doc:: include/net/cfg80211.h | 299 | .. kernel-doc:: include/net/cfg80211.h |
| 300 | :functions: ieee80211_data_to_8023 | 300 | :functions: ieee80211_data_to_8023 |
| 301 | 301 | ||
| 302 | .. kernel-doc:: include/net/cfg80211.h | ||
| 303 | :functions: ieee80211_data_from_8023 | ||
| 304 | |||
| 305 | .. kernel-doc:: include/net/cfg80211.h | 302 | .. kernel-doc:: include/net/cfg80211.h |
| 306 | :functions: ieee80211_amsdu_to_8023s | 303 | :functions: ieee80211_amsdu_to_8023s |
| 307 | 304 | ||
| @@ -19,6 +19,14 @@ core regulatory domain all wireless devices should adhere to. · 18 unmodified lines | |||
| 19 | How to get regulatory domains to the kernel | 19 | How to get regulatory domains to the kernel |
| 20 | ------------------------------------------- | 20 | ------------------------------------------- |
| 21 | 21 | ||
| 22 | When the regulatory domain is first set up, the kernel will request a | ||
| 23 | database file (regulatory.db) containing all the regulatory rules. It | ||
| 24 | will then use that database when it needs to look up the rules for a | ||
| 25 | given country. | ||
| 26 | |||
| 27 | How to get regulatory domains to the kernel (old CRDA solution) | ||
| 28 | --------------------------------------------------------------- | ||
| 29 | |||
| 22 | Userspace gets a regulatory domain in the kernel by having | 30 | Userspace gets a regulatory domain in the kernel by having |
| 23 | a userspace agent build it and send it via nl80211. Only | 31 | a userspace agent build it and send it via nl80211. Only |
| 24 | expected regulatory domains will be respected by the kernel. | 32 | expected regulatory domains will be respected by the kernel. |
| @@ -192,23 +200,5 @@ Then in some part of your code after your wiphy has been registered: · 167 unmodified lines | |||
| 192 | Statically compiled regulatory database | 200 | Statically compiled regulatory database |
| 193 | --------------------------------------- | 201 | --------------------------------------- |
| 194 | 202 | ||
| 195 | In most situations the userland solution using CRDA as described | 203 | When a database should be fixed into the kernel, it can be provided as a |
| 196 | above is the preferred solution. However in some cases a set of | 204 | firmware file at build time that is then linked into the kernel. |
| 197 | rules built into the kernel itself may be desirable. To account | ||
| 198 | for this situation, a configuration option has been provided | ||
| 199 | (i.e. CONFIG_CFG80211_INTERNAL_REGDB). With this option enabled, | ||
| 200 | the wireless database information contained in net/wireless/db.txt is | ||
| 201 | used to generate a data structure encoded in net/wireless/regdb.c. | ||
| 202 | That option also enables code in net/wireless/reg.c which queries | ||
| 203 | the data in regdb.c as an alternative to using CRDA. | ||
| 204 | |||
| 205 | The file net/wireless/db.txt should be kept up-to-date with the db.txt | ||
| 206 | file available in the git repository here: | ||
| 207 | |||
| 208 | git://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git | ||
| 209 | |||
| 210 | Again, most users in most situations should be using the CRDA package | ||
| 211 | provided with their distribution, and in most other situations users | ||
| 212 | should be building and using CRDA on their own rather than using | ||
| 213 | this option. If you are not absolutely sure that you should be using | ||
| 214 | CONFIG_CFG80211_INTERNAL_REGDB then _DO_NOT_USE_IT_. | ||
| @@ -3329,17 +3329,22 @@ S: Maintained · 3328 unmodified lines | |||
| 3329 | F: drivers/auxdisplay/cfag12864bfb.c | 3329 | F: drivers/auxdisplay/cfag12864bfb.c |
| 3330 | F: include/linux/cfag12864b.h | 3330 | F: include/linux/cfag12864b.h |
| 3331 | 3331 | ||
| 3332 | CFG80211 and NL80211 | 3332 | 802.11 (including CFG80211/NL80211) |
| 3333 | M: Johannes Berg <johannes@sipsolutions.net> | 3333 | M: Johannes Berg <johannes@sipsolutions.net> |
| 3334 | L: linux-wireless@vger.kernel.org | 3334 | L: linux-wireless@vger.kernel.org |
| 3335 | W: http://wireless.kernel.org/ | 3335 | W: http://wireless.kernel.org/ |
| 3336 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git | 3336 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git |
| 3337 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git | 3337 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git |
| 3338 | S: Maintained | 3338 | S: Maintained |
| 3339 | F: net/wireless/ | ||
| 3339 | F: include/uapi/linux/nl80211.h | 3340 | F: include/uapi/linux/nl80211.h |
| 3341 | F: include/linux/ieee80211.h | ||
| 3342 | F: include/net/wext.h | ||
| 3340 | F: include/net/cfg80211.h | 3343 | F: include/net/cfg80211.h |
| 3341 | F: net/wireless/* | 3344 | F: include/net/iw_handler.h |
| 3342 | X: net/wireless/wext* | 3345 | F: include/net/ieee80211_radiotap.h |
| 3346 | F: Documentation/driver-api/80211/cfg80211.rst | ||
| 3347 | F: Documentation/networking/regulatory.txt | ||
| 3343 | 3348 | ||
| 3344 | CHAR and MISC DRIVERS | 3349 | CHAR and MISC DRIVERS |
| 3345 | M: Arnd Bergmann <arnd@arndb.de> | 3350 | M: Arnd Bergmann <arnd@arndb.de> |
| @@ -8208,6 +8213,7 @@ F: Documentation/networking/mac80211-injection.txt · 4862 unmodified lines | |||
| 8208 | F: include/net/mac80211.h | 8213 | F: include/net/mac80211.h |
| 8209 | F: net/mac80211/ | 8214 | F: net/mac80211/ |
| 8210 | F: drivers/net/wireless/mac80211_hwsim.[ch] | 8215 | F: drivers/net/wireless/mac80211_hwsim.[ch] |
| 8216 | F: Documentation/networking/mac80211_hwsim/README | ||
| 8211 | 8217 | ||
| 8212 | MAILBOX API | 8218 | MAILBOX API |
| 8213 | M: Jassi Brar <jassisinghbrar@gmail.com> | 8219 | M: Jassi Brar <jassisinghbrar@gmail.com> |
| @@ -11492,6 +11498,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git · 3278 unmodified lines | |||
| 11492 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git | 11498 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git |
| 11493 | S: Maintained | 11499 | S: Maintained |
| 11494 | F: Documentation/rfkill.txt | 11500 | F: Documentation/rfkill.txt |
| 11501 | F: Documentation/ABI/stable/sysfs-class-rfkill | ||
| 11495 | F: net/rfkill/ | 11502 | F: net/rfkill/ |
| 11496 | 11503 | ||
| 11497 | RHASHTABLE | 11504 | RHASHTABLE |
| @@ -396,7 +396,7 @@ static int mac80211_hwsim_vendor_cmd_test(struct wiphy *wiphy, · 395 unmodified lines | |||
| 396 | if (!tb[QCA_WLAN_VENDOR_ATTR_TEST]) | 396 | if (!tb[QCA_WLAN_VENDOR_ATTR_TEST]) |
| 397 | return -EINVAL; | 397 | return -EINVAL; |
| 398 | val = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_TEST]); | 398 | val = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_TEST]); |
| 399 | wiphy_debug(wiphy, "%s: test=%u\n", __func__, val); | 399 | wiphy_dbg(wiphy, "%s: test=%u\n", __func__, val); |
| 400 | 400 | ||
| 401 | /* Send a vendor event as a test. Note that this would not normally be | 401 | /* Send a vendor event as a test. Note that this would not normally be |
| 402 | * done within a command handler, but rather, based on some other | 402 | * done within a command handler, but rather, based on some other |
| @@ -643,9 +643,9 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) · 240 unmodified lines | |||
| 643 | if (!vp->assoc) | 643 | if (!vp->assoc) |
| 644 | return; | 644 | return; |
| 645 | 645 | ||
| 646 | wiphy_debug(data->hw->wiphy, | 646 | wiphy_dbg(data->hw->wiphy, |
| 647 | "%s: send PS-Poll to %pM for aid %d\n", | 647 | "%s: send PS-Poll to %pM for aid %d\n", |
| 648 | __func__, vp->bssid, vp->aid); | 648 | __func__, vp->bssid, vp->aid); |
| 649 | 649 | ||
| 650 | skb = dev_alloc_skb(sizeof(*pspoll)); | 650 | skb = dev_alloc_skb(sizeof(*pspoll)); |
| 651 | if (!skb) | 651 | if (!skb) |
| @@ -674,9 +674,9 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, · 22 unmodified lines | |||
| 674 | if (!vp->assoc) | 674 | if (!vp->assoc) |
| 675 | return; | 675 | return; |
| 676 | 676 | ||
| 677 | wiphy_debug(data->hw->wiphy, | 677 | wiphy_dbg(data->hw->wiphy, |
| 678 | "%s: send data::nullfunc to %pM ps=%d\n", | 678 | "%s: send data::nullfunc to %pM ps=%d\n", |
| 679 | __func__, vp->bssid, ps); | 679 | __func__, vp->bssid, ps); |
| 680 | 680 | ||
| 681 | skb = dev_alloc_skb(sizeof(*hdr)); | 681 | skb = dev_alloc_skb(sizeof(*hdr)); |
| 682 | if (!skb) | 682 | if (!skb) |
| @@ -1034,7 +1034,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, · 351 unmodified lines | |||
| 1034 | msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, | 1034 | msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, |
| 1035 | HWSIM_CMD_FRAME); | 1035 | HWSIM_CMD_FRAME); |
| 1036 | if (msg_head == NULL) { | 1036 | if (msg_head == NULL) { |
| 1037 | printk(KERN_DEBUG "mac80211_hwsim: problem with msg_head\n"); | 1037 | pr_debug("mac80211_hwsim: problem with msg_head\n"); |
| 1038 | goto nla_put_failure; | 1038 | goto nla_put_failure; |
| 1039 | } | 1039 | } |
| 1040 | 1040 | ||
| @@ -1093,7 +1093,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, · 52 unmodified lines | |||
| 1093 | nla_put_failure: | 1093 | nla_put_failure: |
| 1094 | nlmsg_free(skb); | 1094 | nlmsg_free(skb); |
| 1095 | err_free_txskb: | 1095 | err_free_txskb: |
| 1096 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); | 1096 | pr_debug("mac80211_hwsim: error occurred in %s\n", __func__); |
| 1097 | ieee80211_free_txskb(hw, my_skb); | 1097 | ieee80211_free_txskb(hw, my_skb); |
| 1098 | data->tx_failed++; | 1098 | data->tx_failed++; |
| 1099 | } | 1099 | } |
| @@ -1347,7 +1347,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, · 247 unmodified lines | |||
| 1347 | } | 1347 | } |
| 1348 | 1348 | ||
| 1349 | if (data->idle && !data->tmp_chan) { | 1349 | if (data->idle && !data->tmp_chan) { |
| 1350 | wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); | 1350 | wiphy_dbg(hw->wiphy, "Trying to TX when idle - reject\n"); |
| 1351 | ieee80211_free_txskb(hw, skb); | 1351 | ieee80211_free_txskb(hw, skb); |
| 1352 | return; | 1352 | return; |
| 1353 | } | 1353 | } |
| @@ -1408,7 +1408,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, · 54 unmodified lines | |||
| 1408 | static int mac80211_hwsim_start(struct ieee80211_hw *hw) | 1408 | static int mac80211_hwsim_start(struct ieee80211_hw *hw) |
| 1409 | { | 1409 | { |
| 1410 | struct mac80211_hwsim_data *data = hw->priv; | 1410 | struct mac80211_hwsim_data *data = hw->priv; |
| 1411 | wiphy_debug(hw->wiphy, "%s\n", __func__); | 1411 | wiphy_dbg(hw->wiphy, "%s\n", __func__); |
| 1412 | data->started = true; | 1412 | data->started = true; |
| 1413 | return 0; | 1413 | return 0; |
| 1414 | } | 1414 | } |
| @@ -1419,16 +1419,16 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw) · 4 unmodified lines | |||
| 1419 | struct mac80211_hwsim_data *data = hw->priv; | 1419 | struct mac80211_hwsim_data *data = hw->priv; |
| 1420 | data->started = false; | 1420 | data->started = false; |
| 1421 | tasklet_hrtimer_cancel(&data->beacon_timer); | 1421 | tasklet_hrtimer_cancel(&data->beacon_timer); |
| 1422 | wiphy_debug(hw->wiphy, "%s\n", __func__); | 1422 | wiphy_dbg(hw->wiphy, "%s\n", __func__); |
| 1423 | } | 1423 | } |
| 1424 | 1424 | ||
| 1425 | 1425 | ||
| 1426 | static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, | 1426 | static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, |
| 1427 | struct ieee80211_vif *vif) | 1427 | struct ieee80211_vif *vif) |
| 1428 | { | 1428 | { |
| 1429 | wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", | 1429 | wiphy_dbg(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", |
| 1430 | __func__, ieee80211_vif_type_p2p(vif), | 1430 | __func__, ieee80211_vif_type_p2p(vif), |
| 1431 | vif->addr); | 1431 | vif->addr); |
| 1432 | hwsim_set_magic(vif); | 1432 | hwsim_set_magic(vif); |
| 1433 | 1433 | ||
| 1434 | vif->cab_queue = 0; | 1434 | vif->cab_queue = 0; |
| @@ -1447,9 +1447,9 @@ static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw, · 12 unmodified lines | |||
| 1447 | bool newp2p) | 1447 | bool newp2p) |
| 1448 | { | 1448 | { |
| 1449 | newtype = ieee80211_iftype_p2p(newtype, newp2p); | 1449 | newtype = ieee80211_iftype_p2p(newtype, newp2p); |
| 1450 | wiphy_debug(hw->wiphy, | 1450 | wiphy_dbg(hw->wiphy, |
| 1451 | "%s (old type=%d, new type=%d, mac_addr=%pM)\n", | 1451 | "%s (old type=%d, new type=%d, mac_addr=%pM)\n", |
| 1452 | __func__, ieee80211_vif_type_p2p(vif), | 1452 | __func__, ieee80211_vif_type_p2p(vif), |
| 1453 | newtype, vif->addr); | 1453 | newtype, vif->addr); |
| 1454 | hwsim_check_magic(vif); | 1454 | hwsim_check_magic(vif); |
| 1455 | 1455 | ||
| @@ -1465,9 +1465,9 @@ static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw, · 9 unmodified lines | |||
| 1465 | static void mac80211_hwsim_remove_interface( | 1465 | static void mac80211_hwsim_remove_interface( |
| 1466 | struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 1466 | struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
| 1467 | { | 1467 | { |
| 1468 | wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", | 1468 | wiphy_dbg(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", |
| 1469 | __func__, ieee80211_vif_type_p2p(vif), | 1469 | __func__, ieee80211_vif_type_p2p(vif), |
| 1470 | vif->addr); | 1470 | vif->addr); |
| 1471 | hwsim_check_magic(vif); | 1471 | hwsim_check_magic(vif); |
| 1472 | hwsim_clear_magic(vif); | 1472 | hwsim_clear_magic(vif); |
| 1473 | } | 1473 | } |
| @@ -1589,23 +1589,23 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) · 115 unmodified lines | |||
| 1589 | int idx; | 1589 | int idx; |
| 1590 | 1590 | ||
| 1591 | if (conf->chandef.chan) | 1591 | if (conf->chandef.chan) |
| 1592 | wiphy_debug(hw->wiphy, | 1592 | wiphy_dbg(hw->wiphy, |
| 1593 | "%s (freq=%d(%d - %d)/%s idle=%d ps=%d smps=%s)\n", | 1593 | "%s (freq=%d(%d - %d)/%s idle=%d ps=%d smps=%s)\n", |
| 1594 | __func__, | 1594 | __func__, |
| 1595 | conf->chandef.chan->center_freq, | 1595 | conf->chandef.chan->center_freq, |
| 1596 | conf->chandef.center_freq1, | 1596 | conf->chandef.center_freq1, |
| 1597 | conf->chandef.center_freq2, | 1597 | conf->chandef.center_freq2, |
| 1598 | hwsim_chanwidths[conf->chandef.width], | 1598 | hwsim_chanwidths[conf->chandef.width], |
| 1599 | !!(conf->flags & IEEE80211_CONF_IDLE), | 1599 | !!(conf->flags & IEEE80211_CONF_IDLE), |
| 1600 | !!(conf->flags & IEEE80211_CONF_PS), | 1600 | !!(conf->flags & IEEE80211_CONF_PS), |
| 1601 | smps_modes[conf->smps_mode]); | 1601 | smps_modes[conf->smps_mode]); |
| 1602 | else | 1602 | else |
| 1603 | wiphy_debug(hw->wiphy, | 1603 | wiphy_dbg(hw->wiphy, |
| 1604 | "%s (freq=0 idle=%d ps=%d smps=%s)\n", | 1604 | "%s (freq=0 idle=%d ps=%d smps=%s)\n", |
| 1605 | __func__, | 1605 | __func__, |
| 1606 | !!(conf->flags & IEEE80211_CONF_IDLE), | 1606 | !!(conf->flags & IEEE80211_CONF_IDLE), |
| 1607 | !!(conf->flags & IEEE80211_CONF_PS), | 1607 | !!(conf->flags & IEEE80211_CONF_PS), |
| 1608 | smps_modes[conf->smps_mode]); | 1608 | smps_modes[conf->smps_mode]); |
| 1609 | 1609 | ||
| 1610 | data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); | 1610 | data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
| 1611 | 1611 | ||
| @@ -1659,7 +1659,7 @@ static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, · 47 unmodified lines | |||
| 1659 | { | 1659 | { |
| 1660 | struct mac80211_hwsim_data *data = hw->priv; | 1660 | struct mac80211_hwsim_data *data = hw->priv; |
| 1661 | 1661 | ||
| 1662 | wiphy_debug(hw->wiphy, "%s\n", __func__); | 1662 | wiphy_dbg(hw->wiphy, "%s\n", __func__); |
| 1663 | 1663 | ||
| 1664 | data->rx_filter = 0; | 1664 | data->rx_filter = 0; |
| 1665 | if (*total_flags & FIF_ALLMULTI) | 1665 | if (*total_flags & FIF_ALLMULTI) |
| @@ -1688,25 +1688,25 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, · 22 unmodified lines | |||
| 1688 | 1688 | ||
| 1689 | hwsim_check_magic(vif); | 1689 | hwsim_check_magic(vif); |
| 1690 | 1690 | ||
| 1691 | wiphy_debug(hw->wiphy, "%s(changed=0x%x vif->addr=%pM)\n", | 1691 | wiphy_dbg(hw->wiphy, "%s(changed=0x%x vif->addr=%pM)\n", |
| 1692 | __func__, changed, vif->addr); | 1692 | __func__, changed, vif->addr); |
| 1693 | 1693 | ||
| 1694 | if (changed & BSS_CHANGED_BSSID) { | 1694 | if (changed & BSS_CHANGED_BSSID) { |
| 1695 | wiphy_debug(hw->wiphy, "%s: BSSID changed: %pM\n", | 1695 | wiphy_dbg(hw->wiphy, "%s: BSSID changed: %pM\n", |
| 1696 | __func__, info->bssid); | 1696 | __func__, info->bssid); |
| 1697 | memcpy(vp->bssid, info->bssid, ETH_ALEN); | 1697 | memcpy(vp->bssid, info->bssid, ETH_ALEN); |
| 1698 | } | 1698 | } |
| 1699 | 1699 | ||
| 1700 | if (changed & BSS_CHANGED_ASSOC) { | 1700 | if (changed & BSS_CHANGED_ASSOC) { |
| 1701 | wiphy_debug(hw->wiphy, " ASSOC: assoc=%d aid=%d\n", | 1701 | wiphy_dbg(hw->wiphy, " ASSOC: assoc=%d aid=%d\n", |
| 1702 | info->assoc, info->aid); | 1702 | info->assoc, info->aid); |
| 1703 | vp->assoc = info->assoc; | 1703 | vp->assoc = info->assoc; |
| 1704 | vp->aid = info->aid; | 1704 | vp->aid = info->aid; |
| 1705 | } | 1705 | } |
| 1706 | 1706 | ||
| 1707 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 1707 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
| 1708 | wiphy_debug(hw->wiphy, " BCN EN: %d (BI=%u)\n", | 1708 | wiphy_dbg(hw->wiphy, " BCN EN: %d (BI=%u)\n", |
| 1709 | info->enable_beacon, info->beacon_int); | 1709 | info->enable_beacon, info->beacon_int); |
| 1710 | vp->bcn_en = info->enable_beacon; | 1710 | vp->bcn_en = info->enable_beacon; |
| 1711 | if (data->started && | 1711 | if (data->started && |
| 1712 | !hrtimer_is_queued(&data->beacon_timer.timer) && | 1712 | !hrtimer_is_queued(&data->beacon_timer.timer) && |
| @@ -1725,8 +1725,8 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, · 12 unmodified lines | |||
| 1725 | ieee80211_iterate_active_interfaces_atomic( | 1725 | ieee80211_iterate_active_interfaces_atomic( |
| 1726 | data->hw, IEEE80211_IFACE_ITER_NORMAL, | 1726 | data->hw, IEEE80211_IFACE_ITER_NORMAL, |
| 1727 | mac80211_hwsim_bcn_en_iter, &count); | 1727 | mac80211_hwsim_bcn_en_iter, &count); |
| 1728 | wiphy_debug(hw->wiphy, " beaconing vifs remaining: %u", | 1728 | wiphy_dbg(hw->wiphy, " beaconing vifs remaining: %u", |
| 1729 | count); | 1729 | count); |
| 1730 | if (count == 0) { | 1730 | if (count == 0) { |
| 1731 | tasklet_hrtimer_cancel(&data->beacon_timer); | 1731 | tasklet_hrtimer_cancel(&data->beacon_timer); |
| 1732 | data->beacon_int = 0; | 1732 | data->beacon_int = 0; |
| @@ -1735,31 +1735,31 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, · 2 unmodified lines | |||
| 1735 | } | 1735 | } |
| 1736 | 1736 | ||
| 1737 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | 1737 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { |
| 1738 | wiphy_debug(hw->wiphy, " ERP_CTS_PROT: %d\n", | 1738 | wiphy_dbg(hw->wiphy, " ERP_CTS_PROT: %d\n", |
| 1739 | info->use_cts_prot); | 1739 | info->use_cts_prot); |
| 1740 | } | 1740 | } |
| 1741 | 1741 | ||
| 1742 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 1742 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
| 1743 | wiphy_debug(hw->wiphy, " ERP_PREAMBLE: %d\n", | 1743 | wiphy_dbg(hw->wiphy, " ERP_PREAMBLE: %d\n", |
| 1744 | info->use_short_preamble); | 1744 | info->use_short_preamble); |
| 1745 | } | 1745 | } |
| 1746 | 1746 | ||
| 1747 | if (changed & BSS_CHANGED_ERP_SLOT) { | 1747 | if (changed & BSS_CHANGED_ERP_SLOT) { |
| 1748 | wiphy_debug(hw->wiphy, " ERP_SLOT: %d\n", info->use_short_slot); | 1748 | wiphy_dbg(hw->wiphy, " ERP_SLOT: %d\n", info->use_short_slot); |
| 1749 | } | 1749 | } |
| 1750 | 1750 | ||
| 1751 | if (changed & BSS_CHANGED_HT) { | 1751 | if (changed & BSS_CHANGED_HT) { |
| 1752 | wiphy_debug(hw->wiphy, " HT: op_mode=0x%x\n", | 1752 | wiphy_dbg(hw->wiphy, " HT: op_mode=0x%x\n", |
| 1753 | info->ht_operation_mode); | 1753 | info->ht_operation_mode); |
| 1754 | } | 1754 | } |
| 1755 | 1755 | ||
| 1756 | if (changed & BSS_CHANGED_BASIC_RATES) { | 1756 | if (changed & BSS_CHANGED_BASIC_RATES) { |
| 1757 | wiphy_debug(hw->wiphy, " BASIC_RATES: 0x%llx\n", | 1757 | wiphy_dbg(hw->wiphy, " BASIC_RATES: 0x%llx\n", |
| 1758 | (unsigned long long) info->basic_rates); | 1758 | (unsigned long long) info->basic_rates); |
| 1759 | } | 1759 | } |
| 1760 | 1760 | ||
| 1761 | if (changed & BSS_CHANGED_TXPOWER) | 1761 | if (changed & BSS_CHANGED_TXPOWER) |
| 1762 | wiphy_debug(hw->wiphy, " TX Power: %d dBm\n", info->txpower); | 1762 | wiphy_dbg(hw->wiphy, " TX Power: %d dBm\n", info->txpower); |
| 1763 | } | 1763 | } |
| 1764 | 1764 | ||
| 1765 | static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw, | 1765 | static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw, |
| @@ -1813,11 +1813,11 @@ static int mac80211_hwsim_conf_tx( · 47 unmodified lines | |||
| 1813 | struct ieee80211_vif *vif, u16 queue, | 1813 | struct ieee80211_vif *vif, u16 queue, |
| 1814 | const struct ieee80211_tx_queue_params *params) | 1814 | const struct ieee80211_tx_queue_params *params) |
| 1815 | { | 1815 | { |
| 1816 | wiphy_debug(hw->wiphy, | 1816 | wiphy_dbg(hw->wiphy, |
| 1817 | "%s (queue=%d txop=%d cw_min=%d cw_max=%d aifs=%d)\n", | 1817 | "%s (queue=%d txop=%d cw_min=%d cw_max=%d aifs=%d)\n", |
| 1818 | __func__, queue, | 1818 | __func__, queue, |
| 1819 | params->txop, params->cw_min, | 1819 | params->txop, params->cw_min, |
| 1820 | params->cw_max, params->aifs); | 1820 | params->cw_max, params->aifs); |
| 1821 | return 0; | 1821 | return 0; |
| 1822 | } | 1822 | } |
| 1823 | 1823 | ||
| @@ -1981,7 +1981,7 @@ static void hw_scan_work(struct work_struct *work) · 157 unmodified lines | |||
| 1981 | .aborted = false, | 1981 | .aborted = false, |
| 1982 | }; | 1982 | }; |
| 1983 | 1983 | ||
| 1984 | wiphy_debug(hwsim->hw->wiphy, "hw scan complete\n"); | 1984 | wiphy_dbg(hwsim->hw->wiphy, "hw scan complete\n"); |
| 1985 | ieee80211_scan_completed(hwsim->hw, &info); | 1985 | ieee80211_scan_completed(hwsim->hw, &info); |
| 1986 | hwsim->hw_scan_request = NULL; | 1986 | hwsim->hw_scan_request = NULL; |
| 1987 | hwsim->hw_scan_vif = NULL; | 1987 | hwsim->hw_scan_vif = NULL; |
| @@ -1990,8 +1990,8 @@ static void hw_scan_work(struct work_struct *work) · 2 unmodified lines | |||
| 1990 | return; | 1990 | return; |
| 1991 | } | 1991 | } |
| 1992 | 1992 | ||
| 1993 | wiphy_debug(hwsim->hw->wiphy, "hw scan %d MHz\n", | 1993 | wiphy_dbg(hwsim->hw->wiphy, "hw scan %d MHz\n", |
| 1994 | req->channels[hwsim->scan_chan_idx]->center_freq); | 1994 | req->channels[hwsim->scan_chan_idx]->center_freq); |
| 1995 | 1995 | ||
| 1996 | hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx]; | 1996 | hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx]; |
| 1997 | if (hwsim->tmp_chan->flags & (IEEE80211_CHAN_NO_IR | | 1997 | if (hwsim->tmp_chan->flags & (IEEE80211_CHAN_NO_IR | |
| @@ -2060,7 +2060,7 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, · 62 unmodified lines | |||
| 2060 | memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data)); | 2060 | memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data)); |
| 2061 | mutex_unlock(&hwsim->mutex); | 2061 | mutex_unlock(&hwsim->mutex); |
| 2062 | 2062 | ||
| 2063 | wiphy_debug(hw->wiphy, "hwsim hw_scan request\n"); | 2063 | wiphy_dbg(hw->wiphy, "hwsim hw_scan request\n"); |
| 2064 | 2064 | ||
| 2065 | ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0); | 2065 | ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0); |
| 2066 | 2066 | ||
| @@ -2075,7 +2075,7 @@ static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw, · 8 unmodified lines | |||
| 2075 | .aborted = true, | 2075 | .aborted = true, |
| 2076 | }; | 2076 | }; |
| 2077 | 2077 | ||
| 2078 | wiphy_debug(hw->wiphy, "hwsim cancel_hw_scan\n"); | 2078 | wiphy_dbg(hw->wiphy, "hwsim cancel_hw_scan\n"); |
| 2079 | 2079 | ||
| 2080 | cancel_delayed_work_sync(&hwsim->hw_scan); | 2080 | cancel_delayed_work_sync(&hwsim->hw_scan); |
| 2081 | 2081 | ||
| @@ -2096,11 +2096,11 @@ static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw, · 14 unmodified lines | |||
| 2096 | mutex_lock(&hwsim->mutex); | 2096 | mutex_lock(&hwsim->mutex); |
| 2097 | 2097 | ||
| 2098 | if (hwsim->scanning) { | 2098 | if (hwsim->scanning) { |
| 2099 | printk(KERN_DEBUG "two hwsim sw_scans detected!\n"); | 2099 | pr_debug("two hwsim sw_scans detected!\n"); |
| 2100 | goto out; | 2100 | goto out; |
| 2101 | } | 2101 | } |
| 2102 | 2102 | ||
| 2103 | printk(KERN_DEBUG "hwsim sw_scan request, prepping stuff\n"); | 2103 | pr_debug("hwsim sw_scan request, prepping stuff\n"); |
| 2104 | 2104 | ||
| 2105 | memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN); | 2105 | memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN); |
| 2106 | hwsim->scanning = true; | 2106 | hwsim->scanning = true; |
| @@ -2117,7 +2117,7 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw, · 10 unmodified lines | |||
| 2117 | 2117 | ||
| 2118 | mutex_lock(&hwsim->mutex); | 2118 | mutex_lock(&hwsim->mutex); |
| 2119 | 2119 | ||
| 2120 | printk(KERN_DEBUG "hwsim sw_scan_complete\n"); | 2120 | pr_debug("hwsim sw_scan_complete\n"); |
| 2121 | hwsim->scanning = false; | 2121 | hwsim->scanning = false; |
| 2122 | eth_zero_addr(hwsim->scan_addr); | 2122 | eth_zero_addr(hwsim->scan_addr); |
| 2123 | 2123 | ||
| @@ -2131,7 +2131,7 @@ static void hw_roc_start(struct work_struct *work) · 7 unmodified lines | |||
| 2131 | 2131 | ||
| 2132 | mutex_lock(&hwsim->mutex); | 2132 | mutex_lock(&hwsim->mutex); |
| 2133 | 2133 | ||
| 2134 | wiphy_debug(hwsim->hw->wiphy, "hwsim ROC begins\n"); | 2134 | wiphy_dbg(hwsim->hw->wiphy, "hwsim ROC begins\n"); |
| 2135 | hwsim->tmp_chan = hwsim->roc_chan; | 2135 | hwsim->tmp_chan = hwsim->roc_chan; |
| 2136 | ieee80211_ready_on_channel(hwsim->hw); | 2136 | ieee80211_ready_on_channel(hwsim->hw); |
| 2137 | 2137 | ||
| @@ -2151,7 +2151,7 @@ static void hw_roc_done(struct work_struct *work) · 13 unmodified lines | |||
| 2151 | hwsim->tmp_chan = NULL; | 2151 | hwsim->tmp_chan = NULL; |
| 2152 | mutex_unlock(&hwsim->mutex); | 2152 | mutex_unlock(&hwsim->mutex); |
| 2153 | 2153 | ||
| 2154 | wiphy_debug(hwsim->hw->wiphy, "hwsim ROC expired\n"); | 2154 | wiphy_dbg(hwsim->hw->wiphy, "hwsim ROC expired\n"); |
| 2155 | } | 2155 | } |
| 2156 | 2156 | ||
| 2157 | static int mac80211_hwsim_roc(struct ieee80211_hw *hw, | 2157 | static int mac80211_hwsim_roc(struct ieee80211_hw *hw, |
| @@ -2172,8 +2172,8 @@ static int mac80211_hwsim_roc(struct ieee80211_hw *hw, · 14 unmodified lines | |||
| 2172 | hwsim->roc_duration = duration; | 2172 | hwsim->roc_duration = duration; |
| 2173 | mutex_unlock(&hwsim->mutex); | 2173 | mutex_unlock(&hwsim->mutex); |
| 2174 | 2174 | ||
| 2175 | wiphy_debug(hw->wiphy, "hwsim ROC (%d MHz, %d ms)\n", | 2175 | wiphy_dbg(hw->wiphy, "hwsim ROC (%d MHz, %d ms)\n", |
| 2176 | chan->center_freq, duration); | 2176 | chan->center_freq, duration); |
| 2177 | ieee80211_queue_delayed_work(hw, &hwsim->roc_start, HZ/50); | 2177 | ieee80211_queue_delayed_work(hw, &hwsim->roc_start, HZ/50); |
| 2178 | 2178 | ||
| 2179 | return 0; | 2179 | return 0; |
| @@ -2190,7 +2190,7 @@ static int mac80211_hwsim_croc(struct ieee80211_hw *hw) · 10 unmodified lines | |||
| 2190 | hwsim->tmp_chan = NULL; | 2190 | hwsim->tmp_chan = NULL; |
| 2191 | mutex_unlock(&hwsim->mutex); | 2191 | mutex_unlock(&hwsim->mutex); |
| 2192 | 2192 | ||
| 2193 | wiphy_debug(hw->wiphy, "hwsim ROC canceled\n"); | 2193 | wiphy_dbg(hw->wiphy, "hwsim ROC canceled\n"); |
| 2194 | 2194 | ||
| 2195 | return 0; | 2195 | return 0; |
| 2196 | } | 2196 | } |
| @@ -2199,20 +2199,20 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw, · 2 unmodified lines | |||
| 2199 | struct ieee80211_chanctx_conf *ctx) | 2199 | struct ieee80211_chanctx_conf *ctx) |
| 2200 | { | 2200 | { |
| 2201 | hwsim_set_chanctx_magic(ctx); | 2201 | hwsim_set_chanctx_magic(ctx); |
| 2202 | wiphy_debug(hw->wiphy, | 2202 | wiphy_dbg(hw->wiphy, |
| 2203 | "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", | 2203 | "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", |
| 2204 | ctx->def.chan->center_freq, ctx->def.width, | 2204 | ctx->def.chan->center_freq, ctx->def.width, |
| 2205 | ctx->def.center_freq1, ctx->def.center_freq2); | 2205 | ctx->def.center_freq1, ctx->def.center_freq2); |
| 2206 | return 0; | 2206 | return 0; |
| 2207 | } | 2207 | } |
| 2208 | 2208 | ||
| 2209 | static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw, | 2209 | static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw, |
| 2210 | struct ieee80211_chanctx_conf *ctx) | 2210 | struct ieee80211_chanctx_conf *ctx) |
| 2211 | { | 2211 | { |
| 2212 | wiphy_debug(hw->wiphy, | 2212 | wiphy_dbg(hw->wiphy, |
| 2213 | "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", | 2213 | "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", |
| 2214 | ctx->def.chan->center_freq, ctx->def.width, | 2214 | ctx->def.chan->center_freq, ctx->def.width, |
| 2215 | ctx->def.center_freq1, ctx->def.center_freq2); | 2215 | ctx->def.center_freq1, ctx->def.center_freq2); |
| 2216 | hwsim_check_chanctx_magic(ctx); | 2216 | hwsim_check_chanctx_magic(ctx); |
| 2217 | hwsim_clear_chanctx_magic(ctx); | 2217 | hwsim_clear_chanctx_magic(ctx); |
| 2218 | } | 2218 | } |
| @@ -2222,10 +2222,10 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw, · 3 unmodified lines | |||
| 2222 | u32 changed) | 2222 | u32 changed) |
| 2223 | { | 2223 | { |
| 2224 | hwsim_check_chanctx_magic(ctx); | 2224 | hwsim_check_chanctx_magic(ctx); |
| 2225 | wiphy_debug(hw->wiphy, | 2225 | wiphy_dbg(hw->wiphy, |
| 2226 | "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", | 2226 | "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", |
| 2227 | ctx->def.chan->center_freq, ctx->def.width, | 2227 | ctx->def.chan->center_freq, ctx->def.width, |
| 2228 | ctx->def.center_freq1, ctx->def.center_freq2); | 2228 | ctx->def.center_freq1, ctx->def.center_freq2); |
| 2229 | } | 2229 | } |
| 2230 | 2230 | ||
| 2231 | static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw, | 2231 | static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw, |
| @@ -2479,7 +2479,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, · 247 unmodified lines | |||
| 2479 | ops = &mac80211_hwsim_mchan_ops; | 2479 | ops = &mac80211_hwsim_mchan_ops; |
| 2480 | hw = ieee80211_alloc_hw_nm(sizeof(*data), ops, param->hwname); | 2480 | hw = ieee80211_alloc_hw_nm(sizeof(*data), ops, param->hwname); |
| 2481 | if (!hw) { | 2481 | if (!hw) { |
| 2482 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw failed\n"); | 2482 | pr_debug("mac80211_hwsim: ieee80211_alloc_hw failed\n"); |
| 2483 | err = -ENOMEM; | 2483 | err = -ENOMEM; |
| 2484 | goto failed; | 2484 | goto failed; |
| 2485 | } | 2485 | } |
| @@ -2507,7 +2507,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, · 21 unmodified lines | |||
| 2507 | data->dev->driver = &mac80211_hwsim_driver.driver; | 2507 | data->dev->driver = &mac80211_hwsim_driver.driver; |
| 2508 | err = device_bind_driver(data->dev); | 2508 | err = device_bind_driver(data->dev); |
| 2509 | if (err != 0) { | 2509 | if (err != 0) { |
| 2510 | printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n", | 2510 | pr_debug("mac80211_hwsim: device_bind_driver failed (%d)\n", |
| 2511 | err); | 2511 | err); |
| 2512 | goto failed_bind; | 2512 | goto failed_bind; |
| 2513 | } | 2513 | } |
| @@ -2698,12 +2698,12 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, · 184 unmodified lines | |||
| 2698 | 2698 | ||
| 2699 | err = ieee80211_register_hw(hw); | 2699 | err = ieee80211_register_hw(hw); |
| 2700 | if (err < 0) { | 2700 | if (err < 0) { |
| 2701 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", | 2701 | pr_debug("mac80211_hwsim: ieee80211_register_hw failed (%d)\n", |
| 2702 | err); | 2702 | err); |
| 2703 | goto failed_hw; | 2703 | goto failed_hw; |
| 2704 | } | 2704 | } |
| 2705 | 2705 | ||
| 2706 | wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr); | 2706 | wiphy_dbg(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr); |
| 2707 | 2707 | ||
| 2708 | if (param->reg_alpha2) { | 2708 | if (param->reg_alpha2) { |
| 2709 | data->alpha2[0] = param->reg_alpha2[0]; | 2709 | data->alpha2[0] = param->reg_alpha2[0]; |
| @@ -3067,7 +3067,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, · 357 unmodified lines | |||
| 3067 | 3067 | ||
| 3068 | return 0; | 3068 | return 0; |
| 3069 | err: | 3069 | err: |
| 3070 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); | 3070 | pr_debug("mac80211_hwsim: error occurred in %s\n", __func__); |
| 3071 | out: | 3071 | out: |
| 3072 | dev_kfree_skb(skb); | 3072 | dev_kfree_skb(skb); |
| 3073 | return -EINVAL; | 3073 | return -EINVAL; |
| @@ -3098,7 +3098,7 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2, · 24 unmodified lines | |||
| 3098 | 3098 | ||
| 3099 | hwsim_register_wmediumd(net, info->snd_portid); | 3099 | hwsim_register_wmediumd(net, info->snd_portid); |
| 3100 | 3100 | ||
| 3101 | printk(KERN_DEBUG "mac80211_hwsim: received a REGISTER, " | 3101 | pr_debug("mac80211_hwsim: received a REGISTER, " |
| 3102 | "switching to wmediumd mode with pid %d\n", info->snd_portid); | 3102 | "switching to wmediumd mode with pid %d\n", info->snd_portid); |
| 3103 | 3103 | ||
| 3104 | return 0; | 3104 | return 0; |
| @@ -3387,7 +3387,7 @@ static int __init hwsim_init_netlink(void) · 282 unmodified lines | |||
| 3387 | return 0; | 3387 | return 0; |
| 3388 | 3388 | ||
| 3389 | failure: | 3389 | failure: |
| 3390 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); | 3390 | pr_debug("mac80211_hwsim: error occurred in %s\n", __func__); |
| 3391 | return -EINVAL; | 3391 | return -EINVAL; |
| 3392 | } | 3392 | } |
| 3393 | 3393 | ||
| @@ -3578,7 +3578,7 @@ module_init(init_mac80211_hwsim); · 184 unmodified lines | |||
| 3578 | 3578 | ||
| 3579 | static void __exit exit_mac80211_hwsim(void) | 3579 | static void __exit exit_mac80211_hwsim(void) |
| 3580 | { | 3580 | { |
| 3581 | printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n"); | 3581 | pr_debug("mac80211_hwsim: unregister radios\n"); |
| 3582 | 3582 | ||
| 3583 | hwsim_exit_netlink(); | 3583 | hwsim_exit_netlink(); |
| 3584 | 3584 | ||
| @@ -2445,6 +2445,7 @@ enum ieee80211_sa_query_action { · 2444 unmodified lines | |||
| 2445 | #define WLAN_OUI_TYPE_MICROSOFT_WPA 1 | 2445 | #define WLAN_OUI_TYPE_MICROSOFT_WPA 1 |
| 2446 | #define WLAN_OUI_TYPE_MICROSOFT_WMM 2 | 2446 | #define WLAN_OUI_TYPE_MICROSOFT_WMM 2 |
| 2447 | #define WLAN_OUI_TYPE_MICROSOFT_WPS 4 | 2447 | #define WLAN_OUI_TYPE_MICROSOFT_WPS 4 |
| 2448 | #define WLAN_OUI_TYPE_MICROSOFT_TPC 8 | ||
| 2448 | 2449 | ||
| 2449 | /* | 2450 | /* |
| 2450 | * WMM/802.11e Tspec Element | 2451 | * WMM/802.11e Tspec Element |
| @@ -4346,19 +4346,6 @@ static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, · 4345 unmodified lines | |||
| 4346 | return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype); | 4346 | return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype); |
| 4347 | } | 4347 | } |
| 4348 | 4348 | ||
| 4349 | /** | ||
| 4350 | * ieee80211_data_from_8023 - convert an 802.3 frame to 802.11 | ||
| 4351 | * @skb: the 802.3 frame | ||
| 4352 | * @addr: the device MAC address | ||
| 4353 | * @iftype: the virtual interface type | ||
| 4354 | * @bssid: the network bssid (used only for iftype STATION and ADHOC) | ||
| 4355 | * @qos: build 802.11 QoS data frame | ||
| 4356 | * Return: 0 on success, or a negative error code. | ||
| 4357 | */ | ||
| 4358 | int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, | ||
| 4359 | enum nl80211_iftype iftype, const u8 *bssid, | ||
| 4360 | bool qos); | ||
| 4361 | |||
| 4362 | /** | 4349 | /** |
| 4363 | * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame | 4350 | * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame |
| 4364 | * | 4351 | * |
| @@ -5441,9 +5428,6 @@ cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid, · 1076 unmodified lines | |||
| 5441 | * @req_ie_len: association request IEs length | 5428 | * @req_ie_len: association request IEs length |
| 5442 | * @resp_ie: association response IEs (may be %NULL) | 5429 | * @resp_ie: association response IEs (may be %NULL) |
| 5443 | * @resp_ie_len: assoc response IEs length | 5430 | * @resp_ie_len: assoc response IEs length |
| 5444 | * @authorized: true if the 802.1X authentication was done by the driver or is | ||
| 5445 | * not needed (e.g., when Fast Transition protocol was used), false | ||
| 5446 | * otherwise. Ignored for networks that don't use 802.1X authentication. | ||
| 5447 | */ | 5431 | */ |
| 5448 | struct cfg80211_roam_info { | 5432 | struct cfg80211_roam_info { |
| 5449 | struct ieee80211_channel *channel; | 5433 | struct ieee80211_channel *channel; |
| @@ -5453,7 +5437,6 @@ struct cfg80211_roam_info { · 3 unmodified lines | |||
| 5453 | size_t req_ie_len; | 5437 | size_t req_ie_len; |
| 5454 | const u8 *resp_ie; | 5438 | const u8 *resp_ie; |
| 5455 | size_t resp_ie_len; | 5439 | size_t resp_ie_len; |
| 5456 | bool authorized; | ||
| 5457 | }; | 5440 | }; |
| 5458 | 5441 | ||
| 5459 | /** | 5442 | /** |
| @@ -5477,6 +5460,23 @@ struct cfg80211_roam_info { · 17 unmodified lines | |||
| 5477 | void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info, | 5460 | void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info, |
| 5478 | gfp_t gfp); | 5461 | gfp_t gfp); |
| 5479 | 5462 | ||
| 5463 | /** | ||
| 5464 | * cfg80211_port_authorized - notify cfg80211 of successful security association | ||
| 5465 | * | ||
| 5466 | * @dev: network device | ||
| 5467 | * @bssid: the BSSID of the AP | ||
| 5468 | * @gfp: allocation flags | ||
| 5469 | * | ||
| 5470 | * This function should be called by a driver that supports 4 way handshake | ||
| 5471 | * offload after a security association was successfully established (i.e., | ||
| 5472 | * the 4 way handshake was completed successfully). The call to this function | ||
| 5473 | * should be preceded with a call to cfg80211_connect_result(), | ||
| 5474 | * cfg80211_connect_done(), cfg80211_connect_bss() or cfg80211_roamed() to | ||
| 5475 | * indicate the 802.11 association. | ||
| 5476 | */ | ||
| 5477 | void cfg80211_port_authorized(struct net_device *dev, const u8 *bssid, | ||
| 5478 | gfp_t gfp); | ||
| 5479 | |||
| 5480 | /** | 5480 | /** |
| 5481 | * cfg80211_disconnected - notify cfg80211 that connection was dropped | 5481 | * cfg80211_disconnected - notify cfg80211 that connection was dropped |
| 5482 | * | 5482 | * |
| @@ -5934,7 +5934,8 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, · 451 unmodified lines | |||
| 5934 | * @ies: the IE buffer | 5934 | * @ies: the IE buffer |
| 5935 | * @ielen: the length of the IE buffer | 5935 | * @ielen: the length of the IE buffer |
| 5936 | * @ids: an array with element IDs that are allowed before | 5936 | * @ids: an array with element IDs that are allowed before |
| 5937 | * the split | 5937 | * the split. A WLAN_EID_EXTENSION value means that the next |
| 5938 | * EID in the list is a sub-element of the EXTENSION IE. | ||
| 5938 | * @n_ids: the size of the element ID array | 5939 | * @n_ids: the size of the element ID array |
| 5939 | * @after_ric: array IE types that come after the RIC element | 5940 | * @after_ric: array IE types that come after the RIC element |
| 5940 | * @n_after_ric: size of the @after_ric array | 5941 | * @n_after_ric: size of the @after_ric array |
| @@ -5965,7 +5966,8 @@ size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen, · 24 unmodified lines | |||
| 5965 | * @ies: the IE buffer | 5966 | * @ies: the IE buffer |
| 5966 | * @ielen: the length of the IE buffer | 5967 | * @ielen: the length of the IE buffer |
| 5967 | * @ids: an array with element IDs that are allowed before | 5968 | * @ids: an array with element IDs that are allowed before |
| 5968 | * the split | 5969 | * the split. A WLAN_EID_EXTENSION value means that the next |
| 5970 | * EID in the list is a sub-element of the EXTENSION IE. | ||
| 5969 | * @n_ids: the size of the element ID array | 5971 | * @n_ids: the size of the element ID array |
| 5970 | * @offset: offset where to start splitting in the buffer | 5972 | * @offset: offset where to start splitting in the buffer |
| 5971 | * | 5973 | * |
| @@ -90,6 +90,13 @@ typedef void fq_skb_free_t(struct fq *, · 89 unmodified lines | |||
| 90 | struct fq_flow *, | 90 | struct fq_flow *, |
| 91 | struct sk_buff *); | 91 | struct sk_buff *); |
| 92 | 92 | ||
| 93 | /* Return %true to filter (drop) the frame. */ | ||
| 94 | typedef bool fq_skb_filter_t(struct fq *, | ||
| 95 | struct fq_tin *, | ||
| 96 | struct fq_flow *, | ||
| 97 | struct sk_buff *, | ||
| 98 | void *); | ||
| 99 | |||
| 93 | typedef struct fq_flow *fq_flow_get_default_t(struct fq *, | 100 | typedef struct fq_flow *fq_flow_get_default_t(struct fq *, |
| 94 | struct fq_tin *, | 101 | struct fq_tin *, |
| 95 | int idx, | 102 | int idx, |
| @@ -12,24 +12,22 @@ · 11 unmodified lines | |||
| 12 | 12 | ||
| 13 | /* functions that are embedded into includer */ | 13 | /* functions that are embedded into includer */ |
| 14 | 14 | ||
| 15 | static struct sk_buff *fq_flow_dequeue(struct fq *fq, | 15 | static void fq_adjust_removal(struct fq *fq, |
| 16 | struct fq_flow *flow) | 16 | struct fq_flow *flow, |
| 17 | struct sk_buff *skb) | ||
| 17 | { | 18 | { |
| 18 | struct fq_tin *tin = flow->tin; | 19 | struct fq_tin *tin = flow->tin; |
| 19 | struct fq_flow *i; | ||
| 20 | struct sk_buff *skb; | ||
| 21 | |||
| 22 | lockdep_assert_held(&fq->lock); | ||
| 23 | |||
| 24 | skb = __skb_dequeue(&flow->queue); | ||
| 25 | if (!skb) | ||
| 26 | return NULL; | ||
| 27 | 20 | ||
| 28 | tin->backlog_bytes -= skb->len; | 21 | tin->backlog_bytes -= skb->len; |
| 29 | tin->backlog_packets--; | 22 | tin->backlog_packets--; |
| 30 | flow->backlog -= skb->len; | 23 | flow->backlog -= skb->len; |
| 31 | fq->backlog--; | 24 | fq->backlog--; |
| 32 | fq->memory_usage -= skb->truesize; | 25 | fq->memory_usage -= skb->truesize; |
| 26 | } | ||
| 27 | |||
| 28 | static void fq_rejigger_backlog(struct fq *fq, struct fq_flow *flow) | ||
| 29 | { | ||
| 30 | struct fq_flow *i; | ||
| 33 | 31 | ||
| 34 | if (flow->backlog == 0) { | 32 | if (flow->backlog == 0) { |
| 35 | list_del_init(&flow->backlogchain); | 33 | list_del_init(&flow->backlogchain); |
| @@ -43,6 +41,21 @@ static struct sk_buff *fq_flow_dequeue(struct fq *fq, · 7 unmodified lines | |||
| 43 | list_move_tail(&flow->backlogchain, | 41 | list_move_tail(&flow->backlogchain, |
| 44 | &i->backlogchain); | 42 | &i->backlogchain); |
| 45 | } | 43 | } |
| 44 | } | ||
| 45 | |||
| 46 | static struct sk_buff *fq_flow_dequeue(struct fq *fq, | ||
| 47 | struct fq_flow *flow) | ||
| 48 | { | ||
| 49 | struct sk_buff *skb; | ||
| 50 | |||
| 51 | lockdep_assert_held(&fq->lock); | ||
| 52 | |||
| 53 | skb = __skb_dequeue(&flow->queue); | ||
| 54 | if (!skb) | ||
| 55 | return NULL; | ||
| 56 | |||
| 57 | fq_adjust_removal(fq, flow, skb); | ||
| 58 | fq_rejigger_backlog(fq, flow); | ||
| 46 | 59 | ||
| 47 | return skb; | 60 | return skb; |
| 48 | } | 61 | } |
| @@ -188,6 +201,45 @@ static void fq_tin_enqueue(struct fq *fq, · 139 unmodified lines | |||
| 188 | } | 201 | } |
| 189 | } | 202 | } |
| 190 | 203 | ||
| 204 | static void fq_flow_filter(struct fq *fq, | ||
| 205 | struct fq_flow *flow, | ||
| 206 | fq_skb_filter_t filter_func, | ||
| 207 | void *filter_data, | ||
| 208 | fq_skb_free_t free_func) | ||
| 209 | { | ||
| 210 | struct fq_tin *tin = flow->tin; | ||
| 211 | struct sk_buff *skb, *tmp; | ||
| 212 | |||
| 213 | lockdep_assert_held(&fq->lock); | ||
| 214 | |||
| 215 | skb_queue_walk_safe(&flow->queue, skb, tmp) { | ||
| 216 | if (!filter_func(fq, tin, flow, skb, filter_data)) | ||
| 217 | continue; | ||
| 218 | |||
| 219 | __skb_unlink(skb, &flow->queue); | ||
| 220 | fq_adjust_removal(fq, flow, skb); | ||
| 221 | free_func(fq, tin, flow, skb); | ||
| 222 | } | ||
| 223 | |||
| 224 | fq_rejigger_backlog(fq, flow); | ||
| 225 | } | ||
| 226 | |||
| 227 | static void fq_tin_filter(struct fq *fq, | ||
| 228 | struct fq_tin *tin, | ||
| 229 | fq_skb_filter_t filter_func, | ||
| 230 | void *filter_data, | ||
| 231 | fq_skb_free_t free_func) | ||
| 232 | { | ||
| 233 | struct fq_flow *flow; | ||
| 234 | |||
| 235 | lockdep_assert_held(&fq->lock); | ||
| 236 | |||
| 237 | list_for_each_entry(flow, &tin->new_flows, flowchain) | ||
| 238 | fq_flow_filter(fq, flow, filter_func, filter_data, free_func); | ||
| 239 | list_for_each_entry(flow, &tin->old_flows, flowchain) | ||
| 240 | fq_flow_filter(fq, flow, filter_func, filter_data, free_func); | ||
| 241 | } | ||
| 242 | |||
| 191 | static void fq_flow_reset(struct fq *fq, | 243 | static void fq_flow_reset(struct fq *fq, |
| 192 | struct fq_flow *flow, | 244 | struct fq_flow *flow, |
| 193 | fq_skb_free_t free_func) | 245 | fq_skb_free_t free_func) |
| @@ -5441,8 +5441,14 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid, · 5440 unmodified lines | |||
| 5441 | */ | 5441 | */ |
| 5442 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn); | 5442 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn); |
| 5443 | 5443 | ||
| 5444 | /** | ||
| 5445 | * ieee80211_manage_rx_ba_offl - helper to queue an RX BA work | ||
| 5446 | * @vif: &struct ieee80211_vif pointer from the add_interface callback | ||
| 5447 | * @addr: station mac address | ||
| 5448 | * @tid: the rx tid | ||
| 5449 | */ | ||
| 5444 | void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, const u8 *addr, | 5450 | void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, const u8 *addr, |
| 5445 | unsigned int bit); | 5451 | unsigned int tid); |
| 5446 | 5452 | ||
| 5447 | /** | 5453 | /** |
| 5448 | * ieee80211_start_rx_ba_session_offl - start a Rx BA session | 5454 | * ieee80211_start_rx_ba_session_offl - start a Rx BA session |
| @@ -569,13 +569,14 @@ · 568 unmodified lines | |||
| 569 | * authentication/association or not receiving a response from the AP. | 569 | * authentication/association or not receiving a response from the AP. |
| 570 | * Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as | 570 | * Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as |
| 571 | * well to remain backwards compatible. | 571 | * well to remain backwards compatible. |
| 572 | * @NL80211_CMD_ROAM: notifcation indicating the card/driver roamed by itself. | 572 | * When establishing a security association, drivers that support 4 way |
| 573 | * When the driver roamed in a network that requires 802.1X authentication, | 573 | * handshake offload should send %NL80211_CMD_PORT_AUTHORIZED event when |
| 574 | * %NL80211_ATTR_PORT_AUTHORIZED should be set if the 802.1X authentication | 574 | * the 4 way handshake is completed successfully. |
| 575 | * was done by the driver or if roaming was done using Fast Transition | 575 | * @NL80211_CMD_ROAM: Notification indicating the card/driver roamed by itself. |
| 576 | * protocol (in which case 802.1X authentication is not needed). If | 576 | * When a security association was established with the new AP (e.g. if |
| 577 | * %NL80211_ATTR_PORT_AUTHORIZED is not set, user space is responsible for | 577 | * the FT protocol was used for roaming or the driver completed the 4 way |
| 578 | * the 802.1X authentication. | 578 | * handshake), this event should be followed by an |
| 579 | * %NL80211_CMD_PORT_AUTHORIZED event. | ||
| 579 | * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify | 580 | * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify |
| 580 | * userspace that a connection was dropped by the AP or due to other | 581 | * userspace that a connection was dropped by the AP or due to other |
| 581 | * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and | 582 | * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and |
| @@ -982,6 +983,14 @@ · 400 unmodified lines | |||
| 982 | * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously | 983 | * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously |
| 983 | * configured PMK for the authenticator address identified by | 984 | * configured PMK for the authenticator address identified by |
| 984 | * &NL80211_ATTR_MAC. | 985 | * &NL80211_ATTR_MAC. |
| 986 | * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates that the 4 way | ||
| 987 | * handshake was completed successfully by the driver. The BSSID is | ||
| 988 | * specified with &NL80211_ATTR_MAC. Drivers that support 4 way handshake | ||
| 989 | * offload should send this event after indicating 802.11 association with | ||
| 990 | * &NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed | ||
| 991 | * &NL80211_CMD_DISCONNECT should be indicated instead. | ||
| 992 | * | ||
| 993 | * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded. | ||
| 985 | * | 994 | * |
| 986 | * @NL80211_CMD_MAX: highest used command number | 995 | * @NL80211_CMD_MAX: highest used command number |
| 987 | * @__NL80211_CMD_AFTER_LAST: internal use | 996 | * @__NL80211_CMD_AFTER_LAST: internal use |
| @@ -1185,6 +1194,10 @@ enum nl80211_commands { · 197 unmodified lines | |||
| 1185 | NL80211_CMD_SET_PMK, | 1194 | NL80211_CMD_SET_PMK, |
| 1186 | NL80211_CMD_DEL_PMK, | 1195 | NL80211_CMD_DEL_PMK, |
| 1187 | 1196 | ||
| 1197 | NL80211_CMD_PORT_AUTHORIZED, | ||
| 1198 | |||
| 1199 | NL80211_CMD_RELOAD_REGDB, | ||
| 1200 | |||
| 1188 | /* add new commands above here */ | 1201 | /* add new commands above here */ |
| 1189 | 1202 | ||
| 1190 | /* used to define NL80211_CMD_MAX below */ | 1203 | /* used to define NL80211_CMD_MAX below */ |
| @@ -1407,8 +1420,12 @@ enum nl80211_commands { · 216 unmodified lines | |||
| 1407 | * | 1420 | * |
| 1408 | * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is | 1421 | * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is |
| 1409 | * used for the association (&enum nl80211_mfp, represented as a u32); | 1422 | * used for the association (&enum nl80211_mfp, represented as a u32); |
| 1410 | * this attribute can be used | 1423 | * this attribute can be used with %NL80211_CMD_ASSOCIATE and |
| 1411 | * with %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests | 1424 | * %NL80211_CMD_CONNECT requests. %NL80211_MFP_OPTIONAL is not allowed for |
| 1425 | * %NL80211_CMD_ASSOCIATE since user space SME is expected and hence, it | ||
| 1426 | * must have decided whether to use management frame protection or not. | ||
| 1427 | * Setting %NL80211_MFP_OPTIONAL with a %NL80211_CMD_CONNECT request will | ||
| 1428 | * let the driver (or the firmware) decide whether to use MFP or not. | ||
| 1412 | * | 1429 | * |
| 1413 | * @NL80211_ATTR_STA_FLAGS2: Attribute containing a | 1430 | * @NL80211_ATTR_STA_FLAGS2: Attribute containing a |
| 1414 | * &struct nl80211_sta_flag_update. | 1431 | * &struct nl80211_sta_flag_update. |
| @@ -2134,10 +2151,7 @@ enum nl80211_commands { · 719 unmodified lines | |||
| 2134 | * in %NL80211_CMD_CONNECT to indicate that for 802.1X authentication it | 2151 | * in %NL80211_CMD_CONNECT to indicate that for 802.1X authentication it |
| 2135 | * wants to use the supported offload of the 4-way handshake. | 2152 | * wants to use the supported offload of the 4-way handshake. |
| 2136 | * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT. | 2153 | * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT. |
| 2137 | * @NL80211_ATTR_PORT_AUTHORIZED: flag attribute used in %NL80211_CMD_ROAMED | 2154 | * @NL80211_ATTR_PORT_AUTHORIZED: (reserved) |
| 2138 | * notification indicating that that 802.1X authentication was done by | ||
| 2139 | * the driver or is not needed (because roaming used the Fast Transition | ||
| 2140 | * protocol). | ||
| 2141 | * | 2155 | * |
| 2142 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available | 2156 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available |
| 2143 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 2157 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
| @@ -3947,10 +3961,12 @@ enum nl80211_key_type { · 1803 unmodified lines | |||
| 3947 | * enum nl80211_mfp - Management frame protection state | 3961 | * enum nl80211_mfp - Management frame protection state |
| 3948 | * @NL80211_MFP_NO: Management frame protection not used | 3962 | * @NL80211_MFP_NO: Management frame protection not used |
| 3949 | * @NL80211_MFP_REQUIRED: Management frame protection required | 3963 | * @NL80211_MFP_REQUIRED: Management frame protection required |
| 3964 | * @NL80211_MFP_OPTIONAL: Management frame protection is optional | ||
| 3950 | */ | 3965 | */ |
| 3951 | enum nl80211_mfp { | 3966 | enum nl80211_mfp { |
| 3952 | NL80211_MFP_NO, | 3967 | NL80211_MFP_NO, |
| 3953 | NL80211_MFP_REQUIRED, | 3968 | NL80211_MFP_REQUIRED, |
| 3969 | NL80211_MFP_OPTIONAL, | ||
| 3954 | }; | 3970 | }; |
| 3955 | 3971 | ||
| 3956 | enum nl80211_wpa_versions { | 3972 | enum nl80211_wpa_versions { |
| @@ -4914,6 +4930,17 @@ enum nl80211_feature_flags { · 957 unmodified lines | |||
| 4914 | * handshake with 802.1X in station mode (will pass EAP frames to the host | 4930 | * handshake with 802.1X in station mode (will pass EAP frames to the host |
| 4915 | * and accept the set_pmk/del_pmk commands), doing it in the host might not | 4931 | * and accept the set_pmk/del_pmk commands), doing it in the host might not |
| 4916 | * be supported. | 4932 | * be supported. |
| 4933 | * @NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME: Driver is capable of overriding | ||
| 4934 | * the max channel attribute in the FILS request params IE with the | ||
| 4935 | * actual dwell time. | ||
| 4936 | * @NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP: Driver accepts broadcast probe | ||
| 4937 | * response | ||
| 4938 | * @NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE: Driver supports sending | ||
| 4939 | * the first probe request in each channel at rate of at least 5.5Mbps. | ||
| 4940 | * @NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION: Driver supports | ||
| 4941 | * probe request tx deferral and suppression | ||
| 4942 | * @NL80211_EXT_FEATURE_MFP_OPTIONAL: Driver supports the %NL80211_MFP_OPTIONAL | ||
| 4943 | * value in %NL80211_ATTR_USE_MFP. | ||
| 4917 | * | 4944 | * |
| 4918 | * @NUM_NL80211_EXT_FEATURES: number of extended features. | 4945 | * @NUM_NL80211_EXT_FEATURES: number of extended features. |
| 4919 | * @MAX_NL80211_EXT_FEATURES: highest extended feature index. | 4946 | * @MAX_NL80211_EXT_FEATURES: highest extended feature index. |
| @@ -4936,6 +4963,11 @@ enum nl80211_ext_feature_index { · 16 unmodified lines | |||
| 4936 | NL80211_EXT_FEATURE_FILS_SK_OFFLOAD, | 4963 | NL80211_EXT_FEATURE_FILS_SK_OFFLOAD, |
| 4937 | NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK, | 4964 | NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK, |
| 4938 | NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X, | 4965 | NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X, |
| 4966 | NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME, | ||
| 4967 | NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP, | ||
| 4968 | NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE, | ||
| 4969 | NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION, | ||
| 4970 | NL80211_EXT_FEATURE_MFP_OPTIONAL, | ||
| 4939 | 4971 | ||
| 4940 | /* add new features before the definition below */ | 4972 | /* add new features before the definition below */ |
| 4941 | NUM_NL80211_EXT_FEATURES, | 4973 | NUM_NL80211_EXT_FEATURES, |
| @@ -5012,12 +5044,28 @@ enum nl80211_timeout_reason { · 70 unmodified lines | |||
| 5012 | * locally administered 1, multicast 0) is assumed. | 5044 | * locally administered 1, multicast 0) is assumed. |
| 5013 | * This flag must not be requested when the feature isn't supported, check | 5045 | * This flag must not be requested when the feature isn't supported, check |
| 5014 | * the nl80211 feature flags for the device. | 5046 | * the nl80211 feature flags for the device. |
| 5047 | * @NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME: fill the dwell time in the FILS | ||
| 5048 | * request parameters IE in the probe request | ||
| 5049 | * @NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP: accept broadcast probe responses | ||
| 5050 | * @NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE: send probe request frames at | ||
| 5051 | * rate of at least 5.5M. In case non OCE AP is dicovered in the channel, | ||
| 5052 | * only the first probe req in the channel will be sent in high rate. | ||
| 5053 | * @NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION: allow probe request | ||
| 5054 | * tx deferral (dot11FILSProbeDelay shall be set to 15ms) | ||
| 5055 | * and suppression (if it has received a broadcast Probe Response frame, | ||
| 5056 | * Beacon frame or FILS Discovery frame from an AP that the STA considers | ||
| 5057 | * a suitable candidate for (re-)association - suitable in terms of | ||
| 5058 | * SSID and/or RSSI | ||
| 5015 | */ | 5059 | */ |
| 5016 | enum nl80211_scan_flags { | 5060 | enum nl80211_scan_flags { |
| 5017 | NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, | 5061 | NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, |
| 5018 | NL80211_SCAN_FLAG_FLUSH = 1<<1, | 5062 | NL80211_SCAN_FLAG_FLUSH = 1<<1, |
| 5019 | NL80211_SCAN_FLAG_AP = 1<<2, | 5063 | NL80211_SCAN_FLAG_AP = 1<<2, |
| 5020 | NL80211_SCAN_FLAG_RANDOM_ADDR = 1<<3, | 5064 | NL80211_SCAN_FLAG_RANDOM_ADDR = 1<<3, |
| 5065 | NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME = 1<<4, | ||
| 5066 | NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP = 1<<5, | ||
| 5067 | NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE = 1<<6, | ||
| 5068 | NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 1<<7, | ||
| 5021 | }; | 5069 | }; |
| 5022 | 5070 | ||
| 5023 | /** | 5071 | /** |
| @@ -6,6 +6,7 @@ mac80211-y := \ · 5 unmodified lines | |||
| 6 | driver-ops.o \ | 6 | driver-ops.o \ |
| 7 | sta_info.o \ | 7 | sta_info.o \ |
| 8 | wep.o \ | 8 | wep.o \ |
| 9 | aead_api.o \ | ||
| 9 | wpa.o \ | 10 | wpa.o \ |
| 10 | scan.o offchannel.o \ | 11 | scan.o offchannel.o \ |
| 11 | ht.o agg-tx.o agg-rx.o \ | 12 | ht.o agg-tx.o agg-rx.o \ |
| @@ -15,8 +16,6 @@ mac80211-y := \ · 3 unmodified lines | |||
| 15 | rate.o \ | 16 | rate.o \ |
| 16 | michael.o \ | 17 | michael.o \ |
| 17 | tkip.o \ | 18 | tkip.o \ |
| 18 | aes_ccm.o \ | ||
| 19 | aes_gcm.o \ | ||
| 20 | aes_cmac.o \ | 19 | aes_cmac.o \ |
| 21 | aes_gmac.o \ | 20 | aes_gmac.o \ |
| 22 | fils_aead.o \ | 21 | fils_aead.o \ |
| @@ -1,6 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright 2003-2004, Instant802 Networks, Inc. | 2 | * Copyright 2003-2004, Instant802 Networks, Inc. |
| 3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
| 4 | * Copyright 2014-2015, Qualcomm Atheros, Inc. | ||
| 4 | * | 5 | * |
| 5 | * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org> | 6 | * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org> |
| 6 | * | 7 | * |
| @@ -12,30 +13,29 @@ · 5 unmodified lines | |||
| 12 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 13 | #include <linux/types.h> | 14 | #include <linux/types.h> |
| 14 | #include <linux/err.h> | 15 | #include <linux/err.h> |
| 16 | #include <linux/scatterlist.h> | ||
| 15 | #include <crypto/aead.h> | 17 | #include <crypto/aead.h> |
| 16 | 18 | ||
| 17 | #include <net/mac80211.h> | 19 | #include "aead_api.h" |
| 18 | #include "key.h" | ||
| 19 | #include "aes_ccm.h" | ||
| 20 | 20 | ||
| 21 | int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | 21 | int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len, |
| 22 | u8 *data, size_t data_len, u8 *mic, | 22 | u8 *data, size_t data_len, u8 *mic) |
| 23 | size_t mic_len) | ||
| 24 | { | 23 | { |
| 24 | size_t mic_len = tfm->authsize; | ||
| 25 | struct scatterlist sg[3]; | 25 | struct scatterlist sg[3]; |
| 26 | struct aead_request *aead_req; | 26 | struct aead_request *aead_req; |
| 27 | int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); | 27 | int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); |
| 28 | u8 *__aad; | 28 | u8 *__aad; |
| 29 | 29 | ||
| 30 | aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC); | 30 | aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC); |
| 31 | if (!aead_req) | 31 | if (!aead_req) |
| 32 | return -ENOMEM; | 32 | return -ENOMEM; |
| 33 | 33 | ||
| 34 | __aad = (u8 *)aead_req + reqsize; | 34 | __aad = (u8 *)aead_req + reqsize; |
| 35 | memcpy(__aad, aad, CCM_AAD_LEN); | 35 | memcpy(__aad, aad, aad_len); |
| 36 | 36 | ||
| 37 | sg_init_table(sg, 3); | 37 | sg_init_table(sg, 3); |
| 38 | sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); | 38 | sg_set_buf(&sg[0], __aad, aad_len); |
| 39 | sg_set_buf(&sg[1], data, data_len); | 39 | sg_set_buf(&sg[1], data, data_len); |
| 40 | sg_set_buf(&sg[2], mic, mic_len); | 40 | sg_set_buf(&sg[2], mic, mic_len); |
| 41 | 41 | ||
| @@ -49,10 +49,10 @@ int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, · 7 unmodified lines | |||
| 49 | return 0; | 49 | return 0; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | 52 | int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len, |
| 53 | u8 *data, size_t data_len, u8 *mic, | 53 | u8 *data, size_t data_len, u8 *mic) |
| 54 | size_t mic_len) | ||
| 55 | { | 54 | { |
| 55 | size_t mic_len = tfm->authsize; | ||
| 56 | struct scatterlist sg[3]; | 56 | struct scatterlist sg[3]; |
| 57 | struct aead_request *aead_req; | 57 | struct aead_request *aead_req; |
| 58 | int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); | 58 | int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); |
| @@ -62,15 +62,15 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, · 3 unmodified lines | |||
| 62 | if (data_len == 0) | 62 | if (data_len == 0) |
| 63 | return -EINVAL; | 63 | return -EINVAL; |
| 64 | 64 | ||
| 65 | aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC); | 65 | aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC); |
| 66 | if (!aead_req) | 66 | if (!aead_req) |
| 67 | return -ENOMEM; | 67 | return -ENOMEM; |
| 68 | 68 | ||
| 69 | __aad = (u8 *)aead_req + reqsize; | 69 | __aad = (u8 *)aead_req + reqsize; |
| 70 | memcpy(__aad, aad, CCM_AAD_LEN); | 70 | memcpy(__aad, aad, aad_len); |
| 71 | 71 | ||
| 72 | sg_init_table(sg, 3); | 72 | sg_init_table(sg, 3); |
| 73 | sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); | 73 | sg_set_buf(&sg[0], __aad, aad_len); |
| 74 | sg_set_buf(&sg[1], data, data_len); | 74 | sg_set_buf(&sg[1], data, data_len); |
| 75 | sg_set_buf(&sg[2], mic, mic_len); | 75 | sg_set_buf(&sg[2], mic, mic_len); |
| 76 | 76 | ||
| @@ -84,14 +84,14 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, · 7 unmodified lines | |||
| 84 | return err; | 84 | return err; |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], | 87 | struct crypto_aead * |
| 88 | size_t key_len, | 88 | aead_key_setup_encrypt(const char *alg, const u8 key[], |
| 89 | size_t mic_len) | 89 | size_t key_len, size_t mic_len) |
| 90 | { | 90 | { |
| 91 | struct crypto_aead *tfm; | 91 | struct crypto_aead *tfm; |
| 92 | int err; | 92 | int err; |
| 93 | 93 | ||
| 94 | tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC); | 94 | tfm = crypto_alloc_aead(alg, 0, CRYPTO_ALG_ASYNC); |
| 95 | if (IS_ERR(tfm)) | 95 | if (IS_ERR(tfm)) |
| 96 | return tfm; | 96 | return tfm; |
| 97 | 97 | ||
| @@ -109,7 +109,7 @@ free_aead: · 11 unmodified lines | |||
| 109 | return ERR_PTR(err); | 109 | return ERR_PTR(err); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | void ieee80211_aes_key_free(struct crypto_aead *tfm) | 112 | void aead_key_free(struct crypto_aead *tfm) |
| 113 | { | 113 | { |
| 114 | crypto_free_aead(tfm); | 114 | crypto_free_aead(tfm); |
| 115 | } | 115 | } |
| @@ -0,0 +1,27 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License version 2 as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef _AEAD_API_H | ||
| 8 | #define _AEAD_API_H | ||
| 9 | |||
| 10 | #include <crypto/aead.h> | ||
| 11 | #include <linux/crypto.h> | ||
| 12 | |||
| 13 | struct crypto_aead * | ||
| 14 | aead_key_setup_encrypt(const char *alg, const u8 key[], | ||
| 15 | size_t key_len, size_t mic_len); | ||
| 16 | |||
| 17 | int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | ||
| 18 | size_t aad_len, u8 *data, | ||
| 19 | size_t data_len, u8 *mic); | ||
| 20 | |||
| 21 | int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | ||
| 22 | size_t aad_len, u8 *data, | ||
| 23 | size_t data_len, u8 *mic); | ||
| 24 | |||
| 25 | void aead_key_free(struct crypto_aead *tfm); | ||
| 26 | |||
| 27 | #endif /* _AEAD_API_H */ | ||
| @@ -10,19 +10,39 @@ · 9 unmodified lines | |||
| 10 | #ifndef AES_CCM_H | 10 | #ifndef AES_CCM_H |
| 11 | #define AES_CCM_H | 11 | #define AES_CCM_H |
| 12 | 12 | ||
| 13 | #include <linux/crypto.h> | 13 | #include "aead_api.h" |
| 14 | 14 | ||
| 15 | #define CCM_AAD_LEN 32 | 15 | #define CCM_AAD_LEN 32 |
| 16 | 16 | ||
| 17 | struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], | 17 | static inline struct crypto_aead * |
| 18 | size_t key_len, | 18 | ieee80211_aes_key_setup_encrypt(const u8 key[], size_t key_len, size_t mic_len) |
| 19 | size_t mic_len); | 19 | { |
| 20 | int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | 20 | return aead_key_setup_encrypt("ccm(aes)", key, key_len, mic_len); |
| 21 | u8 *data, size_t data_len, u8 *mic, | 21 | } |
| 22 | size_t mic_len); | 22 | |
| 23 | int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | 23 | static inline int |
| 24 | u8 *data, size_t data_len, u8 *mic, | 24 | ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, |
| 25 | size_t mic_len); | 25 | u8 *b_0, u8 *aad, u8 *data, |
| 26 | void ieee80211_aes_key_free(struct crypto_aead *tfm); | 26 | size_t data_len, u8 *mic) |
| 27 | { | ||
| 28 | return aead_encrypt(tfm, b_0, aad + 2, | ||
| 29 | be16_to_cpup((__be16 *)aad), | ||
| 30 | data, data_len, mic); | ||
| 31 | } | ||
| 32 | |||
| 33 | static inline int | ||
| 34 | ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, | ||
| 35 | u8 *b_0, u8 *aad, u8 *data, | ||
| 36 | size_t data_len, u8 *mic) | ||
| 37 | { | ||
| 38 | return aead_decrypt(tfm, b_0, aad + 2, | ||
| 39 | be16_to_cpup((__be16 *)aad), | ||
| 40 | data, data_len, mic); | ||
| 41 | } | ||
| 42 | |||
| 43 | static inline void ieee80211_aes_key_free(struct crypto_aead *tfm) | ||
| 44 | { | ||
| 45 | return aead_key_free(tfm); | ||
| 46 | } | ||
| 27 | 47 | ||
| 28 | #endif /* AES_CCM_H */ | 48 | #endif /* AES_CCM_H */ |
| @@ -1,109 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2014-2015, Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/types.h> | ||
| 11 | #include <linux/err.h> | ||
| 12 | #include <crypto/aead.h> | ||
| 13 | |||
| 14 | #include <net/mac80211.h> | ||
| 15 | #include "key.h" | ||
| 16 | #include "aes_gcm.h" | ||
| 17 | |||
| 18 | int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, | ||
| 19 | u8 *data, size_t data_len, u8 *mic) | ||
| 20 | { | ||
| 21 | struct scatterlist sg[3]; | ||
| 22 | struct aead_request *aead_req; | ||
| 23 | int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); | ||
| 24 | u8 *__aad; | ||
| 25 | |||
| 26 | aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC); | ||
| 27 | if (!aead_req) | ||
| 28 | return -ENOMEM; | ||
| 29 | |||
| 30 | __aad = (u8 *)aead_req + reqsize; | ||
| 31 | memcpy(__aad, aad, GCM_AAD_LEN); | ||
| 32 | |||
| 33 | sg_init_table(sg, 3); | ||
| 34 | sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); | ||
| 35 | sg_set_buf(&sg[1], data, data_len); | ||
| 36 | sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN); | ||
| 37 | |||
| 38 | aead_request_set_tfm(aead_req, tfm); | ||
| 39 | aead_request_set_crypt(aead_req, sg, sg, data_len, j_0); | ||
| 40 | aead_request_set_ad(aead_req, sg[0].length); | ||
| 41 | |||
| 42 | crypto_aead_encrypt(aead_req); | ||
| 43 | kzfree(aead_req); | ||
| 44 | return 0; | ||
| 45 | } | ||
| 46 | |||
| 47 | int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, | ||
| 48 | u8 *data, size_t data_len, u8 *mic) | ||
| 49 | { | ||
| 50 | struct scatterlist sg[3]; | ||
| 51 | struct aead_request *aead_req; | ||
| 52 | int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); | ||
| 53 | u8 *__aad; | ||
| 54 | int err; | ||
| 55 | |||
| 56 | if (data_len == 0) | ||
| 57 | return -EINVAL; | ||
| 58 | |||
| 59 | aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC); | ||
| 60 | if (!aead_req) | ||
| 61 | return -ENOMEM; | ||
| 62 | |||
| 63 | __aad = (u8 *)aead_req + reqsize; | ||
| 64 | memcpy(__aad, aad, GCM_AAD_LEN); | ||
| 65 | |||
| 66 | sg_init_table(sg, 3); | ||
| 67 | sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); | ||
| 68 | sg_set_buf(&sg[1], data, data_len); | ||
| 69 | sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN); | ||
| 70 | |||
| 71 | aead_request_set_tfm(aead_req, tfm); | ||
| 72 | aead_request_set_crypt(aead_req, sg, sg, | ||
| 73 | data_len + IEEE80211_GCMP_MIC_LEN, j_0); | ||
| 74 | aead_request_set_ad(aead_req, sg[0].length); | ||
| 75 | |||
| 76 | err = crypto_aead_decrypt(aead_req); | ||
| 77 | kzfree(aead_req); | ||
| 78 | |||
| 79 | return err; | ||
| 80 | } | ||
| 81 | |||
| 82 | struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], | ||
| 83 | size_t key_len) | ||
| 84 | { | ||
| 85 | struct crypto_aead *tfm; | ||
| 86 | int err; | ||
| 87 | |||
| 88 | tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); | ||
| 89 | if (IS_ERR(tfm)) | ||
| 90 | return tfm; | ||
| 91 | |||
| 92 | err = crypto_aead_setkey(tfm, key, key_len); | ||
| 93 | if (err) | ||
| 94 | goto free_aead; | ||
| 95 | err = crypto_aead_setauthsize(tfm, IEEE80211_GCMP_MIC_LEN); | ||
| 96 | if (err) | ||
| 97 | goto free_aead; | ||
| 98 | |||
| 99 | return tfm; | ||
| 100 | |||
| 101 | free_aead: | ||
| 102 | crypto_free_aead(tfm); | ||
| 103 | return ERR_PTR(err); | ||
| 104 | } | ||
| 105 | |||
| 106 | void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) | ||
| 107 | { | ||
| 108 | crypto_free_aead(tfm); | ||
| 109 | } | ||
| @@ -9,16 +9,38 @@ · 8 unmodified lines | |||
| 9 | #ifndef AES_GCM_H | 9 | #ifndef AES_GCM_H |
| 10 | #define AES_GCM_H | 10 | #define AES_GCM_H |
| 11 | 11 | ||
| 12 | #include <linux/crypto.h> | 12 | #include "aead_api.h" |
| 13 | 13 | ||
| 14 | #define GCM_AAD_LEN 32 | 14 | #define GCM_AAD_LEN 32 |
| 15 | 15 | ||
| 16 | int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, | 16 | static inline int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, |
| 17 | u8 *data, size_t data_len, u8 *mic); | 17 | u8 *j_0, u8 *aad, u8 *data, |
| 18 | int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, | 18 | size_t data_len, u8 *mic) |
| 19 | u8 *data, size_t data_len, u8 *mic); | 19 | { |
| 20 | struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], | 20 | return aead_encrypt(tfm, j_0, aad + 2, |
| 21 | size_t key_len); | 21 | be16_to_cpup((__be16 *)aad), |
| 22 | void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm); | 22 | data, data_len, mic); |
| 23 | } | ||
| 24 | |||
| 25 | static inline int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, | ||
| 26 | u8 *j_0, u8 *aad, u8 *data, | ||
| 27 | size_t data_len, u8 *mic) | ||
| 28 | { | ||
| 29 | return aead_decrypt(tfm, j_0, aad + 2, | ||
| 30 | be16_to_cpup((__be16 *)aad), | ||
| 31 | data, data_len, mic); | ||
| 32 | } | ||
| 33 | |||
| 34 | static inline struct crypto_aead * | ||
| 35 | ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len) | ||
| 36 | { | ||
| 37 | return aead_key_setup_encrypt("gcm(aes)", key, | ||
| 38 | key_len, IEEE80211_GCMP_MIC_LEN); | ||
| 39 | } | ||
| 40 | |||
| 41 | static inline void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) | ||
| 42 | { | ||
| 43 | return aead_key_free(tfm); | ||
| 44 | } | ||
| 23 | 45 | ||
| 24 | #endif /* AES_GCM_H */ | 46 | #endif /* AES_GCM_H */ |
| @@ -459,7 +459,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, · 458 unmodified lines | |||
| 459 | } | 459 | } |
| 460 | 460 | ||
| 461 | void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, | 461 | void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, |
| 462 | const u8 *addr, unsigned int bit) | 462 | const u8 *addr, unsigned int tid) |
| 463 | { | 463 | { |
| 464 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 464 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
| 465 | struct ieee80211_local *local = sdata->local; | 465 | struct ieee80211_local *local = sdata->local; |
| @@ -470,7 +470,7 @@ void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, · 4 unmodified lines | |||
| 470 | if (!sta) | 470 | if (!sta) |
| 471 | goto unlock; | 471 | goto unlock; |
| 472 | 472 | ||
| 473 | set_bit(bit, sta->ampdu_mlme.tid_rx_manage_offl); | 473 | set_bit(tid, sta->ampdu_mlme.tid_rx_manage_offl); |
| 474 | ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); | 474 | ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); |
| 475 | unlock: | 475 | unlock: |
| 476 | rcu_read_unlock(); | 476 | rcu_read_unlock(); |
| @@ -290,13 +290,15 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, · 289 unmodified lines | |||
| 290 | { | 290 | { |
| 291 | int i; | 291 | int i; |
| 292 | 292 | ||
| 293 | mutex_lock(&sta->ampdu_mlme.mtx); | ||
| 293 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { | 294 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
| 294 | __ieee80211_stop_tx_ba_session(sta, i, reason); | 295 | ___ieee80211_stop_tx_ba_session(sta, i, reason); |
| 295 | __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, | 296 | ___ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, |
| 296 | WLAN_REASON_QSTA_LEAVE_QBSS, | 297 | WLAN_REASON_QSTA_LEAVE_QBSS, |
| 297 | reason != AGG_STOP_DESTROY_STA && | 298 | reason != AGG_STOP_DESTROY_STA && |
| 298 | reason != AGG_STOP_PEER_REQUEST); | 299 | reason != AGG_STOP_PEER_REQUEST); |
| 299 | } | 300 | } |
| 301 | mutex_unlock(&sta->ampdu_mlme.mtx); | ||
| 300 | 302 | ||
| 301 | /* stopping might queue the work again - so cancel only afterwards */ | 303 | /* stopping might queue the work again - so cancel only afterwards */ |
| 302 | cancel_work_sync(&sta->ampdu_mlme.work); | 304 | cancel_work_sync(&sta->ampdu_mlme.work); |
| @@ -2009,6 +2009,8 @@ void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata, · 2008 unmodified lines | |||
| 2009 | struct txq_info *txq, int tid); | 2009 | struct txq_info *txq, int tid); |
| 2010 | void ieee80211_txq_purge(struct ieee80211_local *local, | 2010 | void ieee80211_txq_purge(struct ieee80211_local *local, |
| 2011 | struct txq_info *txqi); | 2011 | struct txq_info *txqi); |
| 2012 | void ieee80211_txq_remove_vlan(struct ieee80211_local *local, | ||
| 2013 | struct ieee80211_sub_if_data *sdata); | ||
| 2012 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 2014 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
| 2013 | u16 transaction, u16 auth_alg, u16 status, | 2015 | u16 transaction, u16 auth_alg, u16 status, |
| 2014 | const u8 *extra, size_t extra_len, const u8 *bssid, | 2016 | const u8 *extra, size_t extra_len, const u8 *bssid, |
| @@ -793,9 +793,7 @@ static int ieee80211_open(struct net_device *dev) · 792 unmodified lines | |||
| 793 | static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | 793 | static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, |
| 794 | bool going_down) | 794 | bool going_down) |
| 795 | { | 795 | { |
| 796 | struct ieee80211_sub_if_data *txq_sdata = sdata; | ||
| 797 | struct ieee80211_local *local = sdata->local; | 796 | struct ieee80211_local *local = sdata->local; |
| 798 | struct fq *fq = &local->fq; | ||
| 799 | unsigned long flags; | 797 | unsigned long flags; |
| 800 | struct sk_buff *skb, *tmp; | 798 | struct sk_buff *skb, *tmp; |
| 801 | u32 hw_reconf_flags = 0; | 799 | u32 hw_reconf_flags = 0; |
| @@ -939,9 +937,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, · 137 unmodified lines | |||
| 939 | 937 | ||
| 940 | switch (sdata->vif.type) { | 938 | switch (sdata->vif.type) { |
| 941 | case NL80211_IFTYPE_AP_VLAN: | 939 | case NL80211_IFTYPE_AP_VLAN: |
| 942 | txq_sdata = container_of(sdata->bss, | ||
| 943 | struct ieee80211_sub_if_data, u.ap); | ||
| 944 | |||
| 945 | mutex_lock(&local->mtx); | 940 | mutex_lock(&local->mtx); |
| 946 | list_del(&sdata->u.vlan.list); | 941 | list_del(&sdata->u.vlan.list); |
| 947 | mutex_unlock(&local->mtx); | 942 | mutex_unlock(&local->mtx); |
| @@ -998,8 +993,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, · 50 unmodified lines | |||
| 998 | skb_queue_purge(&sdata->skb_queue); | 993 | skb_queue_purge(&sdata->skb_queue); |
| 999 | } | 994 | } |
| 1000 | 995 | ||
| 1001 | sdata->bss = NULL; | ||
| 1002 | |||
| 1003 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 996 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
| 1004 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { | 997 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { |
| 1005 | skb_queue_walk_safe(&local->pending[i], skb, tmp) { | 998 | skb_queue_walk_safe(&local->pending[i], skb, tmp) { |
| @@ -1012,22 +1005,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, · 6 unmodified lines | |||
| 1012 | } | 1005 | } |
| 1013 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 1006 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
| 1014 | 1007 | ||
| 1015 | if (txq_sdata->vif.txq) { | 1008 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
| 1016 | struct txq_info *txqi = to_txq_info(txq_sdata->vif.txq); | 1009 | ieee80211_txq_remove_vlan(local, sdata); |
| 1017 | |||
| 1018 | /* | ||
| 1019 | * FIXME FIXME | ||
| 1020 | * | ||
| 1021 | * We really shouldn't purge the *entire* txqi since that | ||
| 1022 | * contains frames for the other AP_VLANs (and possibly | ||
| 1023 | * the AP itself) as well, but there's no API in FQ now | ||
| 1024 | * to be able to filter. | ||
| 1025 | */ | ||
| 1026 | 1010 | ||
| 1027 | spin_lock_bh(&fq->lock); | 1011 | sdata->bss = NULL; |
| 1028 | ieee80211_txq_purge(local, txqi); | ||
| 1029 | spin_unlock_bh(&fq->lock); | ||
| 1030 | } | ||
| 1031 | 1012 | ||
| 1032 | if (local->open_count == 0) | 1013 | if (local->open_count == 0) |
| 1033 | ieee80211_clear_tx_pending(local); | 1014 | ieee80211_clear_tx_pending(local); |
| @@ -1772,7 +1753,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, · 738 unmodified lines | |||
| 1772 | sizeof(void *)); | 1753 | sizeof(void *)); |
| 1773 | int txq_size = 0; | 1754 | int txq_size = 0; |
| 1774 | 1755 | ||
| 1775 | if (local->ops->wake_tx_queue) | 1756 | if (local->ops->wake_tx_queue && |
| 1757 | type != NL80211_IFTYPE_AP_VLAN && | ||
| 1758 | type != NL80211_IFTYPE_MONITOR) | ||
| 1776 | txq_size += sizeof(struct txq_info) + | 1759 | txq_size += sizeof(struct txq_info) + |
| 1777 | local->hw.txq_data_size; | 1760 | local->hw.txq_data_size; |
| 1778 | 1761 | ||
| @@ -675,8 +675,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) · 674 unmodified lines | |||
| 675 | enum nl80211_band band; | 675 | enum nl80211_band band; |
| 676 | u8 *pos; | 676 | u8 *pos; |
| 677 | struct ieee80211_sub_if_data *sdata; | 677 | struct ieee80211_sub_if_data *sdata; |
| 678 | int hdr_len = offsetof(struct ieee80211_mgmt, u.beacon) + | 678 | int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon); |
| 679 | sizeof(mgmt->u.beacon); | ||
| 680 | 679 | ||
| 681 | sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh); | 680 | sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh); |
| 682 | rcu_read_lock(); | 681 | rcu_read_lock(); |
| @@ -275,6 +275,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, · 274 unmodified lines | |||
| 275 | u8 *hw_addr, struct ieee802_11_elems *ie); | 275 | u8 *hw_addr, struct ieee802_11_elems *ie); |
| 276 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); | 276 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); |
| 277 | u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); | 277 | u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); |
| 278 | void mesh_plink_timer(struct timer_list *t); | ||
| 278 | void mesh_plink_broken(struct sta_info *sta); | 279 | void mesh_plink_broken(struct sta_info *sta); |
| 279 | u32 mesh_plink_deactivate(struct sta_info *sta); | 280 | u32 mesh_plink_deactivate(struct sta_info *sta); |
| 280 | u32 mesh_plink_open(struct sta_info *sta); | 281 | u32 mesh_plink_open(struct sta_info *sta); |
| @@ -111,8 +111,8 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, · 110 unmodified lines | |||
| 111 | struct sk_buff *skb; | 111 | struct sk_buff *skb; |
| 112 | struct ieee80211_mgmt *mgmt; | 112 | struct ieee80211_mgmt *mgmt; |
| 113 | u8 *pos, ie_len; | 113 | u8 *pos, ie_len; |
| 114 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) + | 114 | int hdr_len = offsetofend(struct ieee80211_mgmt, |
| 115 | sizeof(mgmt->u.action.u.mesh_action); | 115 | u.action.u.mesh_action); |
| 116 | 116 | ||
| 117 | skb = dev_alloc_skb(local->tx_headroom + | 117 | skb = dev_alloc_skb(local->tx_headroom + |
| 118 | hdr_len + | 118 | hdr_len + |
| @@ -242,8 +242,8 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, · 123 unmodified lines | |||
| 242 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 242 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 243 | struct ieee80211_mgmt *mgmt; | 243 | struct ieee80211_mgmt *mgmt; |
| 244 | u8 *pos, ie_len; | 244 | u8 *pos, ie_len; |
| 245 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) + | 245 | int hdr_len = offsetofend(struct ieee80211_mgmt, |
| 246 | sizeof(mgmt->u.action.u.mesh_action); | 246 | u.action.u.mesh_action); |
| 247 | 247 | ||
| 248 | if (time_before(jiffies, ifmsh->next_perr)) | 248 | if (time_before(jiffies, ifmsh->next_perr)) |
| 249 | return -EAGAIN; | 249 | return -EAGAIN; |
| @@ -220,8 +220,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, · 219 unmodified lines | |||
| 220 | bool include_plid = false; | 220 | bool include_plid = false; |
| 221 | u16 peering_proto = 0; | 221 | u16 peering_proto = 0; |
| 222 | u8 *pos, ie_len = 4; | 222 | u8 *pos, ie_len = 4; |
| 223 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) + | 223 | int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.self_prot); |
| 224 | sizeof(mgmt->u.action.u.self_prot); | ||
| 225 | int err = -ENOMEM; | 224 | int err = -ENOMEM; |
| 226 | 225 | ||
| 227 | skb = dev_alloc_skb(local->tx_headroom + | 226 | skb = dev_alloc_skb(local->tx_headroom + |
| @@ -604,8 +603,9 @@ out: · 376 unmodified lines | |||
| 604 | ieee80211_mbss_info_change_notify(sdata, changed); | 603 | ieee80211_mbss_info_change_notify(sdata, changed); |
| 605 | } | 604 | } |
| 606 | 605 | ||
| 607 | static void mesh_plink_timer(unsigned long data) | 606 | void mesh_plink_timer(struct timer_list *t) |
| 608 | { | 607 | { |
| 608 | struct mesh_sta *mesh = from_timer(mesh, t, plink_timer); | ||
| 609 | struct sta_info *sta; | 609 | struct sta_info *sta; |
| 610 | u16 reason = 0; | 610 | u16 reason = 0; |
| 611 | struct ieee80211_sub_if_data *sdata; | 611 | struct ieee80211_sub_if_data *sdata; |
| @@ -617,7 +617,7 @@ static void mesh_plink_timer(unsigned long data) · 5 unmodified lines | |||
| 617 | * del_timer_sync() this timer after having made sure | 617 | * del_timer_sync() this timer after having made sure |
| 618 | * it cannot be readded (by deleting the plink.) | 618 | * it cannot be readded (by deleting the plink.) |
| 619 | */ | 619 | */ |
| 620 | sta = (struct sta_info *) data; | 620 | sta = mesh->plink_sta; |
| 621 | 621 | ||
| 622 | if (sta->sdata->local->quiescing) | 622 | if (sta->sdata->local->quiescing) |
| 623 | return; | 623 | return; |
| @@ -697,11 +697,8 @@ static void mesh_plink_timer(unsigned long data) · 73 unmodified lines | |||
| 697 | 697 | ||
| 698 | static inline void mesh_plink_timer_set(struct sta_info *sta, u32 timeout) | 698 | static inline void mesh_plink_timer_set(struct sta_info *sta, u32 timeout) |
| 699 | { | 699 | { |
| 700 | sta->mesh->plink_timer.expires = jiffies + msecs_to_jiffies(timeout); | ||
| 701 | sta->mesh->plink_timer.data = (unsigned long) sta; | ||
| 702 | sta->mesh->plink_timer.function = mesh_plink_timer; | ||
| 703 | sta->mesh->plink_timeout = timeout; | 700 | sta->mesh->plink_timeout = timeout; |
| 704 | add_timer(&sta->mesh->plink_timer); | 701 | mod_timer(&sta->mesh->plink_timer, jiffies + msecs_to_jiffies(timeout)); |
| 705 | } | 702 | } |
| 706 | 703 | ||
| 707 | static bool llid_in_use(struct ieee80211_sub_if_data *sdata, | 704 | static bool llid_in_use(struct ieee80211_sub_if_data *sdata, |
| @@ -780,11 +780,12 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) · 779 unmodified lines | |||
| 780 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | 780 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, |
| 781 | WLAN_EID_HT_CAPABILITY, | 781 | WLAN_EID_HT_CAPABILITY, |
| 782 | WLAN_EID_BSS_COEX_2040, | 782 | WLAN_EID_BSS_COEX_2040, |
| 783 | /* luckily this is almost always there */ | ||
| 783 | WLAN_EID_EXT_CAPABILITY, | 784 | WLAN_EID_EXT_CAPABILITY, |
| 784 | WLAN_EID_QOS_TRAFFIC_CAPA, | 785 | WLAN_EID_QOS_TRAFFIC_CAPA, |
| 785 | WLAN_EID_TIM_BCAST_REQ, | 786 | WLAN_EID_TIM_BCAST_REQ, |
| 786 | WLAN_EID_INTERWORKING, | 787 | WLAN_EID_INTERWORKING, |
| 787 | /* 60GHz doesn't happen right now */ | 788 | /* 60 GHz (Multi-band, DMG, MMS) can't happen */ |
| 788 | WLAN_EID_VHT_CAPABILITY, | 789 | WLAN_EID_VHT_CAPABILITY, |
| 789 | WLAN_EID_OPMODE_NOTIF, | 790 | WLAN_EID_OPMODE_NOTIF, |
| 790 | }; | 791 | }; |
| @@ -811,22 +812,16 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) · 20 unmodified lines | |||
| 811 | /* if present, add any custom IEs that go before VHT */ | 812 | /* if present, add any custom IEs that go before VHT */ |
| 812 | if (assoc_data->ie_len) { | 813 | if (assoc_data->ie_len) { |
| 813 | static const u8 before_vht[] = { | 814 | static const u8 before_vht[] = { |
| 814 | WLAN_EID_SSID, | 815 | /* |
| 815 | WLAN_EID_SUPP_RATES, | 816 | * no need to list the ones split off before HT |
| 816 | WLAN_EID_EXT_SUPP_RATES, | 817 | * or generated here |
| 817 | WLAN_EID_PWR_CAPABILITY, | 818 | */ |
| 818 | WLAN_EID_SUPPORTED_CHANNELS, | ||
| 819 | WLAN_EID_RSN, | ||
| 820 | WLAN_EID_QOS_CAPA, | ||
| 821 | WLAN_EID_RRM_ENABLED_CAPABILITIES, | ||
| 822 | WLAN_EID_MOBILITY_DOMAIN, | ||
| 823 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
| 824 | WLAN_EID_HT_CAPABILITY, | ||
| 825 | WLAN_EID_BSS_COEX_2040, | 819 | WLAN_EID_BSS_COEX_2040, |
| 826 | WLAN_EID_EXT_CAPABILITY, | 820 | WLAN_EID_EXT_CAPABILITY, |
| 827 | WLAN_EID_QOS_TRAFFIC_CAPA, | 821 | WLAN_EID_QOS_TRAFFIC_CAPA, |
| 828 | WLAN_EID_TIM_BCAST_REQ, | 822 | WLAN_EID_TIM_BCAST_REQ, |
| 829 | WLAN_EID_INTERWORKING, | 823 | WLAN_EID_INTERWORKING, |
| 824 | /* 60 GHz (Multi-band, DMG, MMS) can't happen */ | ||
| 830 | }; | 825 | }; |
| 831 | 826 | ||
| 832 | /* RIC already taken above, so no need to handle here anymore */ | 827 | /* RIC already taken above, so no need to handle here anymore */ |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | |||
| 7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
| 8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | 8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> |
| 9 | * Copyright 2013-2015 Intel Mobile Communications GmbH | 9 | * Copyright 2013-2015 Intel Mobile Communications GmbH |
| 10 | * Copyright 2016 Intel Deutschland GmbH | 10 | * Copyright 2016-2017 Intel Deutschland GmbH |
| 11 | * | 11 | * |
| 12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
| 13 | * it under the terms of the GNU General Public License version 2 as | 13 | * it under the terms of the GNU General Public License version 2 as |
| @@ -183,6 +183,20 @@ ieee80211_bss_info_update(struct ieee80211_local *local, · 169 unmodified lines | |||
| 183 | return bss; | 183 | return bss; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | static bool ieee80211_scan_accept_presp(struct ieee80211_sub_if_data *sdata, | ||
| 187 | u32 scan_flags, const u8 *da) | ||
| 188 | { | ||
| 189 | if (!sdata) | ||
| 190 | return false; | ||
| 191 | /* accept broadcast for OCE */ | ||
| 192 | if (scan_flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP && | ||
| 193 | is_broadcast_ether_addr(da)) | ||
| 194 | return true; | ||
| 195 | if (scan_flags & NL80211_SCAN_FLAG_RANDOM_ADDR) | ||
| 196 | return true; | ||
| 197 | return ether_addr_equal(da, sdata->vif.addr); | ||
| 198 | } | ||
| 199 | |||
| 186 | void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | 200 | void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) |
| 187 | { | 201 | { |
| 188 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); | 202 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); |
| @@ -208,19 +222,24 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) · 19 unmodified lines | |||
| 208 | if (ieee80211_is_probe_resp(mgmt->frame_control)) { | 222 | if (ieee80211_is_probe_resp(mgmt->frame_control)) { |
| 209 | struct cfg80211_scan_request *scan_req; | 223 | struct cfg80211_scan_request *scan_req; |
| 210 | struct cfg80211_sched_scan_request *sched_scan_req; | 224 | struct cfg80211_sched_scan_request *sched_scan_req; |
| 225 | u32 scan_req_flags = 0, sched_scan_req_flags = 0; | ||
| 211 | 226 | ||
| 212 | scan_req = rcu_dereference(local->scan_req); | 227 | scan_req = rcu_dereference(local->scan_req); |
| 213 | sched_scan_req = rcu_dereference(local->sched_scan_req); | 228 | sched_scan_req = rcu_dereference(local->sched_scan_req); |
| 214 | 229 | ||
| 215 | /* ignore ProbeResp to foreign address unless scanning | 230 | if (scan_req) |
| 216 | * with randomised address | 231 | scan_req_flags = scan_req->flags; |
| 232 | |||
| 233 | if (sched_scan_req) | ||
| 234 | sched_scan_req_flags = sched_scan_req->flags; | ||
| 235 | |||
| 236 | /* ignore ProbeResp to foreign address or non-bcast (OCE) | ||
| 237 | * unless scanning with randomised address | ||
| 217 | */ | 238 | */ |
| 218 | if (!(sdata1 && | 239 | if (!ieee80211_scan_accept_presp(sdata1, scan_req_flags, |
| 219 | (ether_addr_equal(mgmt->da, sdata1->vif.addr) || | 240 | mgmt->da) && |
| 220 | scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) && | 241 | !ieee80211_scan_accept_presp(sdata2, sched_scan_req_flags, |
| 221 | !(sdata2 && | 242 | mgmt->da)) |
| 222 | (ether_addr_equal(mgmt->da, sdata2->vif.addr) || | ||
| 223 | sched_scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR))) | ||
| 224 | return; | 243 | return; |
| 225 | 244 | ||
| 226 | elements = mgmt->u.probe_resp.variable; | 245 | elements = mgmt->u.probe_resp.variable; |
| @@ -329,10 +329,12 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, · 328 unmodified lines | |||
| 329 | sta->mesh = kzalloc(sizeof(*sta->mesh), gfp); | 329 | sta->mesh = kzalloc(sizeof(*sta->mesh), gfp); |
| 330 | if (!sta->mesh) | 330 | if (!sta->mesh) |
| 331 | goto free; | 331 | goto free; |
| 332 | sta->mesh->plink_sta = sta; | ||
| 332 | spin_lock_init(&sta->mesh->plink_lock); | 333 | spin_lock_init(&sta->mesh->plink_lock); |
| 333 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 334 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
| 334 | !sdata->u.mesh.user_mpm) | 335 | !sdata->u.mesh.user_mpm) |
| 335 | init_timer(&sta->mesh->plink_timer); | 336 | timer_setup(&sta->mesh->plink_timer, mesh_plink_timer, |
| 337 | 0); | ||
| 336 | sta->mesh->nonpeer_pm = NL80211_MESH_POWER_ACTIVE; | 338 | sta->mesh->nonpeer_pm = NL80211_MESH_POWER_ACTIVE; |
| 337 | } | 339 | } |
| 338 | #endif | 340 | #endif |
| @@ -515,6 +517,31 @@ static int sta_info_insert_drv_state(struct ieee80211_local *local, · 176 unmodified lines | |||
| 515 | return err; | 517 | return err; |
| 516 | } | 518 | } |
| 517 | 519 | ||
| 520 | static void | ||
| 521 | ieee80211_recalc_p2p_go_ps_allowed(struct ieee80211_sub_if_data *sdata) | ||
| 522 | { | ||
| 523 | struct ieee80211_local *local = sdata->local; | ||
| 524 | bool allow_p2p_go_ps = sdata->vif.p2p; | ||
| 525 | struct sta_info *sta; | ||
| 526 | |||
| 527 | rcu_read_lock(); | ||
| 528 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
| 529 | if (sdata != sta->sdata || | ||
| 530 | !test_sta_flag(sta, WLAN_STA_ASSOC)) | ||
| 531 | continue; | ||
| 532 | if (!sta->sta.support_p2p_ps) { | ||
| 533 | allow_p2p_go_ps = false; | ||
| 534 | break; | ||
| 535 | } | ||
| 536 | } | ||
| 537 | rcu_read_unlock(); | ||
| 538 | |||
| 539 | if (allow_p2p_go_ps != sdata->vif.bss_conf.allow_p2p_go_ps) { | ||
| 540 | sdata->vif.bss_conf.allow_p2p_go_ps = allow_p2p_go_ps; | ||
| 541 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_P2P_PS); | ||
| 542 | } | ||
| 543 | } | ||
| 544 | |||
| 518 | /* | 545 | /* |
| 519 | * should be called with sta_mtx locked | 546 | * should be called with sta_mtx locked |
| 520 | * this function replaces the mutex lock | 547 | * this function replaces the mutex lock |
| @@ -561,6 +588,13 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) · 40 unmodified lines | |||
| 561 | goto out_remove; | 588 | goto out_remove; |
| 562 | 589 | ||
| 563 | set_sta_flag(sta, WLAN_STA_INSERTED); | 590 | set_sta_flag(sta, WLAN_STA_INSERTED); |
| 591 | |||
| 592 | if (sta->sta_state >= IEEE80211_STA_ASSOC) { | ||
| 593 | ieee80211_recalc_min_chandef(sta->sdata); | ||
| 594 | if (!sta->sta.support_p2p_ps) | ||
| 595 | ieee80211_recalc_p2p_go_ps_allowed(sta->sdata); | ||
| 596 | } | ||
| 597 | |||
| 564 | /* accept BA sessions now */ | 598 | /* accept BA sessions now */ |
| 565 | clear_sta_flag(sta, WLAN_STA_BLOCK_BA); | 599 | clear_sta_flag(sta, WLAN_STA_BLOCK_BA); |
| 566 | 600 | ||
| @@ -1788,31 +1822,6 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, · 1221 unmodified lines | |||
| 1788 | } | 1822 | } |
| 1789 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); | 1823 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); |
| 1790 | 1824 | ||
| 1791 | static void | ||
| 1792 | ieee80211_recalc_p2p_go_ps_allowed(struct ieee80211_sub_if_data *sdata) | ||
| 1793 | { | ||
| 1794 | struct ieee80211_local *local = sdata->local; | ||
| 1795 | bool allow_p2p_go_ps = sdata->vif.p2p; | ||
| 1796 | struct sta_info *sta; | ||
| 1797 | |||
| 1798 | rcu_read_lock(); | ||
| 1799 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
| 1800 | if (sdata != sta->sdata || | ||
| 1801 | !test_sta_flag(sta, WLAN_STA_ASSOC)) | ||
| 1802 | continue; | ||
| 1803 | if (!sta->sta.support_p2p_ps) { | ||
| 1804 | allow_p2p_go_ps = false; | ||
| 1805 | break; | ||
| 1806 | } | ||
| 1807 | } | ||
| 1808 | rcu_read_unlock(); | ||
| 1809 | |||
| 1810 | if (allow_p2p_go_ps != sdata->vif.bss_conf.allow_p2p_go_ps) { | ||
| 1811 | sdata->vif.bss_conf.allow_p2p_go_ps = allow_p2p_go_ps; | ||
| 1812 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_P2P_PS); | ||
| 1813 | } | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | int sta_info_move_state(struct sta_info *sta, | 1825 | int sta_info_move_state(struct sta_info *sta, |
| 1817 | enum ieee80211_sta_state new_state) | 1826 | enum ieee80211_sta_state new_state) |
| 1818 | { | 1827 | { |
| @@ -344,6 +344,7 @@ DECLARE_EWMA(mesh_fail_avg, 20, 8) · 343 unmodified lines | |||
| 344 | * @plink_state: peer link state | 344 | * @plink_state: peer link state |
| 345 | * @plink_timeout: timeout of peer link | 345 | * @plink_timeout: timeout of peer link |
| 346 | * @plink_timer: peer link watch timer | 346 | * @plink_timer: peer link watch timer |
| 347 | * @plink_sta: peer link watch timer's sta_info | ||
| 347 | * @t_offset: timing offset relative to this host | 348 | * @t_offset: timing offset relative to this host |
| 348 | * @t_offset_setpoint: reference timing offset of this sta to be used when | 349 | * @t_offset_setpoint: reference timing offset of this sta to be used when |
| 349 | * calculating clockdrift | 350 | * calculating clockdrift |
| @@ -356,6 +357,7 @@ DECLARE_EWMA(mesh_fail_avg, 20, 8) · 6 unmodified lines | |||
| 356 | */ | 357 | */ |
| 357 | struct mesh_sta { | 358 | struct mesh_sta { |
| 358 | struct timer_list plink_timer; | 359 | struct timer_list plink_timer; |
| 360 | struct sta_info *plink_sta; | ||
| 359 | 361 | ||
| 360 | s64 t_offset; | 362 | s64 t_offset; |
| 361 | s64 t_offset_setpoint; | 363 | s64 t_offset_setpoint; |
| @@ -398,7 +400,7 @@ struct ieee80211_sta_rx_stats { · 36 unmodified lines | |||
| 398 | u64 msdu[IEEE80211_NUM_TIDS + 1]; | 400 | u64 msdu[IEEE80211_NUM_TIDS + 1]; |
| 399 | }; | 401 | }; |
| 400 | 402 | ||
| 401 | /** | 403 | /* |
| 402 | * The bandwidth threshold below which the per-station CoDel parameters will be | 404 | * The bandwidth threshold below which the per-station CoDel parameters will be |
| 403 | * scaled to be more lenient (to prevent starvation of slow stations). This | 405 | * scaled to be more lenient (to prevent starvation of slow stations). This |
| 404 | * value will be scaled by the number of active stations when it is being | 406 | * value will be scaled by the number of active stations when it is being |
| @@ -1396,6 +1396,40 @@ static void ieee80211_txq_enqueue(struct ieee80211_local *local, · 1395 unmodified lines | |||
| 1396 | fq_flow_get_default_func); | 1396 | fq_flow_get_default_func); |
| 1397 | } | 1397 | } |
| 1398 | 1398 | ||
| 1399 | static bool fq_vlan_filter_func(struct fq *fq, struct fq_tin *tin, | ||
| 1400 | struct fq_flow *flow, struct sk_buff *skb, | ||
| 1401 | void *data) | ||
| 1402 | { | ||
| 1403 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 1404 | |||
| 1405 | return info->control.vif == data; | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | void ieee80211_txq_remove_vlan(struct ieee80211_local *local, | ||
| 1409 | struct ieee80211_sub_if_data *sdata) | ||
| 1410 | { | ||
| 1411 | struct fq *fq = &local->fq; | ||
| 1412 | struct txq_info *txqi; | ||
| 1413 | struct fq_tin *tin; | ||
| 1414 | struct ieee80211_sub_if_data *ap; | ||
| 1415 | |||
| 1416 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) | ||
| 1417 | return; | ||
| 1418 | |||
| 1419 | ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); | ||
| 1420 | |||
| 1421 | if (!ap->vif.txq) | ||
| 1422 | return; | ||
| 1423 | |||
| 1424 | txqi = to_txq_info(ap->vif.txq); | ||
| 1425 | tin = &txqi->tin; | ||
| 1426 | |||
| 1427 | spin_lock_bh(&fq->lock); | ||
| 1428 | fq_tin_filter(fq, tin, fq_vlan_filter_func, &sdata->vif, | ||
| 1429 | fq_skb_free_func); | ||
| 1430 | spin_unlock_bh(&fq->lock); | ||
| 1431 | } | ||
| 1432 | |||
| 1399 | void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata, | 1433 | void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata, |
| 1400 | struct sta_info *sta, | 1434 | struct sta_info *sta, |
| 1401 | struct txq_info *txqi, int tid) | 1435 | struct txq_info *txqi, int tid) |
| @@ -1392,10 +1392,10 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, · 1391 unmodified lines | |||
| 1392 | /* insert custom IEs that go before HT */ | 1392 | /* insert custom IEs that go before HT */ |
| 1393 | if (ie && ie_len) { | 1393 | if (ie && ie_len) { |
| 1394 | static const u8 before_ht[] = { | 1394 | static const u8 before_ht[] = { |
| 1395 | WLAN_EID_SSID, | 1395 | /* |
| 1396 | WLAN_EID_SUPP_RATES, | 1396 | * no need to list the ones split off already |
| 1397 | WLAN_EID_REQUEST, | 1397 | * (or generated here) |
| 1398 | WLAN_EID_EXT_SUPP_RATES, | 1398 | */ |
| 1399 | WLAN_EID_DS_PARAMS, | 1399 | WLAN_EID_DS_PARAMS, |
| 1400 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | 1400 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, |
| 1401 | }; | 1401 | }; |
| @@ -1424,20 +1424,17 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, · 22 unmodified lines | |||
| 1424 | /* insert custom IEs that go before VHT */ | 1424 | /* insert custom IEs that go before VHT */ |
| 1425 | if (ie && ie_len) { | 1425 | if (ie && ie_len) { |
| 1426 | static const u8 before_vht[] = { | 1426 | static const u8 before_vht[] = { |
| 1427 | WLAN_EID_SSID, | 1427 | /* |
| 1428 | WLAN_EID_SUPP_RATES, | 1428 | * no need to list the ones split off already |
| 1429 | WLAN_EID_REQUEST, | 1429 | * (or generated here) |
| 1430 | WLAN_EID_EXT_SUPP_RATES, | 1430 | */ |
| 1431 | WLAN_EID_DS_PARAMS, | ||
| 1432 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
| 1433 | WLAN_EID_HT_CAPABILITY, | ||
| 1434 | WLAN_EID_BSS_COEX_2040, | 1431 | WLAN_EID_BSS_COEX_2040, |
| 1435 | WLAN_EID_EXT_CAPABILITY, | 1432 | WLAN_EID_EXT_CAPABILITY, |
| 1436 | WLAN_EID_SSID_LIST, | 1433 | WLAN_EID_SSID_LIST, |
| 1437 | WLAN_EID_CHANNEL_USAGE, | 1434 | WLAN_EID_CHANNEL_USAGE, |
| 1438 | WLAN_EID_INTERWORKING, | 1435 | WLAN_EID_INTERWORKING, |
| 1439 | WLAN_EID_MESH_ID, | 1436 | WLAN_EID_MESH_ID, |
| 1440 | /* 60 GHz can't happen here right now */ | 1437 | /* 60 GHz (Multi-band, DMG, MMS) can't happen */ |
| 1441 | }; | 1438 | }; |
| 1442 | noffset = ieee80211_ie_split(ie, ie_len, | 1439 | noffset = ieee80211_ie_split(ie, ie_len, |
| 1443 | before_vht, ARRAY_SIZE(before_vht), | 1440 | before_vht, ARRAY_SIZE(before_vht), |
| @@ -2980,8 +2977,8 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, · 1536 unmodified lines | |||
| 2980 | struct ieee80211_mgmt *mgmt; | 2977 | struct ieee80211_mgmt *mgmt; |
| 2981 | struct ieee80211_local *local = sdata->local; | 2978 | struct ieee80211_local *local = sdata->local; |
| 2982 | int freq; | 2979 | int freq; |
| 2983 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.chan_switch) + | 2980 | int hdr_len = offsetofend(struct ieee80211_mgmt, |
| 2984 | sizeof(mgmt->u.action.u.chan_switch); | 2981 | u.action.u.chan_switch); |
| 2985 | u8 *pos; | 2982 | u8 *pos; |
| 2986 | 2983 | ||
| 2987 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && | 2984 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
| @@ -386,6 +386,16 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta) · 385 unmodified lines | |||
| 386 | 386 | ||
| 387 | bw = ieee80211_sta_cap_rx_bw(sta); | 387 | bw = ieee80211_sta_cap_rx_bw(sta); |
| 388 | bw = min(bw, sta->cur_max_bandwidth); | 388 | bw = min(bw, sta->cur_max_bandwidth); |
| 389 | |||
| 390 | /* Don't consider AP's bandwidth for TDLS peers, section 11.23.1 of | ||
| 391 | * IEEE80211-2016 specification makes higher bandwidth operation | ||
| 392 | * possible on the TDLS link if the peers have wider bandwidth | ||
| 393 | * capability. | ||
| 394 | */ | ||
| 395 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && | ||
| 396 | test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW)) | ||
| 397 | return bw; | ||
| 398 | |||
| 389 | bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width)); | 399 | bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width)); |
| 390 | 400 | ||
| 391 | return bw; | 401 | return bw; |
| @@ -464,7 +464,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb, · 463 unmodified lines | |||
| 464 | pos += IEEE80211_CCMP_HDR_LEN; | 464 | pos += IEEE80211_CCMP_HDR_LEN; |
| 465 | ccmp_special_blocks(skb, pn, b_0, aad); | 465 | ccmp_special_blocks(skb, pn, b_0, aad); |
| 466 | return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, | 466 | return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, |
| 467 | skb_put(skb, mic_len), mic_len); | 467 | skb_put(skb, mic_len)); |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | 470 | ||
| @@ -543,7 +543,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, · 72 unmodified lines | |||
| 543 | key->u.ccmp.tfm, b_0, aad, | 543 | key->u.ccmp.tfm, b_0, aad, |
| 544 | skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, | 544 | skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, |
| 545 | data_len, | 545 | data_len, |
| 546 | skb->data + skb->len - mic_len, mic_len)) | 546 | skb->data + skb->len - mic_len)) |
| 547 | return RX_DROP_UNUSABLE; | 547 | return RX_DROP_UNUSABLE; |
| 548 | } | 548 | } |
| 549 | 549 | ||
| @@ -1 +1,2 @@ | |||
| 1 | regdb.c | 1 | shipped-certs.c |
| 2 | extra-certs.c | ||
| @@ -19,6 +19,7 @@ config WEXT_PRIV · 18 unmodified lines | |||
| 19 | config CFG80211 | 19 | config CFG80211 |
| 20 | tristate "cfg80211 - wireless configuration API" | 20 | tristate "cfg80211 - wireless configuration API" |
| 21 | depends on RFKILL || !RFKILL | 21 | depends on RFKILL || !RFKILL |
| 22 | select FW_LOADER | ||
| 22 | ---help--- | 23 | ---help--- |
| 23 | cfg80211 is the Linux wireless LAN (802.11) configuration API. | 24 | cfg80211 is the Linux wireless LAN (802.11) configuration API. |
| 24 | Enable this if you have a wireless device. | 25 | Enable this if you have a wireless device. |
| @@ -82,6 +83,36 @@ config CFG80211_CERTIFICATION_ONUS · 57 unmodified lines | |||
| 82 | you are a wireless researcher and are working in a controlled | 83 | you are a wireless researcher and are working in a controlled |
| 83 | and approved environment by your local regulatory agency. | 84 | and approved environment by your local regulatory agency. |
| 84 | 85 | ||
| 86 | config CFG80211_REQUIRE_SIGNED_REGDB | ||
| 87 | bool "require regdb signature" if CFG80211_CERTIFICATION_ONUS | ||
| 88 | default y | ||
| 89 | select SYSTEM_DATA_VERIFICATION | ||
| 90 | help | ||
| 91 | Require that in addition to the "regulatory.db" file a | ||
| 92 | "regulatory.db.p7s" can be loaded with a valid PKCS#7 | ||
| 93 | signature for the regulatory.db file made by one of the | ||
| 94 | keys in the certs/ directory. | ||
| 95 | |||
| 96 | config CFG80211_USE_KERNEL_REGDB_KEYS | ||
| 97 | bool "allow regdb keys shipped with the kernel" if CFG80211_CERTIFICATION_ONUS | ||
| 98 | default y | ||
| 99 | depends on CFG80211_REQUIRE_SIGNED_REGDB | ||
| 100 | help | ||
| 101 | Allow the regulatory database to be signed by one of the keys for | ||
| 102 | which certificates are part of the kernel sources | ||
| 103 | (in net/wireless/certs/). | ||
| 104 | |||
| 105 | This is currently only Seth Forshee's key, who is the regulatory | ||
| 106 | database maintainer. | ||
| 107 | |||
| 108 | config CFG80211_EXTRA_REGDB_KEYDIR | ||
| 109 | string "additional regdb key directory" if CFG80211_CERTIFICATION_ONUS | ||
| 110 | depends on CFG80211_REQUIRE_SIGNED_REGDB | ||
| 111 | help | ||
| 112 | If selected, point to a directory with DER-encoded X.509 | ||
| 113 | certificates like in the kernel sources (net/wireless/certs/) | ||
| 114 | that shall be accepted for a signed regulatory database. | ||
| 115 | |||
| 85 | config CFG80211_REG_CELLULAR_HINTS | 116 | config CFG80211_REG_CELLULAR_HINTS |
| 86 | bool "cfg80211 regulatory support for cellular base station hints" | 117 | bool "cfg80211 regulatory support for cellular base station hints" |
| 87 | depends on CFG80211_CERTIFICATION_ONUS | 118 | depends on CFG80211_CERTIFICATION_ONUS |
| @@ -139,35 +170,14 @@ config CFG80211_DEBUGFS · 51 unmodified lines | |||
| 139 | 170 | ||
| 140 | If unsure, say N. | 171 | If unsure, say N. |
| 141 | 172 | ||
| 142 | config CFG80211_INTERNAL_REGDB | ||
| 143 | bool "use statically compiled regulatory rules database" if EXPERT | ||
| 144 | default n | ||
| 145 | depends on CFG80211 | ||
| 146 | ---help--- | ||
| 147 | This option generates an internal data structure representing | ||
| 148 | the wireless regulatory rules described in net/wireless/db.txt | ||
| 149 | and includes code to query that database. This is an alternative | ||
| 150 | to using CRDA for defining regulatory rules for the kernel. | ||
| 151 | |||
| 152 | Using this option requires some parsing of the db.txt at build time, | ||
| 153 | the parser will be upkept with the latest wireless-regdb updates but | ||
| 154 | older wireless-regdb formats will be ignored. The parser may later | ||
| 155 | be replaced to avoid issues with conflicts on versions of | ||
| 156 | wireless-regdb. | ||
| 157 | |||
| 158 | For details see: | ||
| 159 | |||
| 160 | http://wireless.kernel.org/en/developers/Regulatory | ||
| 161 | |||
| 162 | Most distributions have a CRDA package. So if unsure, say N. | ||
| 163 | |||
| 164 | config CFG80211_CRDA_SUPPORT | 173 | config CFG80211_CRDA_SUPPORT |
| 165 | bool "support CRDA" if CFG80211_INTERNAL_REGDB | 174 | bool "support CRDA" if EXPERT |
| 166 | default y | 175 | default y |
| 167 | depends on CFG80211 | 176 | depends on CFG80211 |
| 168 | help | 177 | help |
| 169 | You should enable this option unless you know for sure you have no | 178 | You should enable this option unless you know for sure you have no |
| 170 | need for it, for example when using internal regdb (above.) | 179 | need for it, for example when using internal regdb (above) or the |
| 180 | database loaded as a firmware file. | ||
| 171 | 181 | ||
| 172 | If unsure, say Y. | 182 | If unsure, say Y. |
| 173 | 183 | ||
| @@ -14,11 +14,27 @@ cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o ocb.o · 13 unmodified lines | |||
| 14 | cfg80211-$(CONFIG_OF) += of.o | 14 | cfg80211-$(CONFIG_OF) += of.o |
| 15 | cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o | 15 | cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o |
| 16 | cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o | 16 | cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o |
| 17 | cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o | ||
| 18 | 17 | ||
| 19 | CFLAGS_trace.o := -I$(src) | 18 | CFLAGS_trace.o := -I$(src) |
| 20 | 19 | ||
| 21 | $(obj)/regdb.c: $(src)/db.txt $(src)/genregdb.awk | 20 | cfg80211-$(CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS) += shipped-certs.o |
| 22 | @$(AWK) -f $(srctree)/$(src)/genregdb.awk < $< > $@ | 21 | ifneq ($(CONFIG_CFG80211_EXTRA_REGDB_KEYDIR),) |
| 22 | cfg80211-y += extra-certs.o | ||
| 23 | endif | ||
| 23 | 24 | ||
| 24 | clean-files := regdb.c | 25 | $(obj)/shipped-certs.c: $(wildcard $(srctree)/$(src)/certs/*.x509) |
| 26 | @echo " GEN $@" | ||
| 27 | @echo '#include "reg.h"' > $@ | ||
| 28 | @echo 'const u8 shipped_regdb_certs[] = {' >> $@ | ||
| 29 | @for f in $^ ; do hexdump -v -e '1/1 "0x%.2x," "\n"' < $$f >> $@ ; done | ||
| 30 | @echo '};' >> $@ | ||
| 31 | @echo 'unsigned int shipped_regdb_certs_len = sizeof(shipped_regdb_certs);' >> $@ | ||
| 32 | |||
| 33 | $(obj)/extra-certs.c: $(CONFIG_CFG80211_EXTRA_REGDB_KEYDIR:"%"=%) \ | ||
| 34 | $(wildcard $(CONFIG_CFG80211_EXTRA_REGDB_KEYDIR:"%"=%)/*.x509) | ||
| 35 | @echo " GEN $@" | ||
| 36 | @echo '#include "reg.h"' > $@ | ||
| 37 | @echo 'const u8 extra_regdb_certs[] = {' >> $@ | ||
| 38 | @for f in $^ ; do test -f $$f && hexdump -v -e '1/1 "0x%.2x," "\n"' < $$f >> $@ || true ; done | ||
| 39 | @echo '};' >> $@ | ||
| 40 | @echo 'unsigned int extra_regdb_certs_len = sizeof(extra_regdb_certs);' >> $@ | ||
Binary file not shown.
| @@ -1384,7 +1384,7 @@ out_fail_sysfs: · 1383 unmodified lines | |||
| 1384 | out_fail_pernet: | 1384 | out_fail_pernet: |
| 1385 | return err; | 1385 | return err; |
| 1386 | } | 1386 | } |
| 1387 | subsys_initcall(cfg80211_init); | 1387 | fs_initcall(cfg80211_init); |
| 1388 | 1388 | ||
| 1389 | static void __exit cfg80211_exit(void) | 1389 | static void __exit cfg80211_exit(void) |
| 1390 | { | 1390 | { |
| @@ -216,6 +216,7 @@ enum cfg80211_event_type { · 215 unmodified lines | |||
| 216 | EVENT_DISCONNECTED, | 216 | EVENT_DISCONNECTED, |
| 217 | EVENT_IBSS_JOINED, | 217 | EVENT_IBSS_JOINED, |
| 218 | EVENT_STOPPED, | 218 | EVENT_STOPPED, |
| 219 | EVENT_PORT_AUTHORIZED, | ||
| 219 | }; | 220 | }; |
| 220 | 221 | ||
| 221 | struct cfg80211_event { | 222 | struct cfg80211_event { |
| @@ -235,6 +236,9 @@ struct cfg80211_event { · 13 unmodified lines | |||
| 235 | u8 bssid[ETH_ALEN]; | 236 | u8 bssid[ETH_ALEN]; |
| 236 | struct ieee80211_channel *channel; | 237 | struct ieee80211_channel *channel; |
| 237 | } ij; | 238 | } ij; |
| 239 | struct { | ||
| 240 | u8 bssid[ETH_ALEN]; | ||
| 241 | } pa; | ||
| 238 | }; | 242 | }; |
| 239 | }; | 243 | }; |
| 240 | 244 | ||
| @@ -385,6 +389,7 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev, · 144 unmodified lines | |||
| 385 | bool wextev); | 389 | bool wextev); |
| 386 | void __cfg80211_roamed(struct wireless_dev *wdev, | 390 | void __cfg80211_roamed(struct wireless_dev *wdev, |
| 387 | struct cfg80211_roam_info *info); | 391 | struct cfg80211_roam_info *info); |
| 392 | void __cfg80211_port_authorized(struct wireless_dev *wdev, const u8 *bssid); | ||
| 388 | int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | 393 | int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, |
| 389 | struct wireless_dev *wdev); | 394 | struct wireless_dev *wdev); |
| 390 | void cfg80211_autodisconnect_wk(struct work_struct *work); | 395 | void cfg80211_autodisconnect_wk(struct work_struct *work); |
| @@ -1,17 +0,0 @@ | |||
| 1 | # | ||
| 2 | # This file is a placeholder to prevent accidental build breakage if someone | ||
| 3 | # enables CONFIG_CFG80211_INTERNAL_REGDB. Almost no one actually needs to | ||
| 4 | # enable that build option. | ||
| 5 | # | ||
| 6 | # You should be using CRDA instead. It is even better if you use the CRDA | ||
| 7 | # package provided by your distribution, since they will probably keep it | ||
| 8 | # up-to-date on your behalf. | ||
| 9 | # | ||
| 10 | # If you _really_ intend to use CONFIG_CFG80211_INTERNAL_REGDB then you will | ||
| 11 | # need to replace this file with one containing appropriately formatted | ||
| 12 | # regulatory rules that cover the regulatory domains you will be using. Your | ||
| 13 | # best option is to extract the db.txt file from the wireless-regdb git | ||
| 14 | # repository: | ||
| 15 | # | ||
| 16 | # git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git | ||
| 17 | # | ||
| @@ -1,158 +0,0 @@ | |||
| 1 | #!/usr/bin/awk -f | ||
| 2 | # | ||
| 3 | # genregdb.awk -- generate regdb.c from db.txt | ||
| 4 | # | ||
| 5 | # Actually, it reads from stdin (presumed to be db.txt) and writes | ||
| 6 | # to stdout (presumed to be regdb.c), but close enough... | ||
| 7 | # | ||
| 8 | # Copyright 2009 John W. Linville <linville@tuxdriver.com> | ||
| 9 | # | ||
| 10 | # Permission to use, copy, modify, and/or distribute this software for any | ||
| 11 | # purpose with or without fee is hereby granted, provided that the above | ||
| 12 | # copyright notice and this permission notice appear in all copies. | ||
| 13 | # | ||
| 14 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 15 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 16 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 17 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 18 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 19 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 20 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 21 | |||
| 22 | BEGIN { | ||
| 23 | active = 0 | ||
| 24 | rules = 0; | ||
| 25 | print "/*" | ||
| 26 | print " * DO NOT EDIT -- file generated from data in db.txt" | ||
| 27 | print " */" | ||
| 28 | print "" | ||
| 29 | print "#include <linux/nl80211.h>" | ||
| 30 | print "#include <net/cfg80211.h>" | ||
| 31 | print "#include \"regdb.h\"" | ||
| 32 | print "" | ||
| 33 | regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n" | ||
| 34 | } | ||
| 35 | |||
| 36 | function parse_country_head() { | ||
| 37 | country=$2 | ||
| 38 | sub(/:/, "", country) | ||
| 39 | printf "static const struct ieee80211_regdomain regdom_%s = {\n", country | ||
| 40 | printf "\t.alpha2 = \"%s\",\n", country | ||
| 41 | if ($NF ~ /DFS-ETSI/) | ||
| 42 | printf "\t.dfs_region = NL80211_DFS_ETSI,\n" | ||
| 43 | else if ($NF ~ /DFS-FCC/) | ||
| 44 | printf "\t.dfs_region = NL80211_DFS_FCC,\n" | ||
| 45 | else if ($NF ~ /DFS-JP/) | ||
| 46 | printf "\t.dfs_region = NL80211_DFS_JP,\n" | ||
| 47 | printf "\t.reg_rules = {\n" | ||
| 48 | active = 1 | ||
| 49 | regdb = regdb "\t®dom_" country ",\n" | ||
| 50 | } | ||
| 51 | |||
| 52 | function parse_reg_rule() | ||
| 53 | { | ||
| 54 | flag_starts_at = 7 | ||
| 55 | |||
| 56 | start = $1 | ||
| 57 | sub(/\(/, "", start) | ||
| 58 | end = $3 | ||
| 59 | bw = $5 | ||
| 60 | sub(/\),/, "", bw) | ||
| 61 | gain = 0 | ||
| 62 | power = $6 | ||
| 63 | # power might be in mW... | ||
| 64 | units = $7 | ||
| 65 | dfs_cac = 0 | ||
| 66 | |||
| 67 | sub(/\(/, "", power) | ||
| 68 | sub(/\),/, "", power) | ||
| 69 | sub(/\),/, "", units) | ||
| 70 | sub(/\)/, "", units) | ||
| 71 | |||
| 72 | if (units == "mW") { | ||
| 73 | flag_starts_at = 8 | ||
| 74 | power = 10 * log(power)/log(10) | ||
| 75 | if ($8 ~ /[[:digit:]]/) { | ||
| 76 | flag_starts_at = 9 | ||
| 77 | dfs_cac = $8 | ||
| 78 | } | ||
| 79 | } else { | ||
| 80 | if ($7 ~ /[[:digit:]]/) { | ||
| 81 | flag_starts_at = 8 | ||
| 82 | dfs_cac = $7 | ||
| 83 | } | ||
| 84 | } | ||
| 85 | sub(/\(/, "", dfs_cac) | ||
| 86 | sub(/\),/, "", dfs_cac) | ||
| 87 | flagstr = "" | ||
| 88 | for (i=flag_starts_at; i<=NF; i++) | ||
| 89 | flagstr = flagstr $i | ||
| 90 | split(flagstr, flagarray, ",") | ||
| 91 | flags = "" | ||
| 92 | for (arg in flagarray) { | ||
| 93 | if (flagarray[arg] == "NO-OFDM") { | ||
| 94 | flags = flags "\n\t\t\tNL80211_RRF_NO_OFDM | " | ||
| 95 | } else if (flagarray[arg] == "NO-CCK") { | ||
| 96 | flags = flags "\n\t\t\tNL80211_RRF_NO_CCK | " | ||
| 97 | } else if (flagarray[arg] == "NO-INDOOR") { | ||
| 98 | flags = flags "\n\t\t\tNL80211_RRF_NO_INDOOR | " | ||
| 99 | } else if (flagarray[arg] == "NO-OUTDOOR") { | ||
| 100 | flags = flags "\n\t\t\tNL80211_RRF_NO_OUTDOOR | " | ||
| 101 | } else if (flagarray[arg] == "DFS") { | ||
| 102 | flags = flags "\n\t\t\tNL80211_RRF_DFS | " | ||
| 103 | } else if (flagarray[arg] == "PTP-ONLY") { | ||
| 104 | flags = flags "\n\t\t\tNL80211_RRF_PTP_ONLY | " | ||
| 105 | } else if (flagarray[arg] == "PTMP-ONLY") { | ||
| 106 | flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | " | ||
| 107 | } else if (flagarray[arg] == "PASSIVE-SCAN") { | ||
| 108 | flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " | ||
| 109 | } else if (flagarray[arg] == "NO-IBSS") { | ||
| 110 | flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " | ||
| 111 | } else if (flagarray[arg] == "NO-IR") { | ||
| 112 | flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " | ||
| 113 | } else if (flagarray[arg] == "AUTO-BW") { | ||
| 114 | flags = flags "\n\t\t\tNL80211_RRF_AUTO_BW | " | ||
| 115 | } | ||
| 116 | |||
| 117 | } | ||
| 118 | flags = flags "0" | ||
| 119 | printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %.0f, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags | ||
| 120 | rules++ | ||
| 121 | } | ||
| 122 | |||
| 123 | function print_tail_country() | ||
| 124 | { | ||
| 125 | active = 0 | ||
| 126 | printf "\t},\n" | ||
| 127 | printf "\t.n_reg_rules = %d\n", rules | ||
| 128 | printf "};\n\n" | ||
| 129 | rules = 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | /^[ \t]*#/ { | ||
| 133 | # Ignore | ||
| 134 | } | ||
| 135 | |||
| 136 | !active && /^[ \t]*$/ { | ||
| 137 | # Ignore | ||
| 138 | } | ||
| 139 | |||
| 140 | !active && /country/ { | ||
| 141 | parse_country_head() | ||
| 142 | } | ||
| 143 | |||
| 144 | active && /^[ \t]*\(/ { | ||
| 145 | parse_reg_rule() | ||
| 146 | } | ||
| 147 | |||
| 148 | active && /^[ \t]*$/ { | ||
| 149 | print_tail_country() | ||
| 150 | } | ||
| 151 | |||
| 152 | END { | ||
| 153 | if (active) | ||
| 154 | print_tail_country() | ||
| 155 | print regdb "};" | ||
| 156 | print "" | ||
| 157 | print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);" | ||
| 158 | } | ||
| @@ -2130,6 +2130,15 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, · 2129 unmodified lines | |||
| 2130 | case NL80211_CHAN_HT40MINUS: | 2130 | case NL80211_CHAN_HT40MINUS: |
| 2131 | cfg80211_chandef_create(chandef, chandef->chan, | 2131 | cfg80211_chandef_create(chandef, chandef->chan, |
| 2132 | chantype); | 2132 | chantype); |
| 2133 | /* user input for center_freq is incorrect */ | ||
| 2134 | if (info->attrs[NL80211_ATTR_CENTER_FREQ1] && | ||
| 2135 | chandef->center_freq1 != nla_get_u32( | ||
| 2136 | info->attrs[NL80211_ATTR_CENTER_FREQ1])) | ||
| 2137 | return -EINVAL; | ||
| 2138 | /* center_freq2 must be zero */ | ||
| 2139 | if (info->attrs[NL80211_ATTR_CENTER_FREQ2] && | ||
| 2140 | nla_get_u32(info->attrs[NL80211_ATTR_CENTER_FREQ2])) | ||
| 2141 | return -EINVAL; | ||
| 2133 | break; | 2142 | break; |
| 2134 | default: | 2143 | default: |
| 2135 | return -EINVAL; | 2144 | return -EINVAL; |
| @@ -5677,6 +5686,11 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) · 3541 unmodified lines | |||
| 5677 | } | 5686 | } |
| 5678 | } | 5687 | } |
| 5679 | 5688 | ||
| 5689 | static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info) | ||
| 5690 | { | ||
| 5691 | return reg_reload_regdb(); | ||
| 5692 | } | ||
| 5693 | |||
| 5680 | static int nl80211_get_mesh_config(struct sk_buff *skb, | 5694 | static int nl80211_get_mesh_config(struct sk_buff *skb, |
| 5681 | struct genl_info *info) | 5695 | struct genl_info *info) |
| 5682 | { | 5696 | { |
| @@ -6618,6 +6632,77 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev) · 935 unmodified lines | |||
| 6618 | return regulatory_pre_cac_allowed(wdev->wiphy); | 6632 | return regulatory_pre_cac_allowed(wdev->wiphy); |
| 6619 | } | 6633 | } |
| 6620 | 6634 | ||
| 6635 | static int | ||
| 6636 | nl80211_check_scan_flags(struct wiphy *wiphy, struct wireless_dev *wdev, | ||
| 6637 | void *request, struct nlattr **attrs, | ||
| 6638 | bool is_sched_scan) | ||
| 6639 | { | ||
| 6640 | u8 *mac_addr, *mac_addr_mask; | ||
| 6641 | u32 *flags; | ||
| 6642 | enum nl80211_feature_flags randomness_flag; | ||
| 6643 | |||
| 6644 | if (!attrs[NL80211_ATTR_SCAN_FLAGS]) | ||
| 6645 | return 0; | ||
| 6646 | |||
| 6647 | if (is_sched_scan) { | ||
| 6648 | struct cfg80211_sched_scan_request *req = request; | ||
| 6649 | |||
| 6650 | randomness_flag = wdev ? | ||
| 6651 | NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR : | ||
| 6652 | NL80211_FEATURE_ND_RANDOM_MAC_ADDR; | ||
| 6653 | flags = &req->flags; | ||
| 6654 | mac_addr = req->mac_addr; | ||
| 6655 | mac_addr_mask = req->mac_addr_mask; | ||
| 6656 | } else { | ||
| 6657 | struct cfg80211_scan_request *req = request; | ||
| 6658 | |||
| 6659 | randomness_flag = NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; | ||
| 6660 | flags = &req->flags; | ||
| 6661 | mac_addr = req->mac_addr; | ||
| 6662 | mac_addr_mask = req->mac_addr_mask; | ||
| 6663 | } | ||
| 6664 | |||
| 6665 | *flags = nla_get_u32(attrs[NL80211_ATTR_SCAN_FLAGS]); | ||
| 6666 | |||
| 6667 | if ((*flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && | ||
| 6668 | !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) | ||
| 6669 | return -EOPNOTSUPP; | ||
| 6670 | |||
| 6671 | if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { | ||
| 6672 | int err; | ||
| 6673 | |||
| 6674 | if (!(wiphy->features & randomness_flag) || | ||
| 6675 | (wdev && wdev->current_bss)) | ||
| 6676 | return -EOPNOTSUPP; | ||
| 6677 | |||
| 6678 | err = nl80211_parse_random_mac(attrs, mac_addr, mac_addr_mask); | ||
| 6679 | if (err) | ||
| 6680 | return err; | ||
| 6681 | } | ||
| 6682 | |||
| 6683 | if ((*flags & NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME) && | ||
| 6684 | !wiphy_ext_feature_isset(wiphy, | ||
| 6685 | NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME)) | ||
| 6686 | return -EOPNOTSUPP; | ||
| 6687 | |||
| 6688 | if ((*flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP) && | ||
| 6689 | !wiphy_ext_feature_isset(wiphy, | ||
| 6690 | NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP)) | ||
| 6691 | return -EOPNOTSUPP; | ||
| 6692 | |||
| 6693 | if ((*flags & NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) && | ||
| 6694 | !wiphy_ext_feature_isset(wiphy, | ||
| 6695 | NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION)) | ||
| 6696 | return -EOPNOTSUPP; | ||
| 6697 | |||
| 6698 | if ((*flags & NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE) && | ||
| 6699 | !wiphy_ext_feature_isset(wiphy, | ||
| 6700 | NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE)) | ||
| 6701 | return -EOPNOTSUPP; | ||
| 6702 | |||
| 6703 | return 0; | ||
| 6704 | } | ||
| 6705 | |||
| 6621 | static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | 6706 | static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) |
| 6622 | { | 6707 | { |
| 6623 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6708 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| @@ -6823,34 +6908,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) · 199 unmodified lines | |||
| 6823 | nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]); | 6908 | nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]); |
| 6824 | } | 6909 | } |
| 6825 | 6910 | ||
| 6826 | if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { | 6911 | err = nl80211_check_scan_flags(wiphy, wdev, request, info->attrs, |
| 6827 | request->flags = nla_get_u32( | 6912 | false); |
| 6828 | info->attrs[NL80211_ATTR_SCAN_FLAGS]); | 6913 | if (err) |
| 6829 | if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && | 6914 | goto out_free; |
| 6830 | !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) { | ||
| 6831 | err = -EOPNOTSUPP; | ||
| 6832 | goto out_free; | ||
| 6833 | } | ||
| 6834 | |||
| 6835 | if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { | ||
| 6836 | if (!(wiphy->features & | ||
| 6837 | NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR)) { | ||
| 6838 | err = -EOPNOTSUPP; | ||
| 6839 | goto out_free; | ||
| 6840 | } | ||
| 6841 | |||
| 6842 | if (wdev->current_bss) { | ||
| 6843 | err = -EOPNOTSUPP; | ||
| 6844 | goto out_free; | ||
| 6845 | } | ||
| 6846 | |||
| 6847 | err = nl80211_parse_random_mac(info->attrs, | ||
| 6848 | request->mac_addr, | ||
| 6849 | request->mac_addr_mask); | ||
| 6850 | if (err) | ||
| 6851 | goto out_free; | ||
| 6852 | } | ||
| 6853 | } | ||
| 6854 | 6915 | ||
| 6855 | request->no_cck = | 6916 | request->no_cck = |
| 6856 | nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); | 6917 | nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); |
| @@ -7298,37 +7359,9 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, · 441 unmodified lines | |||
| 7298 | request->ie_len); | 7359 | request->ie_len); |
| 7299 | } | 7360 | } |
| 7300 | 7361 | ||
| 7301 | if (attrs[NL80211_ATTR_SCAN_FLAGS]) { | 7362 | err = nl80211_check_scan_flags(wiphy, wdev, request, attrs, true); |
| 7302 | request->flags = nla_get_u32( | 7363 | if (err) |
| 7303 | attrs[NL80211_ATTR_SCAN_FLAGS]); | 7364 | goto out_free; |
| 7304 | if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && | ||
| 7305 | !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) { | ||
| 7306 | err = -EOPNOTSUPP; | ||
| 7307 | goto out_free; | ||
| 7308 | } | ||
| 7309 | |||
| 7310 | if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { | ||
| 7311 | u32 flg = NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR; | ||
| 7312 | |||
| 7313 | if (!wdev) /* must be net-detect */ | ||
| 7314 | flg = NL80211_FEATURE_ND_RANDOM_MAC_ADDR; | ||
| 7315 | |||
| 7316 | if (!(wiphy->features & flg)) { | ||
| 7317 | err = -EOPNOTSUPP; | ||
| 7318 | goto out_free; | ||
| 7319 | } | ||
| 7320 | |||
| 7321 | if (wdev && wdev->current_bss) { | ||
| 7322 | err = -EOPNOTSUPP; | ||
| 7323 | goto out_free; | ||
| 7324 | } | ||
| 7325 | |||
| 7326 | err = nl80211_parse_random_mac(attrs, request->mac_addr, | ||
| 7327 | request->mac_addr_mask); | ||
| 7328 | if (err) | ||
| 7329 | goto out_free; | ||
| 7330 | } | ||
| 7331 | } | ||
| 7332 | 7365 | ||
| 7333 | if (attrs[NL80211_ATTR_SCHED_SCAN_DELAY]) | 7366 | if (attrs[NL80211_ATTR_SCHED_SCAN_DELAY]) |
| 7334 | request->delay = | 7367 | request->delay = |
| @@ -8932,8 +8965,14 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) · 1597 unmodified lines | |||
| 8932 | 8965 | ||
| 8933 | if (info->attrs[NL80211_ATTR_USE_MFP]) { | 8966 | if (info->attrs[NL80211_ATTR_USE_MFP]) { |
| 8934 | connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); | 8967 | connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); |
| 8968 | if (connect.mfp == NL80211_MFP_OPTIONAL && | ||
| 8969 | !wiphy_ext_feature_isset(&rdev->wiphy, | ||
| 8970 | NL80211_EXT_FEATURE_MFP_OPTIONAL)) | ||
| 8971 | return -EOPNOTSUPP; | ||
| 8972 | |||
| 8935 | if (connect.mfp != NL80211_MFP_REQUIRED && | 8973 | if (connect.mfp != NL80211_MFP_REQUIRED && |
| 8936 | connect.mfp != NL80211_MFP_NO) | 8974 | connect.mfp != NL80211_MFP_NO && |
| 8975 | connect.mfp != NL80211_MFP_OPTIONAL) | ||
| 8937 | return -EINVAL; | 8976 | return -EINVAL; |
| 8938 | } else { | 8977 | } else { |
| 8939 | connect.mfp = NL80211_MFP_NO; | 8978 | connect.mfp = NL80211_MFP_NO; |
| @@ -12684,6 +12723,12 @@ static const struct genl_ops nl80211_ops[] = { · 3744 unmodified lines | |||
| 12684 | .policy = nl80211_policy, | 12723 | .policy = nl80211_policy, |
| 12685 | .flags = GENL_ADMIN_PERM, | 12724 | .flags = GENL_ADMIN_PERM, |
| 12686 | }, | 12725 | }, |
| 12726 | { | ||
| 12727 | .cmd = NL80211_CMD_RELOAD_REGDB, | ||
| 12728 | .doit = nl80211_reload_regdb, | ||
| 12729 | .policy = nl80211_policy, | ||
| 12730 | .flags = GENL_ADMIN_PERM, | ||
| 12731 | }, | ||
| 12687 | { | 12732 | { |
| 12688 | .cmd = NL80211_CMD_GET_MESH_CONFIG, | 12733 | .cmd = NL80211_CMD_GET_MESH_CONFIG, |
| 12689 | .doit = nl80211_get_mesh_config, | 12734 | .doit = nl80211_get_mesh_config, |
| @@ -13812,9 +13857,7 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev, · 1122 unmodified lines | |||
| 13812 | info->req_ie)) || | 13857 | info->req_ie)) || |
| 13813 | (info->resp_ie && | 13858 | (info->resp_ie && |
| 13814 | nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len, | 13859 | nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len, |
| 13815 | info->resp_ie)) || | 13860 | info->resp_ie))) |
| 13816 | (info->authorized && | ||
| 13817 | nla_put_flag(msg, NL80211_ATTR_PORT_AUTHORIZED))) | ||
| 13818 | goto nla_put_failure; | 13861 | goto nla_put_failure; |
| 13819 | 13862 | ||
| 13820 | genlmsg_end(msg, hdr); | 13863 | genlmsg_end(msg, hdr); |
| @@ -13828,6 +13871,36 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev, · 7 unmodified lines | |||
| 13828 | nlmsg_free(msg); | 13871 | nlmsg_free(msg); |
| 13829 | } | 13872 | } |
| 13830 | 13873 | ||
| 13874 | void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev, | ||
| 13875 | struct net_device *netdev, const u8 *bssid) | ||
| 13876 | { | ||
| 13877 | struct sk_buff *msg; | ||
| 13878 | void *hdr; | ||
| 13879 | |||
| 13880 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 13881 | if (!msg) | ||
| 13882 | return; | ||
| 13883 | |||
| 13884 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PORT_AUTHORIZED); | ||
| 13885 | if (!hdr) { | ||
| 13886 | nlmsg_free(msg); | ||
| 13887 | return; | ||
| 13888 | } | ||
| 13889 | |||
| 13890 | if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) | ||
| 13891 | goto nla_put_failure; | ||
| 13892 | |||
| 13893 | genlmsg_end(msg, hdr); | ||
| 13894 | |||
| 13895 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, | ||
| 13896 | NL80211_MCGRP_MLME, GFP_KERNEL); | ||
| 13897 | return; | ||
| 13898 | |||
| 13899 | nla_put_failure: | ||
| 13900 | genlmsg_cancel(msg, hdr); | ||
| 13901 | nlmsg_free(msg); | ||
| 13902 | } | ||
| 13903 | |||
| 13831 | void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, | 13904 | void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, |
| 13832 | struct net_device *netdev, u16 reason, | 13905 | struct net_device *netdev, u16 reason, |
| 13833 | const u8 *ie, size_t ie_len, bool from_ap) | 13906 | const u8 *ie, size_t ie_len, bool from_ap) |
| @@ -58,6 +58,8 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, · 57 unmodified lines | |||
| 58 | void nl80211_send_roamed(struct cfg80211_registered_device *rdev, | 58 | void nl80211_send_roamed(struct cfg80211_registered_device *rdev, |
| 59 | struct net_device *netdev, | 59 | struct net_device *netdev, |
| 60 | struct cfg80211_roam_info *info, gfp_t gfp); | 60 | struct cfg80211_roam_info *info, gfp_t gfp); |
| 61 | void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev, | ||
| 62 | struct net_device *netdev, const u8 *bssid); | ||
| 61 | void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, | 63 | void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, |
| 62 | struct net_device *netdev, u16 reason, | 64 | struct net_device *netdev, u16 reason, |
| 63 | const u8 *ie, size_t ie_len, bool from_ap); | 65 | const u8 *ie, size_t ie_len, bool from_ap); |
| @@ -53,12 +53,13 @@ · 52 unmodified lines | |||
| 53 | #include <linux/ctype.h> | 53 | #include <linux/ctype.h> |
| 54 | #include <linux/nl80211.h> | 54 | #include <linux/nl80211.h> |
| 55 | #include <linux/platform_device.h> | 55 | #include <linux/platform_device.h> |
| 56 | #include <linux/verification.h> | ||
| 56 | #include <linux/moduleparam.h> | 57 | #include <linux/moduleparam.h> |
| 58 | #include <linux/firmware.h> | ||
| 57 | #include <net/cfg80211.h> | 59 | #include <net/cfg80211.h> |
| 58 | #include "core.h" | 60 | #include "core.h" |
| 59 | #include "reg.h" | 61 | #include "reg.h" |
| 60 | #include "rdev-ops.h" | 62 | #include "rdev-ops.h" |
| 61 | #include "regdb.h" | ||
| 62 | #include "nl80211.h" | 63 | #include "nl80211.h" |
| 63 | 64 | ||
| 64 | /* | 65 | /* |
| @@ -100,7 +101,7 @@ static struct regulatory_request core_request_world = { · 35 unmodified lines | |||
| 100 | static struct regulatory_request __rcu *last_request = | 101 | static struct regulatory_request __rcu *last_request = |
| 101 | (void __force __rcu *)&core_request_world; | 102 | (void __force __rcu *)&core_request_world; |
| 102 | 103 | ||
| 103 | /* To trigger userspace events */ | 104 | /* To trigger userspace events and load firmware */ |
| 104 | static struct platform_device *reg_pdev; | 105 | static struct platform_device *reg_pdev; |
| 105 | 106 | ||
| 106 | /* | 107 | /* |
| @@ -443,7 +444,6 @@ reg_copy_regd(const struct ieee80211_regdomain *src_regd) · 336 unmodified lines | |||
| 443 | return regd; | 444 | return regd; |
| 444 | } | 445 | } |
| 445 | 446 | ||
| 446 | #ifdef CONFIG_CFG80211_INTERNAL_REGDB | ||
| 447 | struct reg_regdb_apply_request { | 447 | struct reg_regdb_apply_request { |
| 448 | struct list_head list; | 448 | struct list_head list; |
| 449 | const struct ieee80211_regdomain *regdom; | 449 | const struct ieee80211_regdomain *regdom; |
| @@ -475,55 +475,26 @@ static void reg_regdb_apply(struct work_struct *work) · 25 unmodified lines | |||
| 475 | 475 | ||
| 476 | static DECLARE_WORK(reg_regdb_work, reg_regdb_apply); | 476 | static DECLARE_WORK(reg_regdb_work, reg_regdb_apply); |
| 477 | 477 | ||
| 478 | static int reg_query_builtin(const char *alpha2) | 478 | static int reg_schedule_apply(const struct ieee80211_regdomain *regdom) |
| 479 | { | 479 | { |
| 480 | const struct ieee80211_regdomain *regdom = NULL; | ||
| 481 | struct reg_regdb_apply_request *request; | 480 | struct reg_regdb_apply_request *request; |
| 482 | unsigned int i; | ||
| 483 | |||
| 484 | for (i = 0; i < reg_regdb_size; i++) { | ||
| 485 | if (alpha2_equal(alpha2, reg_regdb[i]->alpha2)) { | ||
| 486 | regdom = reg_regdb[i]; | ||
| 487 | break; | ||
| 488 | } | ||
| 489 | } | ||
| 490 | |||
| 491 | if (!regdom) | ||
| 492 | return -ENODATA; | ||
| 493 | 481 | ||
| 494 | request = kzalloc(sizeof(struct reg_regdb_apply_request), GFP_KERNEL); | 482 | request = kzalloc(sizeof(struct reg_regdb_apply_request), GFP_KERNEL); |
| 495 | if (!request) | 483 | if (!request) { |
| 496 | return -ENOMEM; | 484 | kfree(regdom); |
| 497 | |||
| 498 | request->regdom = reg_copy_regd(regdom); | ||
| 499 | if (IS_ERR_OR_NULL(request->regdom)) { | ||
| 500 | kfree(request); | ||
| 501 | return -ENOMEM; | 485 | return -ENOMEM; |
| 502 | } | 486 | } |
| 503 | 487 | ||
| 488 | request->regdom = regdom; | ||
| 489 | |||
| 504 | mutex_lock(®_regdb_apply_mutex); | 490 | mutex_lock(®_regdb_apply_mutex); |
| 505 | list_add_tail(&request->list, ®_regdb_apply_list); | 491 | list_add_tail(&request->list, ®_regdb_apply_list); |
| 506 | mutex_unlock(®_regdb_apply_mutex); | 492 | mutex_unlock(®_regdb_apply_mutex); |
| 507 | 493 | ||
| 508 | schedule_work(®_regdb_work); | 494 | schedule_work(®_regdb_work); |
| 509 | |||
| 510 | return 0; | 495 | return 0; |
| 511 | } | 496 | } |
| 512 | 497 | ||
| 513 | /* Feel free to add any other sanity checks here */ | ||
| 514 | static void reg_regdb_size_check(void) | ||
| 515 | { | ||
| 516 | /* We should ideally BUILD_BUG_ON() but then random builds would fail */ | ||
| 517 | WARN_ONCE(!reg_regdb_size, "db.txt is empty, you should update it..."); | ||
| 518 | } | ||
| 519 | #else | ||
| 520 | static inline void reg_regdb_size_check(void) {} | ||
| 521 | static inline int reg_query_builtin(const char *alpha2) | ||
| 522 | { | ||
| 523 | return -ENODATA; | ||
| 524 | } | ||
| 525 | #endif /* CONFIG_CFG80211_INTERNAL_REGDB */ | ||
| 526 | |||
| 527 | #ifdef CONFIG_CFG80211_CRDA_SUPPORT | 498 | #ifdef CONFIG_CFG80211_CRDA_SUPPORT |
| 528 | /* Max number of consecutive attempts to communicate with CRDA */ | 499 | /* Max number of consecutive attempts to communicate with CRDA */ |
| 529 | #define REG_MAX_CRDA_TIMEOUTS 10 | 500 | #define REG_MAX_CRDA_TIMEOUTS 10 |
| @@ -599,10 +570,402 @@ static inline int call_crda(const char *alpha2) · 69 unmodified lines | |||
| 599 | } | 570 | } |
| 600 | #endif /* CONFIG_CFG80211_CRDA_SUPPORT */ | 571 | #endif /* CONFIG_CFG80211_CRDA_SUPPORT */ |
| 601 | 572 | ||
| 573 | /* code to directly load a firmware database through request_firmware */ | ||
| 574 | static const struct fwdb_header *regdb; | ||
| 575 | |||
| 576 | struct fwdb_country { | ||
| 577 | u8 alpha2[2]; | ||
| 578 | __be16 coll_ptr; | ||
| 579 | /* this struct cannot be extended */ | ||
| 580 | } __packed __aligned(4); | ||
| 581 | |||
| 582 | struct fwdb_collection { | ||
| 583 | u8 len; | ||
| 584 | u8 n_rules; | ||
| 585 | u8 dfs_region; | ||
| 586 | /* no optional data yet */ | ||
| 587 | /* aligned to 2, then followed by __be16 array of rule pointers */ | ||
| 588 | } __packed __aligned(4); | ||
| 589 | |||
| 590 | enum fwdb_flags { | ||
| 591 | FWDB_FLAG_NO_OFDM = BIT(0), | ||
| 592 | FWDB_FLAG_NO_OUTDOOR = BIT(1), | ||
| 593 | FWDB_FLAG_DFS = BIT(2), | ||
| 594 | FWDB_FLAG_NO_IR = BIT(3), | ||
| 595 | FWDB_FLAG_AUTO_BW = BIT(4), | ||
| 596 | }; | ||
| 597 | |||
| 598 | struct fwdb_rule { | ||
| 599 | u8 len; | ||
| 600 | u8 flags; | ||
| 601 | __be16 max_eirp; | ||
| 602 | __be32 start, end, max_bw; | ||
| 603 | /* start of optional data */ | ||
| 604 | __be16 cac_timeout; | ||
| 605 | } __packed __aligned(4); | ||
| 606 | |||
| 607 | #define FWDB_MAGIC 0x52474442 | ||
| 608 | #define FWDB_VERSION 20 | ||
| 609 | |||
| 610 | struct fwdb_header { | ||
| 611 | __be32 magic; | ||
| 612 | __be32 version; | ||
| 613 | struct fwdb_country country[]; | ||
| 614 | } __packed __aligned(4); | ||
| 615 | |||
| 616 | static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr) | ||
| 617 | { | ||
| 618 | struct fwdb_rule *rule = (void *)(data + (rule_ptr << 2)); | ||
| 619 | |||
| 620 | if ((u8 *)rule + sizeof(rule->len) > data + size) | ||
| 621 | return false; | ||
| 622 | |||
| 623 | /* mandatory fields */ | ||
| 624 | if (rule->len < offsetofend(struct fwdb_rule, max_bw)) | ||
| 625 | return false; | ||
| 626 | |||
| 627 | return true; | ||
| 628 | } | ||
| 629 | |||
| 630 | static bool valid_country(const u8 *data, unsigned int size, | ||
| 631 | const struct fwdb_country *country) | ||
| 632 | { | ||
| 633 | unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2; | ||
| 634 | struct fwdb_collection *coll = (void *)(data + ptr); | ||
| 635 | __be16 *rules_ptr; | ||
| 636 | unsigned int i; | ||
| 637 | |||
| 638 | /* make sure we can read len/n_rules */ | ||
| 639 | if ((u8 *)coll + offsetofend(typeof(*coll), n_rules) > data + size) | ||
| 640 | return false; | ||
| 641 | |||
| 642 | /* make sure base struct and all rules fit */ | ||
| 643 | if ((u8 *)coll + ALIGN(coll->len, 2) + | ||
| 644 | (coll->n_rules * 2) > data + size) | ||
| 645 | return false; | ||
| 646 | |||
| 647 | /* mandatory fields must exist */ | ||
| 648 | if (coll->len < offsetofend(struct fwdb_collection, dfs_region)) | ||
| 649 | return false; | ||
| 650 | |||
| 651 | rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2)); | ||
| 652 | |||
| 653 | for (i = 0; i < coll->n_rules; i++) { | ||
| 654 | u16 rule_ptr = be16_to_cpu(rules_ptr[i]); | ||
| 655 | |||
| 656 | if (!valid_rule(data, size, rule_ptr)) | ||
| 657 | return false; | ||
| 658 | } | ||
| 659 | |||
| 660 | return true; | ||
| 661 | } | ||
| 662 | |||
| 663 | #ifdef CONFIG_CFG80211_REQUIRE_SIGNED_REGDB | ||
| 664 | static struct key *builtin_regdb_keys; | ||
| 665 | |||
| 666 | static void __init load_keys_from_buffer(const u8 *p, unsigned int buflen) | ||
| 667 | { | ||
| 668 | const u8 *end = p + buflen; | ||
| 669 | size_t plen; | ||
| 670 | key_ref_t key; | ||
| 671 | |||
| 672 | while (p < end) { | ||
| 673 | /* Each cert begins with an ASN.1 SEQUENCE tag and must be more | ||
| 674 | * than 256 bytes in size. | ||
| 675 | */ | ||
| 676 | if (end - p < 4) | ||
| 677 | goto dodgy_cert; | ||
| 678 | if (p[0] != 0x30 && | ||
| 679 | p[1] != 0x82) | ||
| 680 | goto dodgy_cert; | ||
| 681 | plen = (p[2] << 8) | p[3]; | ||
| 682 | plen += 4; | ||
| 683 | if (plen > end - p) | ||
| 684 | goto dodgy_cert; | ||
| 685 | |||
| 686 | key = key_create_or_update(make_key_ref(builtin_regdb_keys, 1), | ||
| 687 | "asymmetric", NULL, p, plen, | ||
| 688 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
| 689 | KEY_USR_VIEW | KEY_USR_READ), | ||
| 690 | KEY_ALLOC_NOT_IN_QUOTA | | ||
| 691 | KEY_ALLOC_BUILT_IN | | ||
| 692 | KEY_ALLOC_BYPASS_RESTRICTION); | ||
| 693 | if (IS_ERR(key)) { | ||
| 694 | pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", | ||
| 695 | PTR_ERR(key)); | ||
| 696 | } else { | ||
| 697 | pr_notice("Loaded X.509 cert '%s'\n", | ||
| 698 | key_ref_to_ptr(key)->description); | ||
| 699 | key_ref_put(key); | ||
| 700 | } | ||
| 701 | p += plen; | ||
| 702 | } | ||
| 703 | |||
| 704 | return; | ||
| 705 | |||
| 706 | dodgy_cert: | ||
| 707 | pr_err("Problem parsing in-kernel X.509 certificate list\n"); | ||
| 708 | } | ||
| 709 | |||
| 710 | static int __init load_builtin_regdb_keys(void) | ||
| 711 | { | ||
| 712 | builtin_regdb_keys = | ||
| 713 | keyring_alloc(".builtin_regdb_keys", | ||
| 714 | KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), | ||
| 715 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
| 716 | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH), | ||
| 717 | KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); | ||
| 718 | if (IS_ERR(builtin_regdb_keys)) | ||
| 719 | return PTR_ERR(builtin_regdb_keys); | ||
| 720 | |||
| 721 | pr_notice("Loading compiled-in X.509 certificates for regulatory database\n"); | ||
| 722 | |||
| 723 | #ifdef CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS | ||
| 724 | load_keys_from_buffer(shipped_regdb_certs, shipped_regdb_certs_len); | ||
| 725 | #endif | ||
| 726 | #ifdef CFG80211_EXTRA_REGDB_KEYDIR | ||
| 727 | if (CONFIG_CFG80211_EXTRA_REGDB_KEYDIR[0] != '\0') | ||
| 728 | load_keys_from_buffer(extra_regdb_certs, extra_regdb_certs_len); | ||
| 729 | #endif | ||
| 730 | |||
| 731 | return 0; | ||
| 732 | } | ||
| 733 | |||
| 734 | static bool regdb_has_valid_signature(const u8 *data, unsigned int size) | ||
| 735 | { | ||
| 736 | const struct firmware *sig; | ||
| 737 | bool result; | ||
| 738 | |||
| 739 | if (request_firmware(&sig, "regulatory.db.p7s", ®_pdev->dev)) | ||
| 740 | return false; | ||
| 741 | |||
| 742 | result = verify_pkcs7_signature(data, size, sig->data, sig->size, | ||
| 743 | builtin_regdb_keys, | ||
| 744 | VERIFYING_UNSPECIFIED_SIGNATURE, | ||
| 745 | NULL, NULL) == 0; | ||
| 746 | |||
| 747 | release_firmware(sig); | ||
| 748 | |||
| 749 | return result; | ||
| 750 | } | ||
| 751 | |||
| 752 | static void free_regdb_keyring(void) | ||
| 753 | { | ||
| 754 | key_put(builtin_regdb_keys); | ||
| 755 | } | ||
| 756 | #else | ||
| 757 | static int load_builtin_regdb_keys(void) | ||
| 758 | { | ||
| 759 | return 0; | ||
| 760 | } | ||
| 761 | |||
| 762 | static bool regdb_has_valid_signature(const u8 *data, unsigned int size) | ||
| 763 | { | ||
| 764 | return true; | ||
| 765 | } | ||
| 766 | |||
| 767 | static void free_regdb_keyring(void) | ||
| 768 | { | ||
| 769 | } | ||
| 770 | #endif /* CONFIG_CFG80211_REQUIRE_SIGNED_REGDB */ | ||
| 771 | |||
| 772 | static bool valid_regdb(const u8 *data, unsigned int size) | ||
| 773 | { | ||
| 774 | const struct fwdb_header *hdr = (void *)data; | ||
| 775 | const struct fwdb_country *country; | ||
| 776 | |||
| 777 | if (size < sizeof(*hdr)) | ||
| 778 | return false; | ||
| 779 | |||
| 780 | if (hdr->magic != cpu_to_be32(FWDB_MAGIC)) | ||
| 781 | return false; | ||
| 782 | |||
| 783 | if (hdr->version != cpu_to_be32(FWDB_VERSION)) | ||
| 784 | return false; | ||
| 785 | |||
| 786 | if (!regdb_has_valid_signature(data, size)) | ||
| 787 | return false; | ||
| 788 | |||
| 789 | country = &hdr->country[0]; | ||
| 790 | while ((u8 *)(country + 1) <= data + size) { | ||
| 791 | if (!country->coll_ptr) | ||
| 792 | break; | ||
| 793 | if (!valid_country(data, size, country)) | ||
| 794 | return false; | ||
| 795 | country++; | ||
| 796 | } | ||
| 797 | |||
| 798 | return true; | ||
| 799 | } | ||
| 800 | |||
| 801 | static int regdb_query_country(const struct fwdb_header *db, | ||
| 802 | const struct fwdb_country *country) | ||
| 803 | { | ||
| 804 | unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2; | ||
| 805 | struct fwdb_collection *coll = (void *)((u8 *)db + ptr); | ||
| 806 | struct ieee80211_regdomain *regdom; | ||
| 807 | unsigned int size_of_regd; | ||
| 808 | unsigned int i; | ||
| 809 | |||
| 810 | size_of_regd = | ||
| 811 | sizeof(struct ieee80211_regdomain) + | ||
| 812 | coll->n_rules * sizeof(struct ieee80211_reg_rule); | ||
| 813 | |||
| 814 | regdom = kzalloc(size_of_regd, GFP_KERNEL); | ||
| 815 | if (!regdom) | ||
| 816 | return -ENOMEM; | ||
| 817 | |||
| 818 | regdom->n_reg_rules = coll->n_rules; | ||
| 819 | regdom->alpha2[0] = country->alpha2[0]; | ||
| 820 | regdom->alpha2[1] = country->alpha2[1]; | ||
| 821 | regdom->dfs_region = coll->dfs_region; | ||
| 822 | |||
| 823 | for (i = 0; i < regdom->n_reg_rules; i++) { | ||
| 824 | __be16 *rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2)); | ||
| 825 | unsigned int rule_ptr = be16_to_cpu(rules_ptr[i]) << 2; | ||
| 826 | struct fwdb_rule *rule = (void *)((u8 *)db + rule_ptr); | ||
| 827 | struct ieee80211_reg_rule *rrule = ®dom->reg_rules[i]; | ||
| 828 | |||
| 829 | rrule->freq_range.start_freq_khz = be32_to_cpu(rule->start); | ||
| 830 | rrule->freq_range.end_freq_khz = be32_to_cpu(rule->end); | ||
| 831 | rrule->freq_range.max_bandwidth_khz = be32_to_cpu(rule->max_bw); | ||
| 832 | |||
| 833 | rrule->power_rule.max_antenna_gain = 0; | ||
| 834 | rrule->power_rule.max_eirp = be16_to_cpu(rule->max_eirp); | ||
| 835 | |||
| 836 | rrule->flags = 0; | ||
| 837 | if (rule->flags & FWDB_FLAG_NO_OFDM) | ||
| 838 | rrule->flags |= NL80211_RRF_NO_OFDM; | ||
| 839 | if (rule->flags & FWDB_FLAG_NO_OUTDOOR) | ||
| 840 | rrule->flags |= NL80211_RRF_NO_OUTDOOR; | ||
| 841 | if (rule->flags & FWDB_FLAG_DFS) | ||
| 842 | rrule->flags |= NL80211_RRF_DFS; | ||
| 843 | if (rule->flags & FWDB_FLAG_NO_IR) | ||
| 844 | rrule->flags |= NL80211_RRF_NO_IR; | ||
| 845 | if (rule->flags & FWDB_FLAG_AUTO_BW) | ||
| 846 | rrule->flags |= NL80211_RRF_AUTO_BW; | ||
| 847 | |||
| 848 | rrule->dfs_cac_ms = 0; | ||
| 849 | |||
| 850 | /* handle optional data */ | ||
| 851 | if (rule->len >= offsetofend(struct fwdb_rule, cac_timeout)) | ||
| 852 | rrule->dfs_cac_ms = | ||
| 853 | 1000 * be16_to_cpu(rule->cac_timeout); | ||
| 854 | } | ||
| 855 | |||
| 856 | return reg_schedule_apply(regdom); | ||
| 857 | } | ||
| 858 | |||
| 859 | static int query_regdb(const char *alpha2) | ||
| 860 | { | ||
| 861 | const struct fwdb_header *hdr = regdb; | ||
| 862 | const struct fwdb_country *country; | ||
| 863 | |||
| 864 | ASSERT_RTNL(); | ||
| 865 | |||
| 866 | if (IS_ERR(regdb)) | ||
| 867 | return PTR_ERR(regdb); | ||
| 868 | |||
| 869 | country = &hdr->country[0]; | ||
| 870 | while (country->coll_ptr) { | ||
| 871 | if (alpha2_equal(alpha2, country->alpha2)) | ||
| 872 | return regdb_query_country(regdb, country); | ||
| 873 | country++; | ||
| 874 | } | ||
| 875 | |||
| 876 | return -ENODATA; | ||
| 877 | } | ||
| 878 | |||
| 879 | static void regdb_fw_cb(const struct firmware *fw, void *context) | ||
| 880 | { | ||
| 881 | int set_error = 0; | ||
| 882 | bool restore = true; | ||
| 883 | void *db; | ||
| 884 | |||
| 885 | if (!fw) { | ||
| 886 | pr_info("failed to load regulatory.db\n"); | ||
| 887 | set_error = -ENODATA; | ||
| 888 | } else if (!valid_regdb(fw->data, fw->size)) { | ||
| 889 | pr_info("loaded regulatory.db is malformed or signature is missing/invalid\n"); | ||
| 890 | set_error = -EINVAL; | ||
| 891 | } | ||
| 892 | |||
| 893 | rtnl_lock(); | ||
| 894 | if (WARN_ON(regdb && !IS_ERR(regdb))) { | ||
| 895 | /* just restore and free new db */ | ||
| 896 | } else if (set_error) { | ||
| 897 | regdb = ERR_PTR(set_error); | ||
| 898 | } else if (fw) { | ||
| 899 | db = kmemdup(fw->data, fw->size, GFP_KERNEL); | ||
| 900 | if (db) { | ||
| 901 | regdb = db; | ||
| 902 | restore = context && query_regdb(context); | ||
| 903 | } else { | ||
| 904 | restore = true; | ||
| 905 | } | ||
| 906 | } | ||
| 907 | |||
| 908 | if (restore) | ||
| 909 | restore_regulatory_settings(true); | ||
| 910 | |||
| 911 | rtnl_unlock(); | ||
| 912 | |||
| 913 | kfree(context); | ||
| 914 | |||
| 915 | release_firmware(fw); | ||
| 916 | } | ||
| 917 | |||
| 918 | static int query_regdb_file(const char *alpha2) | ||
| 919 | { | ||
| 920 | ASSERT_RTNL(); | ||
| 921 | |||
| 922 | if (regdb) | ||
| 923 | return query_regdb(alpha2); | ||
| 924 | |||
| 925 | alpha2 = kmemdup(alpha2, 2, GFP_KERNEL); | ||
| 926 | if (!alpha2) | ||
| 927 | return -ENOMEM; | ||
| 928 | |||
| 929 | return request_firmware_nowait(THIS_MODULE, true, "regulatory.db", | ||
| 930 | ®_pdev->dev, GFP_KERNEL, | ||
| 931 | (void *)alpha2, regdb_fw_cb); | ||
| 932 | } | ||
| 933 | |||
| 934 | int reg_reload_regdb(void) | ||
| 935 | { | ||
| 936 | const struct firmware *fw; | ||
| 937 | void *db; | ||
| 938 | int err; | ||
| 939 | |||
| 940 | err = request_firmware(&fw, "regulatory.db", ®_pdev->dev); | ||
| 941 | if (err) | ||
| 942 | return err; | ||
| 943 | |||
| 944 | if (!valid_regdb(fw->data, fw->size)) { | ||
| 945 | err = -ENODATA; | ||
| 946 | goto out; | ||
| 947 | } | ||
| 948 | |||
| 949 | db = kmemdup(fw->data, fw->size, GFP_KERNEL); | ||
| 950 | if (!db) { | ||
| 951 | err = -ENOMEM; | ||
| 952 | goto out; | ||
| 953 | } | ||
| 954 | |||
| 955 | rtnl_lock(); | ||
| 956 | if (!IS_ERR_OR_NULL(regdb)) | ||
| 957 | kfree(regdb); | ||
| 958 | regdb = db; | ||
| 959 | rtnl_unlock(); | ||
| 960 | |||
| 961 | out: | ||
| 962 | release_firmware(fw); | ||
| 963 | return err; | ||
| 964 | } | ||
| 965 | |||
| 602 | static bool reg_query_database(struct regulatory_request *request) | 966 | static bool reg_query_database(struct regulatory_request *request) |
| 603 | { | 967 | { |
| 604 | /* query internal regulatory database (if it exists) */ | 968 | if (query_regdb_file(request->alpha2) == 0) |
| 605 | if (reg_query_builtin(request->alpha2) == 0) | ||
| 606 | return true; | 969 | return true; |
| 607 | 970 | ||
| 608 | if (call_crda(request->alpha2) == 0) | 971 | if (call_crda(request->alpha2) == 0) |
| @@ -3285,6 +3648,10 @@ int __init regulatory_init(void) · 2676 unmodified lines | |||
| 3285 | { | 3648 | { |
| 3286 | int err = 0; | 3649 | int err = 0; |
| 3287 | 3650 | ||
| 3651 | err = load_builtin_regdb_keys(); | ||
| 3652 | if (err) | ||
| 3653 | return err; | ||
| 3654 | |||
| 3288 | reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); | 3655 | reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); |
| 3289 | if (IS_ERR(reg_pdev)) | 3656 | if (IS_ERR(reg_pdev)) |
| 3290 | return PTR_ERR(reg_pdev); | 3657 | return PTR_ERR(reg_pdev); |
| @@ -3293,8 +3660,6 @@ int __init regulatory_init(void) · 2 unmodified lines | |||
| 3293 | spin_lock_init(®_pending_beacons_lock); | 3660 | spin_lock_init(®_pending_beacons_lock); |
| 3294 | spin_lock_init(®_indoor_lock); | 3661 | spin_lock_init(®_indoor_lock); |
| 3295 | 3662 | ||
| 3296 | reg_regdb_size_check(); | ||
| 3297 | |||
| 3298 | rcu_assign_pointer(cfg80211_regdomain, cfg80211_world_regdom); | 3663 | rcu_assign_pointer(cfg80211_regdomain, cfg80211_world_regdom); |
| 3299 | 3664 | ||
| 3300 | user_alpha2[0] = '9'; | 3665 | user_alpha2[0] = '9'; |
| @@ -3360,4 +3725,9 @@ void regulatory_exit(void) · 59 unmodified lines | |||
| 3360 | list_del(®_request->list); | 3725 | list_del(®_request->list); |
| 3361 | kfree(reg_request); | 3726 | kfree(reg_request); |
| 3362 | } | 3727 | } |
| 3728 | |||
| 3729 | if (!IS_ERR_OR_NULL(regdb)) | ||
| 3730 | kfree(regdb); | ||
| 3731 | |||
| 3732 | free_regdb_keyring(); | ||
| 3363 | } | 3733 | } |
| @@ -1,5 +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 | |||
| 4 | #include <net/cfg80211.h> | ||
| 5 | |||
| 3 | /* | 6 | /* |
| 4 | * Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com> | 7 | * Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com> |
| 5 | * | 8 | * |
| @@ -179,4 +182,15 @@ void regulatory_propagate_dfs_state(struct wiphy *wiphy, · 173 unmodified lines | |||
| 179 | * @wiphy2 - wiphy it's dfs_region to be checked against that of wiphy1 | 182 | * @wiphy2 - wiphy it's dfs_region to be checked against that of wiphy1 |
| 180 | */ | 183 | */ |
| 181 | bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2); | 184 | bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2); |
| 185 | |||
| 186 | /** | ||
| 187 | * reg_reload_regdb - reload the regulatory.db firmware file | ||
| 188 | */ | ||
| 189 | int reg_reload_regdb(void); | ||
| 190 | |||
| 191 | extern const u8 shipped_regdb_certs[]; | ||
| 192 | extern unsigned int shipped_regdb_certs_len; | ||
| 193 | extern const u8 extra_regdb_certs[]; | ||
| 194 | extern unsigned int extra_regdb_certs_len; | ||
| 195 | |||
| 182 | #endif /* __NET_WIRELESS_REG_H */ | 196 | #endif /* __NET_WIRELESS_REG_H */ |
| @@ -1,23 +0,0 @@ | |||
| 1 | #ifndef __REGDB_H__ | ||
| 2 | #define __REGDB_H__ | ||
| 3 | |||
| 4 | /* | ||
| 5 | * Copyright 2009 John W. Linville <linville@tuxdriver.com> | ||
| 6 | * | ||
| 7 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 8 | * purpose with or without fee is hereby granted, provided that the above | ||
| 9 | * copyright notice and this permission notice appear in all copies. | ||
| 10 | * | ||
| 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 18 | */ | ||
| 19 | |||
| 20 | extern const struct ieee80211_regdomain *reg_regdb[]; | ||
| 21 | extern int reg_regdb_size; | ||
| 22 | |||
| 23 | #endif /* __REGDB_H__ */ | ||
| @@ -960,7 +960,6 @@ void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info, · 959 unmodified lines | |||
| 960 | ev->rm.resp_ie_len = info->resp_ie_len; | 960 | ev->rm.resp_ie_len = info->resp_ie_len; |
| 961 | memcpy((void *)ev->rm.resp_ie, info->resp_ie, info->resp_ie_len); | 961 | memcpy((void *)ev->rm.resp_ie, info->resp_ie, info->resp_ie_len); |
| 962 | ev->rm.bss = info->bss; | 962 | ev->rm.bss = info->bss; |
| 963 | ev->rm.authorized = info->authorized; | ||
| 964 | 963 | ||
| 965 | spin_lock_irqsave(&wdev->event_lock, flags); | 964 | spin_lock_irqsave(&wdev->event_lock, flags); |
| 966 | list_add_tail(&ev->list, &wdev->event_list); | 965 | list_add_tail(&ev->list, &wdev->event_list); |
| @@ -969,6 +968,50 @@ void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info, · 2 unmodified lines | |||
| 969 | } | 968 | } |
| 970 | EXPORT_SYMBOL(cfg80211_roamed); | 969 | EXPORT_SYMBOL(cfg80211_roamed); |
| 971 | 970 | ||
| 971 | void __cfg80211_port_authorized(struct wireless_dev *wdev, const u8 *bssid) | ||
| 972 | { | ||
| 973 | ASSERT_WDEV_LOCK(wdev); | ||
| 974 | |||
| 975 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) | ||
| 976 | return; | ||
| 977 | |||
| 978 | if (WARN_ON(!wdev->current_bss) || | ||
| 979 | WARN_ON(!ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) | ||
| 980 | return; | ||
| 981 | |||
| 982 | nl80211_send_port_authorized(wiphy_to_rdev(wdev->wiphy), wdev->netdev, | ||
| 983 | bssid); | ||
| 984 | } | ||
| 985 | |||
| 986 | void cfg80211_port_authorized(struct net_device *dev, const u8 *bssid, | ||
| 987 | gfp_t gfp) | ||
| 988 | { | ||
| 989 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
| 990 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | ||
| 991 | struct cfg80211_event *ev; | ||
| 992 | unsigned long flags; | ||
| 993 | |||
| 994 | if (WARN_ON(!bssid)) | ||
| 995 | return; | ||
| 996 | |||
| 997 | ev = kzalloc(sizeof(*ev), gfp); | ||
| 998 | if (!ev) | ||
| 999 | return; | ||
| 1000 | |||
| 1001 | ev->type = EVENT_PORT_AUTHORIZED; | ||
| 1002 | memcpy(ev->pa.bssid, bssid, ETH_ALEN); | ||
| 1003 | |||
| 1004 | /* | ||
| 1005 | * Use the wdev event list so that if there are pending | ||
| 1006 | * connected/roamed events, they will be reported first. | ||
| 1007 | */ | ||
| 1008 | spin_lock_irqsave(&wdev->event_lock, flags); | ||
| 1009 | list_add_tail(&ev->list, &wdev->event_list); | ||
| 1010 | spin_unlock_irqrestore(&wdev->event_lock, flags); | ||
| 1011 | queue_work(cfg80211_wq, &rdev->event_work); | ||
| 1012 | } | ||
| 1013 | EXPORT_SYMBOL(cfg80211_port_authorized); | ||
| 1014 | |||
| 972 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | 1015 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, |
| 973 | size_t ie_len, u16 reason, bool from_ap) | 1016 | size_t ie_len, u16 reason, bool from_ap) |
| 974 | { | 1017 | { |
| @@ -157,32 +157,30 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband) · 156 unmodified lines | |||
| 157 | case NL80211_BAND_2GHZ: | 157 | case NL80211_BAND_2GHZ: |
| 158 | want = 7; | 158 | want = 7; |
| 159 | for (i = 0; i < sband->n_bitrates; i++) { | 159 | for (i = 0; i < sband->n_bitrates; i++) { |
| 160 | if (sband->bitrates[i].bitrate == 10) { | 160 | switch (sband->bitrates[i].bitrate) { |
| 161 | case 10: | ||
| 162 | case 20: | ||
| 163 | case 55: | ||
| 164 | case 110: | ||
| 161 | sband->bitrates[i].flags |= | 165 | sband->bitrates[i].flags |= |
| 162 | IEEE80211_RATE_MANDATORY_B | | 166 | IEEE80211_RATE_MANDATORY_B | |
| 163 | IEEE80211_RATE_MANDATORY_G; | 167 | IEEE80211_RATE_MANDATORY_G; |
| 164 | want--; | 168 | want--; |
| 165 | } | 169 | break; |
| 166 | 170 | case 60: | |
| 167 | if (sband->bitrates[i].bitrate == 20 || | 171 | case 120: |
| 168 | sband->bitrates[i].bitrate == 55 || | 172 | case 240: |
| 169 | sband->bitrates[i].bitrate == 110 || | ||
| 170 | sband->bitrates[i].bitrate == 60 || | ||
| 171 | sband->bitrates[i].bitrate == 120 || | ||
| 172 | sband->bitrates[i].bitrate == 240) { | ||
| 173 | sband->bitrates[i].flags |= | 173 | sband->bitrates[i].flags |= |
| 174 | IEEE80211_RATE_MANDATORY_G; | 174 | IEEE80211_RATE_MANDATORY_G; |
| 175 | want--; | 175 | want--; |
| 176 | } | 176 | /* fall through */ |
| 177 | 177 | default: | |
| 178 | if (sband->bitrates[i].bitrate != 10 && | ||
| 179 | sband->bitrates[i].bitrate != 20 && | ||
| 180 | sband->bitrates[i].bitrate != 55 && | ||
| 181 | sband->bitrates[i].bitrate != 110) | ||
| 182 | sband->bitrates[i].flags |= | 178 | sband->bitrates[i].flags |= |
| 183 | IEEE80211_RATE_ERP_G; | 179 | IEEE80211_RATE_ERP_G; |
| 180 | break; | ||
| 181 | } | ||
| 184 | } | 182 | } |
| 185 | WARN_ON(want != 0 && want != 3 && want != 6); | 183 | WARN_ON(want != 0 && want != 3); |
| 186 | break; | 184 | break; |
| 187 | case NL80211_BAND_60GHZ: | 185 | case NL80211_BAND_60GHZ: |
| 188 | /* check for mandatory HT MCS 1..4 */ | 186 | /* check for mandatory HT MCS 1..4 */ |
| @@ -529,121 +527,6 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, · 340 unmodified lines | |||
| 529 | } | 527 | } |
| 530 | EXPORT_SYMBOL(ieee80211_data_to_8023_exthdr); | 528 | EXPORT_SYMBOL(ieee80211_data_to_8023_exthdr); |
| 531 | 529 | ||
| 532 | int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, | ||
| 533 | enum nl80211_iftype iftype, | ||
| 534 | const u8 *bssid, bool qos) | ||
| 535 | { | ||
| 536 | struct ieee80211_hdr hdr; | ||
| 537 | u16 hdrlen, ethertype; | ||
| 538 | __le16 fc; | ||
| 539 | const u8 *encaps_data; | ||
| 540 | int encaps_len, skip_header_bytes; | ||
| 541 | int nh_pos, h_pos; | ||
| 542 | int head_need; | ||
| 543 | |||
| 544 | if (unlikely(skb->len < ETH_HLEN)) | ||
| 545 | return -EINVAL; | ||
| 546 | |||
| 547 | nh_pos = skb_network_header(skb) - skb->data; | ||
| 548 | h_pos = skb_transport_header(skb) - skb->data; | ||
| 549 | |||
| 550 | /* convert Ethernet header to proper 802.11 header (based on | ||
| 551 | * operation mode) */ | ||
| 552 | ethertype = (skb->data[12] << 8) | skb->data[13]; | ||
| 553 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); | ||
| 554 | |||
| 555 | switch (iftype) { | ||
| 556 | case NL80211_IFTYPE_AP: | ||
| 557 | case NL80211_IFTYPE_AP_VLAN: | ||
| 558 | case NL80211_IFTYPE_P2P_GO: | ||
| 559 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | ||
| 560 | /* DA BSSID SA */ | ||
| 561 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | ||
| 562 | memcpy(hdr.addr2, addr, ETH_ALEN); | ||
| 563 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); | ||
| 564 | hdrlen = 24; | ||
| 565 | break; | ||
| 566 | case NL80211_IFTYPE_STATION: | ||
| 567 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 568 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); | ||
| 569 | /* BSSID SA DA */ | ||
| 570 | memcpy(hdr.addr1, bssid, ETH_ALEN); | ||
| 571 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | ||
| 572 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
| 573 | hdrlen = 24; | ||
| 574 | break; | ||
| 575 | case NL80211_IFTYPE_OCB: | ||
| 576 | case NL80211_IFTYPE_ADHOC: | ||
| 577 | /* DA SA BSSID */ | ||
| 578 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | ||
| 579 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | ||
| 580 | memcpy(hdr.addr3, bssid, ETH_ALEN); | ||
| 581 | hdrlen = 24; | ||
| 582 | break; | ||
| 583 | default: | ||
| 584 | return -EOPNOTSUPP; | ||
| 585 | } | ||
| 586 | |||
| 587 | if (qos) { | ||
| 588 | fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); | ||
| 589 | hdrlen += 2; | ||
| 590 | } | ||
| 591 | |||
| 592 | hdr.frame_control = fc; | ||
| 593 | hdr.duration_id = 0; | ||
| 594 | hdr.seq_ctrl = 0; | ||
| 595 | |||
| 596 | skip_header_bytes = ETH_HLEN; | ||
| 597 | if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) { | ||
| 598 | encaps_data = bridge_tunnel_header; | ||
| 599 | encaps_len = sizeof(bridge_tunnel_header); | ||
| 600 | skip_header_bytes -= 2; | ||
| 601 | } else if (ethertype >= ETH_P_802_3_MIN) { | ||
| 602 | encaps_data = rfc1042_header; | ||
| 603 | encaps_len = sizeof(rfc1042_header); | ||
| 604 | skip_header_bytes -= 2; | ||
| 605 | } else { | ||
| 606 | encaps_data = NULL; | ||
| 607 | encaps_len = 0; | ||
| 608 | } | ||
| 609 | |||
| 610 | skb_pull(skb, skip_header_bytes); | ||
| 611 | nh_pos -= skip_header_bytes; | ||
| 612 | h_pos -= skip_header_bytes; | ||
| 613 | |||
| 614 | head_need = hdrlen + encaps_len - skb_headroom(skb); | ||
| 615 | |||
| 616 | if (head_need > 0 || skb_cloned(skb)) { | ||
| 617 | head_need = max(head_need, 0); | ||
| 618 | if (head_need) | ||
| 619 | skb_orphan(skb); | ||
| 620 | |||
| 621 | if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC)) | ||
| 622 | return -ENOMEM; | ||
| 623 | } | ||
| 624 | |||
| 625 | if (encaps_data) { | ||
| 626 | memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len); | ||
| 627 | nh_pos += encaps_len; | ||
| 628 | h_pos += encaps_len; | ||
| 629 | } | ||
| 630 | |||
| 631 | memcpy(skb_push(skb, hdrlen), &hdr, hdrlen); | ||
| 632 | |||
| 633 | nh_pos += hdrlen; | ||
| 634 | h_pos += hdrlen; | ||
| 635 | |||
| 636 | /* Update skb pointers to various headers since this modified frame | ||
| 637 | * is going to go through Linux networking code that may potentially | ||
| 638 | * need things like pointer to IP header. */ | ||
| 639 | skb_reset_mac_header(skb); | ||
| 640 | skb_set_network_header(skb, nh_pos); | ||
| 641 | skb_set_transport_header(skb, h_pos); | ||
| 642 | |||
| 643 | return 0; | ||
| 644 | } | ||
| 645 | EXPORT_SYMBOL(ieee80211_data_from_8023); | ||
| 646 | |||
| 647 | static void | 530 | static void |
| 648 | __frame_add_frag(struct sk_buff *skb, struct page *page, | 531 | __frame_add_frag(struct sk_buff *skb, struct page *page, |
| 649 | void *ptr, int len, int size) | 532 | void *ptr, int len, int size) |
| @@ -963,6 +846,9 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) · 313 unmodified lines | |||
| 963 | case EVENT_STOPPED: | 846 | case EVENT_STOPPED: |
| 964 | __cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev); | 847 | __cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev); |
| 965 | break; | 848 | break; |
| 849 | case EVENT_PORT_AUTHORIZED: | ||
| 850 | __cfg80211_port_authorized(wdev, ev->pa.bssid); | ||
| 851 | break; | ||
| 966 | } | 852 | } |
| 967 | wdev_unlock(wdev); | 853 | wdev_unlock(wdev); |
| 968 | 854 | ||
| @@ -1367,13 +1253,29 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, · 398 unmodified lines | |||
| 1367 | } | 1253 | } |
| 1368 | EXPORT_SYMBOL(cfg80211_get_p2p_attr); | 1254 | EXPORT_SYMBOL(cfg80211_get_p2p_attr); |
| 1369 | 1255 | ||
| 1370 | static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) | 1256 | static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id, bool id_ext) |
| 1371 | { | 1257 | { |
| 1372 | int i; | 1258 | int i; |
| 1373 | 1259 | ||
| 1374 | for (i = 0; i < n_ids; i++) | 1260 | /* Make sure array values are legal */ |
| 1375 | if (ids[i] == id) | 1261 | if (WARN_ON(ids[n_ids - 1] == WLAN_EID_EXTENSION)) |
| 1262 | return false; | ||
| 1263 | |||
| 1264 | i = 0; | ||
| 1265 | while (i < n_ids) { | ||
| 1266 | if (ids[i] == WLAN_EID_EXTENSION) { | ||
| 1267 | if (id_ext && (ids[i + 1] == id)) | ||
| 1268 | return true; | ||
| 1269 | |||
| 1270 | i += 2; | ||
| 1271 | continue; | ||
| 1272 | } | ||
| 1273 | |||
| 1274 | if (ids[i] == id && !id_ext) | ||
| 1376 | return true; | 1275 | return true; |
| 1276 | |||
| 1277 | i++; | ||
| 1278 | } | ||
| 1377 | return false; | 1279 | return false; |
| 1378 | } | 1280 | } |
| 1379 | 1281 | ||
| @@ -1403,14 +1305,36 @@ size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen, · 23 unmodified lines | |||
| 1403 | { | 1305 | { |
| 1404 | size_t pos = offset; | 1306 | size_t pos = offset; |
| 1405 | 1307 | ||
| 1406 | while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) { | 1308 | while (pos < ielen) { |
| 1309 | u8 ext = 0; | ||
| 1310 | |||
| 1311 | if (ies[pos] == WLAN_EID_EXTENSION) | ||
| 1312 | ext = 2; | ||
| 1313 | if ((pos + ext) >= ielen) | ||
| 1314 | break; | ||
| 1315 | |||
| 1316 | if (!ieee80211_id_in_list(ids, n_ids, ies[pos + ext], | ||
| 1317 | ies[pos] == WLAN_EID_EXTENSION)) | ||
| 1318 | break; | ||
| 1319 | |||
| 1407 | if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) { | 1320 | if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) { |
| 1408 | pos = skip_ie(ies, ielen, pos); | 1321 | pos = skip_ie(ies, ielen, pos); |
| 1409 | 1322 | ||
| 1410 | while (pos < ielen && | 1323 | while (pos < ielen) { |
| 1411 | !ieee80211_id_in_list(after_ric, n_after_ric, | 1324 | if (ies[pos] == WLAN_EID_EXTENSION) |
| 1412 | ies[pos])) | 1325 | ext = 2; |
| 1413 | pos = skip_ie(ies, ielen, pos); | 1326 | else |
| 1327 | ext = 0; | ||
| 1328 | |||
| 1329 | if ((pos + ext) >= ielen) | ||
| 1330 | break; | ||
| 1331 | |||
| 1332 | if (!ieee80211_id_in_list(after_ric, | ||
| 1333 | n_after_ric, | ||
| 1334 | ies[pos + ext], | ||
| 1335 | ext == 2)) | ||
| 1336 | pos = skip_ie(ies, ielen, pos); | ||
| 1337 | } | ||
| 1414 | } else { | 1338 | } else { |
| 1415 | pos = skip_ie(ies, ielen, pos); | 1339 | pos = skip_ie(ies, ielen, pos); |
| 1416 | } | 1340 | } |