summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-11-13 07:37:47 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-12-03 10:27:17 -0500
commitad7e718c9b4f717823fd920a0103f7b0fb06183f (patch)
treecb87f5792da6330705586e232f8e39b46e188e26
parent7869303b17a3cc78c9e9f26544be98b5734ac97c (diff)
nl80211: vendor command support
Add support for vendor-specific commands to nl80211. This is intended to be used for really vendor-specific functionality that can't be implemented in a generic fashion for any reason. It's *NOT* intended to be used for any normal/generic feature or any optimisations that could be implemented across drivers. Currently, only vendor commands (with replies) are supported, no dump operations or vendor-specific notifications. Also add a function wdev_to_ieee80211_vif() to mac80211 which is needed for mac80211-based drivers wanting to implement any vendor commands. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/cfg80211.h116
-rw-r--r--include/net/mac80211.h13
-rw-r--r--include/uapi/linux/nl80211.h41
-rw-r--r--net/mac80211/util.c11
-rw-r--r--net/wireless/core.h4
-rw-r--r--net/wireless/nl80211.c237
6 files changed, 348 insertions, 74 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 47290a4059ae..884ac69b5e55 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2680,6 +2680,34 @@ struct wiphy_coalesce_support {
2680}; 2680};
2681 2681
2682/** 2682/**
2683 * enum wiphy_vendor_command_flags - validation flags for vendor commands
2684 * @WIPHY_VENDOR_CMD_NEED_WDEV: vendor command requires wdev
2685 * @WIPHY_VENDOR_CMD_NEED_NETDEV: vendor command requires netdev
2686 * @WIPHY_VENDOR_CMD_NEED_RUNNING: interface/wdev must be up & running
2687 * (must be combined with %_WDEV or %_NETDEV)
2688 */
2689enum wiphy_vendor_command_flags {
2690 WIPHY_VENDOR_CMD_NEED_WDEV = BIT(0),
2691 WIPHY_VENDOR_CMD_NEED_NETDEV = BIT(1),
2692 WIPHY_VENDOR_CMD_NEED_RUNNING = BIT(2),
2693};
2694
2695/**
2696 * struct wiphy_vendor_command - vendor command definition
2697 * @info: vendor command identifying information, as used in nl80211
2698 * @flags: flags, see &enum wiphy_vendor_command_flags
2699 * @doit: callback for the operation, note that wdev is %NULL if the
2700 * flags didn't ask for a wdev and non-%NULL otherwise; the data
2701 * pointer may be %NULL if userspace provided no data at all
2702 */
2703struct wiphy_vendor_command {
2704 struct nl80211_vendor_cmd_info info;
2705 u32 flags;
2706 int (*doit)(struct wiphy *wiphy, struct wireless_dev *wdev,
2707 const void *data, int data_len);
2708};
2709
2710/**
2683 * struct wiphy - wireless hardware description 2711 * struct wiphy - wireless hardware description
2684 * @reg_notifier: the driver's regulatory notification callback, 2712 * @reg_notifier: the driver's regulatory notification callback,
2685 * note that if your driver uses wiphy_apply_custom_regulatory() 2713 * note that if your driver uses wiphy_apply_custom_regulatory()
@@ -2792,6 +2820,9 @@ struct wiphy_coalesce_support {
2792 * @extended_capabilities_mask: mask of the valid values 2820 * @extended_capabilities_mask: mask of the valid values
2793 * @extended_capabilities_len: length of the extended capabilities 2821 * @extended_capabilities_len: length of the extended capabilities
2794 * @coalesce: packet coalescing support information 2822 * @coalesce: packet coalescing support information
2823 *
2824 * @vendor_commands: array of vendor commands supported by the hardware
2825 * @n_vendor_commands: number of vendor commands
2795 */ 2826 */
2796struct wiphy { 2827struct wiphy {
2797 /* assign these fields before you register the wiphy */ 2828 /* assign these fields before you register the wiphy */
@@ -2903,6 +2934,9 @@ struct wiphy {
2903 2934
2904 const struct wiphy_coalesce_support *coalesce; 2935 const struct wiphy_coalesce_support *coalesce;
2905 2936
2937 const struct wiphy_vendor_command *vendor_commands;
2938 int n_vendor_commands;
2939
2906 char priv[0] __aligned(NETDEV_ALIGN); 2940 char priv[0] __aligned(NETDEV_ALIGN);
2907}; 2941};
2908 2942
@@ -3847,6 +3881,75 @@ void wiphy_rfkill_start_polling(struct wiphy *wiphy);
3847 */ 3881 */
3848void wiphy_rfkill_stop_polling(struct wiphy *wiphy); 3882void wiphy_rfkill_stop_polling(struct wiphy *wiphy);
3849 3883
3884/**
3885 * DOC: Vendor commands
3886 *
3887 * Occasionally, there are special protocol or firmware features that
3888 * can't be implemented very openly. For this and similar cases, the
3889 * vendor command functionality allows implementing the features with
3890 * (typically closed-source) userspace and firmware, using nl80211 as
3891 * the configuration mechanism.
3892 *
3893 * A driver supporting vendor commands must register them as an array
3894 * in struct wiphy, with handlers for each one, each command has an
3895 * OUI and sub command ID to identify it.
3896 *
3897 * Note that this feature should not be (ab)used to implement protocol
3898 * features that could openly be shared across drivers. In particular,
3899 * it must never be required to use vendor commands to implement any
3900 * "normal" functionality that higher-level userspace like connection
3901 * managers etc. need.
3902 */
3903
3904struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
3905 enum nl80211_commands cmd,
3906 enum nl80211_attrs attr,
3907 int approxlen);
3908
3909/**
3910 * cfg80211_vendor_cmd_alloc_reply_skb - allocate vendor command reply
3911 * @wiphy: the wiphy
3912 * @approxlen: an upper bound of the length of the data that will
3913 * be put into the skb
3914 *
3915 * This function allocates and pre-fills an skb for a reply to
3916 * a vendor command. Since it is intended for a reply, calling
3917 * it outside of a vendor command's doit() operation is invalid.
3918 *
3919 * The returned skb is pre-filled with some identifying data in
3920 * a way that any data that is put into the skb (with skb_put(),
3921 * nla_put() or similar) will end up being within the
3922 * %NL80211_ATTR_VENDOR_DATA attribute, so all that needs to be done
3923 * with the skb is adding data for the corresponding userspace tool
3924 * which can then read that data out of the vendor data attribute.
3925 * You must not modify the skb in any other way.
3926 *
3927 * When done, call cfg80211_vendor_cmd_reply() with the skb and return
3928 * its error code as the result of the doit() operation.
3929 *
3930 * Return: An allocated and pre-filled skb. %NULL if any errors happen.
3931 */
3932static inline struct sk_buff *
3933cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int approxlen)
3934{
3935 return __cfg80211_alloc_reply_skb(wiphy, NL80211_CMD_VENDOR,
3936 NL80211_ATTR_VENDOR_DATA, approxlen);
3937}
3938
3939/**
3940 * cfg80211_vendor_cmd_reply - send the reply skb
3941 * @skb: The skb, must have been allocated with
3942 * cfg80211_vendor_cmd_alloc_reply_skb()
3943 *
3944 * Since calling this function will usually be the last thing
3945 * before returning from the vendor command doit() you should
3946 * return the error code. Note that this function consumes the
3947 * skb regardless of the return value.
3948 *
3949 * Return: An error code or 0 on success.
3950 */
3951int cfg80211_vendor_cmd_reply(struct sk_buff *skb);
3952
3850#ifdef CONFIG_NL80211_TESTMODE 3953#ifdef CONFIG_NL80211_TESTMODE
3851/** 3954/**
3852 * DOC: Test mode 3955 * DOC: Test mode
@@ -3882,8 +3985,12 @@ void wiphy_rfkill_stop_polling(struct wiphy *wiphy);
3882 * 3985 *
3883 * Return: An allocated and pre-filled skb. %NULL if any errors happen. 3986 * Return: An allocated and pre-filled skb. %NULL if any errors happen.
3884 */ 3987 */
3885struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy, 3988static inline struct sk_buff *
3886 int approxlen); 3989cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy, int approxlen)
3990{
3991 return __cfg80211_alloc_reply_skb(wiphy, NL80211_CMD_TESTMODE,
3992 NL80211_ATTR_TESTDATA, approxlen);
3993}
3887 3994
3888/** 3995/**
3889 * cfg80211_testmode_reply - send the reply skb 3996 * cfg80211_testmode_reply - send the reply skb
@@ -3897,7 +4004,10 @@ struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
3897 * 4004 *
3898 * Return: An error code or 0 on success. 4005 * Return: An error code or 0 on success.
3899 */ 4006 */
3900int cfg80211_testmode_reply(struct sk_buff *skb); 4007static inline int cfg80211_testmode_reply(struct sk_buff *skb)
4008{
4009 return cfg80211_vendor_cmd_reply(skb);
4010}
3901 4011
3902/** 4012/**
3903 * cfg80211_testmode_alloc_event_skb - allocate testmode event 4013 * cfg80211_testmode_alloc_event_skb - allocate testmode event
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 73d99bc3e636..c014acc09ebc 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1163,6 +1163,19 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
1163} 1163}
1164 1164
1165/** 1165/**
1166 * wdev_to_ieee80211_vif - return a vif struct from a wdev
1167 * @wdev: the wdev to get the vif for
1168 *
1169 * This can be used by mac80211 drivers with direct cfg80211 APIs
1170 * (like the vendor commands) that get a wdev.
1171 *
1172 * Note that this function may return %NULL if the given wdev isn't
1173 * associated with a vif that the driver knows about (e.g. monitor
1174 * or AP_VLAN interfaces.)
1175 */
1176struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
1177
1178/**
1166 * enum ieee80211_key_flags - key flags 1179 * enum ieee80211_key_flags - key flags
1167 * 1180 *
1168 * These flags are used for communication about keys between the driver 1181 * These flags are used for communication about keys between the driver
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 9a4d0e18251c..72ba3584c90d 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -693,6 +693,15 @@
693 * other station that transmission must be blocked until the channel 693 * other station that transmission must be blocked until the channel
694 * switch is complete. 694 * switch is complete.
695 * 695 *
696 * @NL80211_CMD_VENDOR: Vendor-specified command/event. The command is specified
697 * by the %NL80211_ATTR_VENDOR_ID attribute and a sub-command in
698 * %NL80211_ATTR_VENDOR_SUBCMD. Parameter(s) can be transported in
699 * %NL80211_ATTR_VENDOR_DATA.
700 * For feature advertisement, the %NL80211_ATTR_VENDOR_DATA attribute is
701 * used in the wiphy data as a nested attribute containing descriptions
702 * (&struct nl80211_vendor_cmd_info) of the supported vendor commands.
703 * This may also be sent as an event with the same attributes.
704 *
696 * @NL80211_CMD_MAX: highest used command number 705 * @NL80211_CMD_MAX: highest used command number
697 * @__NL80211_CMD_AFTER_LAST: internal use 706 * @__NL80211_CMD_AFTER_LAST: internal use
698 */ 707 */
@@ -860,6 +869,8 @@ enum nl80211_commands {
860 869
861 NL80211_CMD_CHANNEL_SWITCH, 870 NL80211_CMD_CHANNEL_SWITCH,
862 871
872 NL80211_CMD_VENDOR,
873
863 /* add new commands above here */ 874 /* add new commands above here */
864 875
865 /* used to define NL80211_CMD_MAX below */ 876 /* used to define NL80211_CMD_MAX below */
@@ -1524,6 +1535,12 @@ enum nl80211_commands {
1524 * Notification Element based on association request when used with 1535 * Notification Element based on association request when used with
1525 * %NL80211_CMD_NEW_STATION; u8 attribute. 1536 * %NL80211_CMD_NEW_STATION; u8 attribute.
1526 * 1537 *
1538 * @NL80211_ATTR_VENDOR_ID: The vendor ID, either a 24-bit OUI or, if
1539 * %NL80211_VENDOR_ID_IS_LINUX is set, a special Linux ID (not used yet)
1540 * @NL80211_ATTR_VENDOR_SUBCMD: vendor sub-command
1541 * @NL80211_ATTR_VENDOR_DATA: data for the vendor command, if any; this
1542 * attribute is also used for vendor command feature advertisement
1543 *
1527 * @NL80211_ATTR_MAX: highest attribute number currently defined 1544 * @NL80211_ATTR_MAX: highest attribute number currently defined
1528 * @__NL80211_ATTR_AFTER_LAST: internal use 1545 * @__NL80211_ATTR_AFTER_LAST: internal use
1529 */ 1546 */
@@ -1845,6 +1862,10 @@ enum nl80211_attrs {
1845 1862
1846 NL80211_ATTR_OPMODE_NOTIF, 1863 NL80211_ATTR_OPMODE_NOTIF,
1847 1864
1865 NL80211_ATTR_VENDOR_ID,
1866 NL80211_ATTR_VENDOR_SUBCMD,
1867 NL80211_ATTR_VENDOR_DATA,
1868
1848 /* add attributes here, update the policy in nl80211.c */ 1869 /* add attributes here, update the policy in nl80211.c */
1849 1870
1850 __NL80211_ATTR_AFTER_LAST, 1871 __NL80211_ATTR_AFTER_LAST,
@@ -3965,4 +3986,24 @@ enum nl80211_rxmgmt_flags {
3965 NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0, 3986 NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0,
3966}; 3987};
3967 3988
3989/*
3990 * If this flag is unset, the lower 24 bits are an OUI, if set
3991 * a Linux nl80211 vendor ID is used (no such IDs are allocated
3992 * yet, so that's not valid so far)
3993 */
3994#define NL80211_VENDOR_ID_IS_LINUX 0x80000000
3995
3996/**
3997 * struct nl80211_vendor_cmd_info - vendor command data
3998 * @vendor_id: If the %NL80211_VENDOR_ID_IS_LINUX flag is clear, then the
3999 * value is a 24-bit OUI; if it is set then a separately allocated ID
4000 * may be used, but no such IDs are allocated yet. New IDs should be
4001 * added to this file when needed.
4002 * @subcmd: sub-command ID for the command
4003 */
4004struct nl80211_vendor_cmd_info {
4005 __u32 vendor_id;
4006 __u32 subcmd;
4007};
4008
3968#endif /* __LINUX_NL80211_H */ 4009#endif /* __LINUX_NL80211_H */
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 06265d7f8cc3..4a376a724153 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -642,6 +642,17 @@ void ieee80211_iterate_active_interfaces_rtnl(
642} 642}
643EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl); 643EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl);
644 644
645struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev)
646{
647 struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
648
649 if (!ieee80211_sdata_running(sdata) ||
650 !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
651 return NULL;
652 return &sdata->vif;
653}
654EXPORT_SYMBOL_GPL(wdev_to_ieee80211_vif);
655
645/* 656/*
646 * Nothing should have been stuffed into the workqueue during 657 * Nothing should have been stuffed into the workqueue during
647 * the suspend->resume cycle. If this WARN is seen then there 658 * the suspend->resume cycle. If this WARN is seen then there
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 6716c5c3f748..ac77644cf894 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -67,9 +67,7 @@ struct cfg80211_registered_device {
67 struct work_struct scan_done_wk; 67 struct work_struct scan_done_wk;
68 struct work_struct sched_scan_results_wk; 68 struct work_struct sched_scan_results_wk;
69 69
70#ifdef CONFIG_NL80211_TESTMODE 70 struct genl_info *cur_cmd_info;
71 struct genl_info *testmode_info;
72#endif
73 71
74 struct work_struct conn_work; 72 struct work_struct conn_work;
75 struct work_struct event_work; 73 struct work_struct event_work;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index bdcf256e3628..6989989de092 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -358,6 +358,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
358 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY }, 358 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
359 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG }, 359 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
360 [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 }, 360 [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
361 [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
362 [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
363 [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
361}; 364};
362 365
363/* policy for the key attributes */ 366/* policy for the key attributes */
@@ -1166,6 +1169,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1166 struct nlattr *nl_bands, *nl_band; 1169 struct nlattr *nl_bands, *nl_band;
1167 struct nlattr *nl_freqs, *nl_freq; 1170 struct nlattr *nl_freqs, *nl_freq;
1168 struct nlattr *nl_cmds; 1171 struct nlattr *nl_cmds;
1172 struct nlattr *nl_vendor_cmds;
1169 enum ieee80211_band band; 1173 enum ieee80211_band band;
1170 struct ieee80211_channel *chan; 1174 struct ieee80211_channel *chan;
1171 int i; 1175 int i;
@@ -1561,6 +1565,19 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1561 (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) || 1565 (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
1562 nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ))) 1566 nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
1563 goto nla_put_failure; 1567 goto nla_put_failure;
1568 state->split_start++;
1569 break;
1570 case 11:
1571 nl_vendor_cmds = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
1572 if (!nl_vendor_cmds)
1573 goto nla_put_failure;
1574
1575 for (i = 0; i < dev->wiphy.n_vendor_commands; i++)
1576 if (nla_put(msg, i + 1,
1577 sizeof(struct nl80211_vendor_cmd_info),
1578 &dev->wiphy.vendor_commands[i].info))
1579 goto nla_put_failure;
1580 nla_nest_end(msg, nl_vendor_cmds);
1564 1581
1565 /* done */ 1582 /* done */
1566 state->split_start = 0; 1583 state->split_start = 0;
@@ -6682,6 +6699,40 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
6682 return err; 6699 return err;
6683} 6700}
6684 6701
6702static struct sk_buff *
6703__cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
6704 int approxlen, u32 portid, u32 seq,
6705 enum nl80211_commands cmd,
6706 enum nl80211_attrs attr, gfp_t gfp)
6707{
6708 struct sk_buff *skb;
6709 void *hdr;
6710 struct nlattr *data;
6711
6712 skb = nlmsg_new(approxlen + 100, gfp);
6713 if (!skb)
6714 return NULL;
6715
6716 hdr = nl80211hdr_put(skb, portid, seq, 0, cmd);
6717 if (!hdr) {
6718 kfree_skb(skb);
6719 return NULL;
6720 }
6721
6722 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
6723 goto nla_put_failure;
6724 data = nla_nest_start(skb, attr);
6725
6726 ((void **)skb->cb)[0] = rdev;
6727 ((void **)skb->cb)[1] = hdr;
6728 ((void **)skb->cb)[2] = data;
6729
6730 return skb;
6731
6732 nla_put_failure:
6733 kfree_skb(skb);
6734 return NULL;
6735}
6685 6736
6686#ifdef CONFIG_NL80211_TESTMODE 6737#ifdef CONFIG_NL80211_TESTMODE
6687static struct genl_multicast_group nl80211_testmode_mcgrp = { 6738static struct genl_multicast_group nl80211_testmode_mcgrp = {
@@ -6710,11 +6761,11 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
6710 if (!info->attrs[NL80211_ATTR_TESTDATA]) 6761 if (!info->attrs[NL80211_ATTR_TESTDATA])
6711 return -EINVAL; 6762 return -EINVAL;
6712 6763
6713 rdev->testmode_info = info; 6764 rdev->cur_cmd_info = info;
6714 err = rdev_testmode_cmd(rdev, wdev, 6765 err = rdev_testmode_cmd(rdev, wdev,
6715 nla_data(info->attrs[NL80211_ATTR_TESTDATA]), 6766 nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
6716 nla_len(info->attrs[NL80211_ATTR_TESTDATA])); 6767 nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
6717 rdev->testmode_info = NULL; 6768 rdev->cur_cmd_info = NULL;
6718 6769
6719 return err; 6770 return err;
6720} 6771}
@@ -6814,77 +6865,14 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
6814 return err; 6865 return err;
6815} 6866}
6816 6867
6817static struct sk_buff *
6818__cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev,
6819 int approxlen, u32 portid, u32 seq, gfp_t gfp)
6820{
6821 struct sk_buff *skb;
6822 void *hdr;
6823 struct nlattr *data;
6824
6825 skb = nlmsg_new(approxlen + 100, gfp);
6826 if (!skb)
6827 return NULL;
6828
6829 hdr = nl80211hdr_put(skb, portid, seq, 0, NL80211_CMD_TESTMODE);
6830 if (!hdr) {
6831 kfree_skb(skb);
6832 return NULL;
6833 }
6834
6835 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
6836 goto nla_put_failure;
6837 data = nla_nest_start(skb, NL80211_ATTR_TESTDATA);
6838
6839 ((void **)skb->cb)[0] = rdev;
6840 ((void **)skb->cb)[1] = hdr;
6841 ((void **)skb->cb)[2] = data;
6842
6843 return skb;
6844
6845 nla_put_failure:
6846 kfree_skb(skb);
6847 return NULL;
6848}
6849
6850struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
6851 int approxlen)
6852{
6853 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
6854
6855 if (WARN_ON(!rdev->testmode_info))
6856 return NULL;
6857
6858 return __cfg80211_testmode_alloc_skb(rdev, approxlen,
6859 rdev->testmode_info->snd_portid,
6860 rdev->testmode_info->snd_seq,
6861 GFP_KERNEL);
6862}
6863EXPORT_SYMBOL(cfg80211_testmode_alloc_reply_skb);
6864
6865int cfg80211_testmode_reply(struct sk_buff *skb)
6866{
6867 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
6868 void *hdr = ((void **)skb->cb)[1];
6869 struct nlattr *data = ((void **)skb->cb)[2];
6870
6871 if (WARN_ON(!rdev->testmode_info)) {
6872 kfree_skb(skb);
6873 return -EINVAL;
6874 }
6875
6876 nla_nest_end(skb, data);
6877 genlmsg_end(skb, hdr);
6878 return genlmsg_reply(skb, rdev->testmode_info);
6879}
6880EXPORT_SYMBOL(cfg80211_testmode_reply);
6881
6882struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, 6868struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
6883 int approxlen, gfp_t gfp) 6869 int approxlen, gfp_t gfp)
6884{ 6870{
6885 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 6871 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
6886 6872
6887 return __cfg80211_testmode_alloc_skb(rdev, approxlen, 0, 0, gfp); 6873 return __cfg80211_alloc_vendor_skb(rdev, approxlen, 0, 0,
6874 NL80211_CMD_TESTMODE,
6875 NL80211_ATTR_TESTDATA, gfp);
6888} 6876}
6889EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb); 6877EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb);
6890 6878
@@ -8867,6 +8855,111 @@ static int nl80211_crit_protocol_stop(struct sk_buff *skb,
8867 return 0; 8855 return 0;
8868} 8856}
8869 8857
8858static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
8859{
8860 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8861 struct wireless_dev *wdev =
8862 __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
8863 int i, err;
8864 u32 vid, subcmd;
8865
8866 if (!rdev->wiphy.vendor_commands)
8867 return -EOPNOTSUPP;
8868
8869 if (IS_ERR(wdev)) {
8870 err = PTR_ERR(wdev);
8871 if (err != -EINVAL)
8872 return err;
8873 wdev = NULL;
8874 } else if (wdev->wiphy != &rdev->wiphy) {
8875 return -EINVAL;
8876 }
8877
8878 if (!info->attrs[NL80211_ATTR_VENDOR_ID] ||
8879 !info->attrs[NL80211_ATTR_VENDOR_SUBCMD])
8880 return -EINVAL;
8881
8882 vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]);
8883 subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]);
8884 for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
8885 const struct wiphy_vendor_command *vcmd;
8886 void *data = NULL;
8887 int len = 0;
8888
8889 vcmd = &rdev->wiphy.vendor_commands[i];
8890
8891 if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
8892 continue;
8893
8894 if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
8895 WIPHY_VENDOR_CMD_NEED_NETDEV)) {
8896 if (!wdev)
8897 return -EINVAL;
8898 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
8899 !wdev->netdev)
8900 return -EINVAL;
8901
8902 if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
8903 if (wdev->netdev &&
8904 !netif_running(wdev->netdev))
8905 return -ENETDOWN;
8906 if (!wdev->netdev && !wdev->p2p_started)
8907 return -ENETDOWN;
8908 }
8909 } else {
8910 wdev = NULL;
8911 }
8912
8913 if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
8914 data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
8915 len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
8916 }
8917
8918 rdev->cur_cmd_info = info;
8919 err = rdev->wiphy.vendor_commands[i].doit(&rdev->wiphy, wdev,
8920 data, len);
8921 rdev->cur_cmd_info = NULL;
8922 return err;
8923 }
8924
8925 return -EOPNOTSUPP;
8926}
8927
8928struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
8929 enum nl80211_commands cmd,
8930 enum nl80211_attrs attr,
8931 int approxlen)
8932{
8933 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
8934
8935 if (WARN_ON(!rdev->cur_cmd_info))
8936 return NULL;
8937
8938 return __cfg80211_alloc_vendor_skb(rdev, approxlen,
8939 rdev->cur_cmd_info->snd_portid,
8940 rdev->cur_cmd_info->snd_seq,
8941 cmd, attr, GFP_KERNEL);
8942}
8943EXPORT_SYMBOL(__cfg80211_alloc_reply_skb);
8944
8945int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
8946{
8947 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
8948 void *hdr = ((void **)skb->cb)[1];
8949 struct nlattr *data = ((void **)skb->cb)[2];
8950
8951 if (WARN_ON(!rdev->cur_cmd_info)) {
8952 kfree_skb(skb);
8953 return -EINVAL;
8954 }
8955
8956 nla_nest_end(skb, data);
8957 genlmsg_end(skb, hdr);
8958 return genlmsg_reply(skb, rdev->cur_cmd_info);
8959}
8960EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
8961
8962
8870#define NL80211_FLAG_NEED_WIPHY 0x01 8963#define NL80211_FLAG_NEED_WIPHY 0x01
8871#define NL80211_FLAG_NEED_NETDEV 0x02 8964#define NL80211_FLAG_NEED_NETDEV 0x02
8872#define NL80211_FLAG_NEED_RTNL 0x04 8965#define NL80211_FLAG_NEED_RTNL 0x04
@@ -9591,6 +9684,14 @@ static struct genl_ops nl80211_ops[] = {
9591 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 9684 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
9592 NL80211_FLAG_NEED_RTNL, 9685 NL80211_FLAG_NEED_RTNL,
9593 }, 9686 },
9687 {
9688 .cmd = NL80211_CMD_VENDOR,
9689 .doit = nl80211_vendor_cmd,
9690 .policy = nl80211_policy,
9691 .flags = GENL_ADMIN_PERM,
9692 .internal_flags = NL80211_FLAG_NEED_WIPHY |
9693 NL80211_FLAG_NEED_RTNL,
9694 },
9594}; 9695};
9595 9696
9596static struct genl_multicast_group nl80211_mlme_mcgrp = { 9697static struct genl_multicast_group nl80211_mlme_mcgrp = {