diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 208 |
1 files changed, 159 insertions, 49 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 37902a54e9c1..f15b1af2c768 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -136,6 +136,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
136 | .len = sizeof(struct nl80211_sta_flag_update), | 136 | .len = sizeof(struct nl80211_sta_flag_update), |
137 | }, | 137 | }, |
138 | [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG }, | 138 | [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG }, |
139 | [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 }, | ||
140 | [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG }, | ||
139 | [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG }, | 141 | [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG }, |
140 | [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 }, | 142 | [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 }, |
141 | [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, | 143 | [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, |
@@ -156,6 +158,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
156 | 158 | ||
157 | [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, | 159 | [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, |
158 | [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, | 160 | [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, |
161 | [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, | ||
159 | }; | 162 | }; |
160 | 163 | ||
161 | /* policy for the attributes */ | 164 | /* policy for the attributes */ |
@@ -407,12 +410,14 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) | |||
407 | switch (wdev->iftype) { | 410 | switch (wdev->iftype) { |
408 | case NL80211_IFTYPE_AP: | 411 | case NL80211_IFTYPE_AP: |
409 | case NL80211_IFTYPE_AP_VLAN: | 412 | case NL80211_IFTYPE_AP_VLAN: |
413 | case NL80211_IFTYPE_P2P_GO: | ||
410 | break; | 414 | break; |
411 | case NL80211_IFTYPE_ADHOC: | 415 | case NL80211_IFTYPE_ADHOC: |
412 | if (!wdev->current_bss) | 416 | if (!wdev->current_bss) |
413 | return -ENOLINK; | 417 | return -ENOLINK; |
414 | break; | 418 | break; |
415 | case NL80211_IFTYPE_STATION: | 419 | case NL80211_IFTYPE_STATION: |
420 | case NL80211_IFTYPE_P2P_CLIENT: | ||
416 | if (wdev->sme_state != CFG80211_SME_CONNECTED) | 421 | if (wdev->sme_state != CFG80211_SME_CONNECTED) |
417 | return -ENOLINK; | 422 | return -ENOLINK; |
418 | break; | 423 | break; |
@@ -437,6 +442,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
437 | struct ieee80211_rate *rate; | 442 | struct ieee80211_rate *rate; |
438 | int i; | 443 | int i; |
439 | u16 ifmodes = dev->wiphy.interface_modes; | 444 | u16 ifmodes = dev->wiphy.interface_modes; |
445 | const struct ieee80211_txrx_stypes *mgmt_stypes = | ||
446 | dev->wiphy.mgmt_stypes; | ||
440 | 447 | ||
441 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); | 448 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); |
442 | if (!hdr) | 449 | if (!hdr) |
@@ -471,6 +478,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
471 | NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, | 478 | NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, |
472 | dev->wiphy.max_num_pmkids); | 479 | dev->wiphy.max_num_pmkids); |
473 | 480 | ||
481 | if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) | ||
482 | NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE); | ||
483 | |||
474 | nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); | 484 | nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); |
475 | if (!nl_modes) | 485 | if (!nl_modes) |
476 | goto nla_put_failure; | 486 | goto nla_put_failure; |
@@ -587,7 +597,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
587 | CMD(flush_pmksa, FLUSH_PMKSA); | 597 | CMD(flush_pmksa, FLUSH_PMKSA); |
588 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); | 598 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); |
589 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); | 599 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); |
590 | CMD(action, ACTION); | 600 | CMD(mgmt_tx, FRAME); |
591 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { | 601 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { |
592 | i++; | 602 | i++; |
593 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); | 603 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); |
@@ -608,6 +618,55 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
608 | 618 | ||
609 | nla_nest_end(msg, nl_cmds); | 619 | nla_nest_end(msg, nl_cmds); |
610 | 620 | ||
621 | if (mgmt_stypes) { | ||
622 | u16 stypes; | ||
623 | struct nlattr *nl_ftypes, *nl_ifs; | ||
624 | enum nl80211_iftype ift; | ||
625 | |||
626 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES); | ||
627 | if (!nl_ifs) | ||
628 | goto nla_put_failure; | ||
629 | |||
630 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | ||
631 | nl_ftypes = nla_nest_start(msg, ift); | ||
632 | if (!nl_ftypes) | ||
633 | goto nla_put_failure; | ||
634 | i = 0; | ||
635 | stypes = mgmt_stypes[ift].tx; | ||
636 | while (stypes) { | ||
637 | if (stypes & 1) | ||
638 | NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, | ||
639 | (i << 4) | IEEE80211_FTYPE_MGMT); | ||
640 | stypes >>= 1; | ||
641 | i++; | ||
642 | } | ||
643 | nla_nest_end(msg, nl_ftypes); | ||
644 | } | ||
645 | |||
646 | nla_nest_end(msg, nl_ifs); | ||
647 | |||
648 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); | ||
649 | if (!nl_ifs) | ||
650 | goto nla_put_failure; | ||
651 | |||
652 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | ||
653 | nl_ftypes = nla_nest_start(msg, ift); | ||
654 | if (!nl_ftypes) | ||
655 | goto nla_put_failure; | ||
656 | i = 0; | ||
657 | stypes = mgmt_stypes[ift].rx; | ||
658 | while (stypes) { | ||
659 | if (stypes & 1) | ||
660 | NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, | ||
661 | (i << 4) | IEEE80211_FTYPE_MGMT); | ||
662 | stypes >>= 1; | ||
663 | i++; | ||
664 | } | ||
665 | nla_nest_end(msg, nl_ftypes); | ||
666 | } | ||
667 | nla_nest_end(msg, nl_ifs); | ||
668 | } | ||
669 | |||
611 | return genlmsg_end(msg, hdr); | 670 | return genlmsg_end(msg, hdr); |
612 | 671 | ||
613 | nla_put_failure: | 672 | nla_put_failure: |
@@ -709,7 +768,8 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) | |||
709 | wdev->iftype == NL80211_IFTYPE_AP || | 768 | wdev->iftype == NL80211_IFTYPE_AP || |
710 | wdev->iftype == NL80211_IFTYPE_WDS || | 769 | wdev->iftype == NL80211_IFTYPE_WDS || |
711 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || | 770 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || |
712 | wdev->iftype == NL80211_IFTYPE_MONITOR; | 771 | wdev->iftype == NL80211_IFTYPE_MONITOR || |
772 | wdev->iftype == NL80211_IFTYPE_P2P_GO; | ||
713 | } | 773 | } |
714 | 774 | ||
715 | static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | 775 | static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, |
@@ -776,7 +836,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
776 | struct cfg80211_registered_device *rdev; | 836 | struct cfg80211_registered_device *rdev; |
777 | struct net_device *netdev = NULL; | 837 | struct net_device *netdev = NULL; |
778 | struct wireless_dev *wdev; | 838 | struct wireless_dev *wdev; |
779 | int result, rem_txq_params = 0; | 839 | int result = 0, rem_txq_params = 0; |
780 | struct nlattr *nl_txq_params; | 840 | struct nlattr *nl_txq_params; |
781 | u32 changed; | 841 | u32 changed; |
782 | u8 retry_short = 0, retry_long = 0; | 842 | u8 retry_short = 0, retry_long = 0; |
@@ -1636,7 +1696,8 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1636 | if (err) | 1696 | if (err) |
1637 | goto unlock_rtnl; | 1697 | goto unlock_rtnl; |
1638 | 1698 | ||
1639 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) { | 1699 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
1700 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
1640 | err = -EOPNOTSUPP; | 1701 | err = -EOPNOTSUPP; |
1641 | goto out; | 1702 | goto out; |
1642 | } | 1703 | } |
@@ -1728,7 +1789,8 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1728 | goto out; | 1789 | goto out; |
1729 | } | 1790 | } |
1730 | 1791 | ||
1731 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) { | 1792 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
1793 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
1732 | err = -EOPNOTSUPP; | 1794 | err = -EOPNOTSUPP; |
1733 | goto out; | 1795 | goto out; |
1734 | } | 1796 | } |
@@ -2071,10 +2133,12 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
2071 | switch (dev->ieee80211_ptr->iftype) { | 2133 | switch (dev->ieee80211_ptr->iftype) { |
2072 | case NL80211_IFTYPE_AP: | 2134 | case NL80211_IFTYPE_AP: |
2073 | case NL80211_IFTYPE_AP_VLAN: | 2135 | case NL80211_IFTYPE_AP_VLAN: |
2136 | case NL80211_IFTYPE_P2P_GO: | ||
2074 | /* disallow mesh-specific things */ | 2137 | /* disallow mesh-specific things */ |
2075 | if (params.plink_action) | 2138 | if (params.plink_action) |
2076 | err = -EINVAL; | 2139 | err = -EINVAL; |
2077 | break; | 2140 | break; |
2141 | case NL80211_IFTYPE_P2P_CLIENT: | ||
2078 | case NL80211_IFTYPE_STATION: | 2142 | case NL80211_IFTYPE_STATION: |
2079 | /* disallow everything but AUTHORIZED flag */ | 2143 | /* disallow everything but AUTHORIZED flag */ |
2080 | if (params.plink_action) | 2144 | if (params.plink_action) |
@@ -2176,7 +2240,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
2176 | goto out_rtnl; | 2240 | goto out_rtnl; |
2177 | 2241 | ||
2178 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2242 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2179 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | 2243 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
2244 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
2180 | err = -EINVAL; | 2245 | err = -EINVAL; |
2181 | goto out; | 2246 | goto out; |
2182 | } | 2247 | } |
@@ -2229,7 +2294,8 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
2229 | 2294 | ||
2230 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2295 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2231 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | 2296 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
2232 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { | 2297 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && |
2298 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
2233 | err = -EINVAL; | 2299 | err = -EINVAL; |
2234 | goto out; | 2300 | goto out; |
2235 | } | 2301 | } |
@@ -2603,7 +2669,8 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
2603 | goto out; | 2669 | goto out; |
2604 | } | 2670 | } |
2605 | 2671 | ||
2606 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) { | 2672 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2673 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
2607 | err = -EOPNOTSUPP; | 2674 | err = -EOPNOTSUPP; |
2608 | goto out; | 2675 | goto out; |
2609 | } | 2676 | } |
@@ -3306,6 +3373,7 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
3306 | } | 3373 | } |
3307 | 3374 | ||
3308 | switch (wdev->iftype) { | 3375 | switch (wdev->iftype) { |
3376 | case NL80211_IFTYPE_P2P_CLIENT: | ||
3309 | case NL80211_IFTYPE_STATION: | 3377 | case NL80211_IFTYPE_STATION: |
3310 | if (intbss == wdev->current_bss) | 3378 | if (intbss == wdev->current_bss) |
3311 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, | 3379 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, |
@@ -3572,12 +3640,28 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3572 | if (err) | 3640 | if (err) |
3573 | goto unlock_rtnl; | 3641 | goto unlock_rtnl; |
3574 | 3642 | ||
3643 | if (key.idx >= 0) { | ||
3644 | int i; | ||
3645 | bool ok = false; | ||
3646 | for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) { | ||
3647 | if (key.p.cipher == rdev->wiphy.cipher_suites[i]) { | ||
3648 | ok = true; | ||
3649 | break; | ||
3650 | } | ||
3651 | } | ||
3652 | if (!ok) { | ||
3653 | err = -EINVAL; | ||
3654 | goto out; | ||
3655 | } | ||
3656 | } | ||
3657 | |||
3575 | if (!rdev->ops->auth) { | 3658 | if (!rdev->ops->auth) { |
3576 | err = -EOPNOTSUPP; | 3659 | err = -EOPNOTSUPP; |
3577 | goto out; | 3660 | goto out; |
3578 | } | 3661 | } |
3579 | 3662 | ||
3580 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 3663 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
3664 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
3581 | err = -EOPNOTSUPP; | 3665 | err = -EOPNOTSUPP; |
3582 | goto out; | 3666 | goto out; |
3583 | } | 3667 | } |
@@ -3624,7 +3708,8 @@ unlock_rtnl: | |||
3624 | return err; | 3708 | return err; |
3625 | } | 3709 | } |
3626 | 3710 | ||
3627 | static int nl80211_crypto_settings(struct genl_info *info, | 3711 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, |
3712 | struct genl_info *info, | ||
3628 | struct cfg80211_crypto_settings *settings, | 3713 | struct cfg80211_crypto_settings *settings, |
3629 | int cipher_limit) | 3714 | int cipher_limit) |
3630 | { | 3715 | { |
@@ -3632,6 +3717,19 @@ static int nl80211_crypto_settings(struct genl_info *info, | |||
3632 | 3717 | ||
3633 | settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT]; | 3718 | settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT]; |
3634 | 3719 | ||
3720 | if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) { | ||
3721 | u16 proto; | ||
3722 | proto = nla_get_u16( | ||
3723 | info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]); | ||
3724 | settings->control_port_ethertype = cpu_to_be16(proto); | ||
3725 | if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) && | ||
3726 | proto != ETH_P_PAE) | ||
3727 | return -EINVAL; | ||
3728 | if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]) | ||
3729 | settings->control_port_no_encrypt = true; | ||
3730 | } else | ||
3731 | settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE); | ||
3732 | |||
3635 | if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) { | 3733 | if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) { |
3636 | void *data; | 3734 | void *data; |
3637 | int len, i; | 3735 | int len, i; |
@@ -3718,7 +3816,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
3718 | goto out; | 3816 | goto out; |
3719 | } | 3817 | } |
3720 | 3818 | ||
3721 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 3819 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
3820 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
3722 | err = -EOPNOTSUPP; | 3821 | err = -EOPNOTSUPP; |
3723 | goto out; | 3822 | goto out; |
3724 | } | 3823 | } |
@@ -3759,7 +3858,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
3759 | if (info->attrs[NL80211_ATTR_PREV_BSSID]) | 3858 | if (info->attrs[NL80211_ATTR_PREV_BSSID]) |
3760 | prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); | 3859 | prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); |
3761 | 3860 | ||
3762 | err = nl80211_crypto_settings(info, &crypto, 1); | 3861 | err = nl80211_crypto_settings(rdev, info, &crypto, 1); |
3763 | if (!err) | 3862 | if (!err) |
3764 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, | 3863 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, |
3765 | ssid, ssid_len, ie, ie_len, use_mfp, | 3864 | ssid, ssid_len, ie, ie_len, use_mfp, |
@@ -3802,7 +3901,8 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3802 | goto out; | 3901 | goto out; |
3803 | } | 3902 | } |
3804 | 3903 | ||
3805 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 3904 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
3905 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
3806 | err = -EOPNOTSUPP; | 3906 | err = -EOPNOTSUPP; |
3807 | goto out; | 3907 | goto out; |
3808 | } | 3908 | } |
@@ -3868,7 +3968,8 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3868 | goto out; | 3968 | goto out; |
3869 | } | 3969 | } |
3870 | 3970 | ||
3871 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 3971 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
3972 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
3872 | err = -EOPNOTSUPP; | 3973 | err = -EOPNOTSUPP; |
3873 | goto out; | 3974 | goto out; |
3874 | } | 3975 | } |
@@ -4236,7 +4337,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
4236 | 4337 | ||
4237 | connect.privacy = info->attrs[NL80211_ATTR_PRIVACY]; | 4338 | connect.privacy = info->attrs[NL80211_ATTR_PRIVACY]; |
4238 | 4339 | ||
4239 | err = nl80211_crypto_settings(info, &connect.crypto, | 4340 | err = nl80211_crypto_settings(rdev, info, &connect.crypto, |
4240 | NL80211_MAX_NR_CIPHER_SUITES); | 4341 | NL80211_MAX_NR_CIPHER_SUITES); |
4241 | if (err) | 4342 | if (err) |
4242 | return err; | 4343 | return err; |
@@ -4246,7 +4347,8 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
4246 | if (err) | 4347 | if (err) |
4247 | goto unlock_rtnl; | 4348 | goto unlock_rtnl; |
4248 | 4349 | ||
4249 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 4350 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4351 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
4250 | err = -EOPNOTSUPP; | 4352 | err = -EOPNOTSUPP; |
4251 | goto out; | 4353 | goto out; |
4252 | } | 4354 | } |
@@ -4322,7 +4424,8 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) | |||
4322 | if (err) | 4424 | if (err) |
4323 | goto unlock_rtnl; | 4425 | goto unlock_rtnl; |
4324 | 4426 | ||
4325 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 4427 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4428 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
4326 | err = -EOPNOTSUPP; | 4429 | err = -EOPNOTSUPP; |
4327 | goto out; | 4430 | goto out; |
4328 | } | 4431 | } |
@@ -4410,7 +4513,8 @@ static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info) | |||
4410 | pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]); | 4513 | pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]); |
4411 | pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 4514 | pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
4412 | 4515 | ||
4413 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 4516 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4517 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
4414 | err = -EOPNOTSUPP; | 4518 | err = -EOPNOTSUPP; |
4415 | goto out; | 4519 | goto out; |
4416 | } | 4520 | } |
@@ -4455,7 +4559,8 @@ static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info) | |||
4455 | if (err) | 4559 | if (err) |
4456 | goto out_rtnl; | 4560 | goto out_rtnl; |
4457 | 4561 | ||
4458 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 4562 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4563 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
4459 | err = -EOPNOTSUPP; | 4564 | err = -EOPNOTSUPP; |
4460 | goto out; | 4565 | goto out; |
4461 | } | 4566 | } |
@@ -4717,17 +4822,18 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
4717 | return err; | 4822 | return err; |
4718 | } | 4823 | } |
4719 | 4824 | ||
4720 | static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | 4825 | static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) |
4721 | { | 4826 | { |
4722 | struct cfg80211_registered_device *rdev; | 4827 | struct cfg80211_registered_device *rdev; |
4723 | struct net_device *dev; | 4828 | struct net_device *dev; |
4829 | u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION; | ||
4724 | int err; | 4830 | int err; |
4725 | 4831 | ||
4726 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) | 4832 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) |
4727 | return -EINVAL; | 4833 | return -EINVAL; |
4728 | 4834 | ||
4729 | if (nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]) < 1) | 4835 | if (info->attrs[NL80211_ATTR_FRAME_TYPE]) |
4730 | return -EINVAL; | 4836 | frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]); |
4731 | 4837 | ||
4732 | rtnl_lock(); | 4838 | rtnl_lock(); |
4733 | 4839 | ||
@@ -4736,18 +4842,20 @@ static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | |||
4736 | goto unlock_rtnl; | 4842 | goto unlock_rtnl; |
4737 | 4843 | ||
4738 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 4844 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4739 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { | 4845 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && |
4846 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
4740 | err = -EOPNOTSUPP; | 4847 | err = -EOPNOTSUPP; |
4741 | goto out; | 4848 | goto out; |
4742 | } | 4849 | } |
4743 | 4850 | ||
4744 | /* not much point in registering if we can't reply */ | 4851 | /* not much point in registering if we can't reply */ |
4745 | if (!rdev->ops->action) { | 4852 | if (!rdev->ops->mgmt_tx) { |
4746 | err = -EOPNOTSUPP; | 4853 | err = -EOPNOTSUPP; |
4747 | goto out; | 4854 | goto out; |
4748 | } | 4855 | } |
4749 | 4856 | ||
4750 | err = cfg80211_mlme_register_action(dev->ieee80211_ptr, info->snd_pid, | 4857 | err = cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid, |
4858 | frame_type, | ||
4751 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), | 4859 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), |
4752 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); | 4860 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); |
4753 | out: | 4861 | out: |
@@ -4758,7 +4866,7 @@ static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | |||
4758 | return err; | 4866 | return err; |
4759 | } | 4867 | } |
4760 | 4868 | ||
4761 | static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | 4869 | static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) |
4762 | { | 4870 | { |
4763 | struct cfg80211_registered_device *rdev; | 4871 | struct cfg80211_registered_device *rdev; |
4764 | struct net_device *dev; | 4872 | struct net_device *dev; |
@@ -4781,13 +4889,14 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | |||
4781 | if (err) | 4889 | if (err) |
4782 | goto unlock_rtnl; | 4890 | goto unlock_rtnl; |
4783 | 4891 | ||
4784 | if (!rdev->ops->action) { | 4892 | if (!rdev->ops->mgmt_tx) { |
4785 | err = -EOPNOTSUPP; | 4893 | err = -EOPNOTSUPP; |
4786 | goto out; | 4894 | goto out; |
4787 | } | 4895 | } |
4788 | 4896 | ||
4789 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 4897 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4790 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { | 4898 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && |
4899 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
4791 | err = -EOPNOTSUPP; | 4900 | err = -EOPNOTSUPP; |
4792 | goto out; | 4901 | goto out; |
4793 | } | 4902 | } |
@@ -4824,17 +4933,17 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | |||
4824 | } | 4933 | } |
4825 | 4934 | ||
4826 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 4935 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
4827 | NL80211_CMD_ACTION); | 4936 | NL80211_CMD_FRAME); |
4828 | 4937 | ||
4829 | if (IS_ERR(hdr)) { | 4938 | if (IS_ERR(hdr)) { |
4830 | err = PTR_ERR(hdr); | 4939 | err = PTR_ERR(hdr); |
4831 | goto free_msg; | 4940 | goto free_msg; |
4832 | } | 4941 | } |
4833 | err = cfg80211_mlme_action(rdev, dev, chan, channel_type, | 4942 | err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, channel_type, |
4834 | channel_type_valid, | 4943 | channel_type_valid, |
4835 | nla_data(info->attrs[NL80211_ATTR_FRAME]), | 4944 | nla_data(info->attrs[NL80211_ATTR_FRAME]), |
4836 | nla_len(info->attrs[NL80211_ATTR_FRAME]), | 4945 | nla_len(info->attrs[NL80211_ATTR_FRAME]), |
4837 | &cookie); | 4946 | &cookie); |
4838 | if (err) | 4947 | if (err) |
4839 | goto free_msg; | 4948 | goto free_msg; |
4840 | 4949 | ||
@@ -5005,7 +5114,8 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, | |||
5005 | goto unlock_rdev; | 5114 | goto unlock_rdev; |
5006 | } | 5115 | } |
5007 | 5116 | ||
5008 | if (wdev->iftype != NL80211_IFTYPE_STATION) { | 5117 | if (wdev->iftype != NL80211_IFTYPE_STATION && |
5118 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
5009 | err = -EOPNOTSUPP; | 5119 | err = -EOPNOTSUPP; |
5010 | goto unlock_rdev; | 5120 | goto unlock_rdev; |
5011 | } | 5121 | } |
@@ -5333,14 +5443,14 @@ static struct genl_ops nl80211_ops[] = { | |||
5333 | .flags = GENL_ADMIN_PERM, | 5443 | .flags = GENL_ADMIN_PERM, |
5334 | }, | 5444 | }, |
5335 | { | 5445 | { |
5336 | .cmd = NL80211_CMD_REGISTER_ACTION, | 5446 | .cmd = NL80211_CMD_REGISTER_FRAME, |
5337 | .doit = nl80211_register_action, | 5447 | .doit = nl80211_register_mgmt, |
5338 | .policy = nl80211_policy, | 5448 | .policy = nl80211_policy, |
5339 | .flags = GENL_ADMIN_PERM, | 5449 | .flags = GENL_ADMIN_PERM, |
5340 | }, | 5450 | }, |
5341 | { | 5451 | { |
5342 | .cmd = NL80211_CMD_ACTION, | 5452 | .cmd = NL80211_CMD_FRAME, |
5343 | .doit = nl80211_action, | 5453 | .doit = nl80211_tx_mgmt, |
5344 | .policy = nl80211_policy, | 5454 | .policy = nl80211_policy, |
5345 | .flags = GENL_ADMIN_PERM, | 5455 | .flags = GENL_ADMIN_PERM, |
5346 | }, | 5456 | }, |
@@ -6040,9 +6150,9 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
6040 | nl80211_mlme_mcgrp.id, gfp); | 6150 | nl80211_mlme_mcgrp.id, gfp); |
6041 | } | 6151 | } |
6042 | 6152 | ||
6043 | int nl80211_send_action(struct cfg80211_registered_device *rdev, | 6153 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
6044 | struct net_device *netdev, u32 nlpid, | 6154 | struct net_device *netdev, u32 nlpid, |
6045 | int freq, const u8 *buf, size_t len, gfp_t gfp) | 6155 | int freq, const u8 *buf, size_t len, gfp_t gfp) |
6046 | { | 6156 | { |
6047 | struct sk_buff *msg; | 6157 | struct sk_buff *msg; |
6048 | void *hdr; | 6158 | void *hdr; |
@@ -6052,7 +6162,7 @@ int nl80211_send_action(struct cfg80211_registered_device *rdev, | |||
6052 | if (!msg) | 6162 | if (!msg) |
6053 | return -ENOMEM; | 6163 | return -ENOMEM; |
6054 | 6164 | ||
6055 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION); | 6165 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME); |
6056 | if (!hdr) { | 6166 | if (!hdr) { |
6057 | nlmsg_free(msg); | 6167 | nlmsg_free(msg); |
6058 | return -ENOMEM; | 6168 | return -ENOMEM; |
@@ -6080,10 +6190,10 @@ int nl80211_send_action(struct cfg80211_registered_device *rdev, | |||
6080 | return -ENOBUFS; | 6190 | return -ENOBUFS; |
6081 | } | 6191 | } |
6082 | 6192 | ||
6083 | void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | 6193 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, |
6084 | struct net_device *netdev, u64 cookie, | 6194 | struct net_device *netdev, u64 cookie, |
6085 | const u8 *buf, size_t len, bool ack, | 6195 | const u8 *buf, size_t len, bool ack, |
6086 | gfp_t gfp) | 6196 | gfp_t gfp) |
6087 | { | 6197 | { |
6088 | struct sk_buff *msg; | 6198 | struct sk_buff *msg; |
6089 | void *hdr; | 6199 | void *hdr; |
@@ -6092,7 +6202,7 @@ void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | |||
6092 | if (!msg) | 6202 | if (!msg) |
6093 | return; | 6203 | return; |
6094 | 6204 | ||
6095 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION_TX_STATUS); | 6205 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME_TX_STATUS); |
6096 | if (!hdr) { | 6206 | if (!hdr) { |
6097 | nlmsg_free(msg); | 6207 | nlmsg_free(msg); |
6098 | return; | 6208 | return; |
@@ -6179,7 +6289,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
6179 | 6289 | ||
6180 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) | 6290 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) |
6181 | list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) | 6291 | list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) |
6182 | cfg80211_mlme_unregister_actions(wdev, notify->pid); | 6292 | cfg80211_mlme_unregister_socket(wdev, notify->pid); |
6183 | 6293 | ||
6184 | rcu_read_unlock(); | 6294 | rcu_read_unlock(); |
6185 | 6295 | ||