diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2007-12-18 20:03:34 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:59:51 -0500 |
commit | 5727ef1b2e797a1922f5bc239b6afb2b4cfb80bc (patch) | |
tree | 16fb0c8afcb1c5282fcc45ffa90c8e34b0daa6d4 | |
parent | ed1b6cc7f80f831e192704b05b9917f9cc37be15 (diff) |
cfg80211/nl80211: station handling
This patch adds station handling to cfg80211/nl80211.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/nl80211.h | 68 | ||||
-rw-r--r-- | include/net/cfg80211.h | 55 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 235 |
3 files changed, 358 insertions, 0 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index f1e455a8b4de..85e2d7d1f9e3 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -7,6 +7,18 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | /** | 9 | /** |
10 | * DOC: Station handling | ||
11 | * | ||
12 | * Stations are added per interface, but a special case exists with VLAN | ||
13 | * interfaces. When a station is bound to an AP interface, it may be moved | ||
14 | * into a VLAN identified by a VLAN interface index (%NL80211_ATTR_STA_VLAN). | ||
15 | * The station is still assumed to belong to the AP interface it was added | ||
16 | * to. | ||
17 | * | ||
18 | * TODO: need more info? | ||
19 | */ | ||
20 | |||
21 | /** | ||
10 | * enum nl80211_commands - supported nl80211 commands | 22 | * enum nl80211_commands - supported nl80211 commands |
11 | * | 23 | * |
12 | * @NL80211_CMD_UNSPEC: unspecified command to catch errors | 24 | * @NL80211_CMD_UNSPEC: unspecified command to catch errors |
@@ -56,6 +68,16 @@ | |||
56 | * parameters are like for %NL80211_CMD_SET_BEACON. | 68 | * parameters are like for %NL80211_CMD_SET_BEACON. |
57 | * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it | 69 | * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it |
58 | * | 70 | * |
71 | * @NL80211_CMD_GET_STATION: Get station attributes for station identified by | ||
72 | * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. | ||
73 | * @NL80211_CMD_SET_STATION: Set station attributes for station identified by | ||
74 | * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. | ||
75 | * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the | ||
76 | * the interface identified by %NL80211_ATTR_IFINDEX. | ||
77 | * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC | ||
78 | * or, if no MAC address given, all stations, on the interface identified | ||
79 | * by %NL80211_ATTR_IFINDEX. | ||
80 | * | ||
59 | * @NL80211_CMD_MAX: highest used command number | 81 | * @NL80211_CMD_MAX: highest used command number |
60 | * @__NL80211_CMD_AFTER_LAST: internal use | 82 | * @__NL80211_CMD_AFTER_LAST: internal use |
61 | */ | 83 | */ |
@@ -83,6 +105,11 @@ enum nl80211_commands { | |||
83 | NL80211_CMD_NEW_BEACON, | 105 | NL80211_CMD_NEW_BEACON, |
84 | NL80211_CMD_DEL_BEACON, | 106 | NL80211_CMD_DEL_BEACON, |
85 | 107 | ||
108 | NL80211_CMD_GET_STATION, | ||
109 | NL80211_CMD_SET_STATION, | ||
110 | NL80211_CMD_NEW_STATION, | ||
111 | NL80211_CMD_DEL_STATION, | ||
112 | |||
86 | /* add commands here */ | 113 | /* add commands here */ |
87 | 114 | ||
88 | /* used to define NL80211_CMD_MAX below */ | 115 | /* used to define NL80211_CMD_MAX below */ |
@@ -120,6 +147,17 @@ enum nl80211_commands { | |||
120 | * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE | 147 | * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE |
121 | * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE | 148 | * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE |
122 | * | 149 | * |
150 | * @NL80211_ATTR_STA_AID: Association ID for the station (u16) | ||
151 | * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of | ||
152 | * &enum nl80211_sta_flags. | ||
153 | * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by | ||
154 | * IEEE 802.11 7.3.1.6 (u16). | ||
155 | * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported | ||
156 | * rates as defined by IEEE 802.11 7.3.2.2 but without the length | ||
157 | * restriction (at most %NL80211_MAX_SUPP_RATES). | ||
158 | * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station | ||
159 | * to, or the AP interface the station was originally added to to. | ||
160 | * | ||
123 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 161 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
124 | * @__NL80211_ATTR_AFTER_LAST: internal use | 162 | * @__NL80211_ATTR_AFTER_LAST: internal use |
125 | */ | 163 | */ |
@@ -147,12 +185,20 @@ enum nl80211_attrs { | |||
147 | NL80211_ATTR_BEACON_HEAD, | 185 | NL80211_ATTR_BEACON_HEAD, |
148 | NL80211_ATTR_BEACON_TAIL, | 186 | NL80211_ATTR_BEACON_TAIL, |
149 | 187 | ||
188 | NL80211_ATTR_STA_AID, | ||
189 | NL80211_ATTR_STA_FLAGS, | ||
190 | NL80211_ATTR_STA_LISTEN_INTERVAL, | ||
191 | NL80211_ATTR_STA_SUPPORTED_RATES, | ||
192 | NL80211_ATTR_STA_VLAN, | ||
193 | |||
150 | /* add attributes here, update the policy in nl80211.c */ | 194 | /* add attributes here, update the policy in nl80211.c */ |
151 | 195 | ||
152 | __NL80211_ATTR_AFTER_LAST, | 196 | __NL80211_ATTR_AFTER_LAST, |
153 | NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 | 197 | NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 |
154 | }; | 198 | }; |
155 | 199 | ||
200 | #define NL80211_MAX_SUPP_RATES 32 | ||
201 | |||
156 | /** | 202 | /** |
157 | * enum nl80211_iftype - (virtual) interface types | 203 | * enum nl80211_iftype - (virtual) interface types |
158 | * | 204 | * |
@@ -184,4 +230,26 @@ enum nl80211_iftype { | |||
184 | NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1 | 230 | NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1 |
185 | }; | 231 | }; |
186 | 232 | ||
233 | /** | ||
234 | * enum nl80211_sta_flags - station flags | ||
235 | * | ||
236 | * Station flags. When a station is added to an AP interface, it is | ||
237 | * assumed to be already associated (and hence authenticated.) | ||
238 | * | ||
239 | * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) | ||
240 | * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames | ||
241 | * with short barker preamble | ||
242 | * @NL80211_STA_FLAG_WME: station is WME/QoS capable | ||
243 | */ | ||
244 | enum nl80211_sta_flags { | ||
245 | __NL80211_STA_FLAG_INVALID, | ||
246 | NL80211_STA_FLAG_AUTHORIZED, | ||
247 | NL80211_STA_FLAG_SHORT_PREAMBLE, | ||
248 | NL80211_STA_FLAG_WME, | ||
249 | |||
250 | /* keep last */ | ||
251 | __NL80211_STA_FLAG_AFTER_LAST, | ||
252 | NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 | ||
253 | }; | ||
254 | |||
187 | #endif /* __LINUX_NL80211_H */ | 255 | #endif /* __LINUX_NL80211_H */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index fc94852e967b..df650935e268 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -89,6 +89,47 @@ struct beacon_parameters { | |||
89 | int head_len, tail_len; | 89 | int head_len, tail_len; |
90 | }; | 90 | }; |
91 | 91 | ||
92 | /** | ||
93 | * enum station_flags - station flags | ||
94 | * | ||
95 | * Station capability flags. Note that these must be the bits | ||
96 | * according to the nl80211 flags. | ||
97 | * | ||
98 | * @STATION_FLAG_CHANGED: station flags were changed | ||
99 | * @STATION_FLAG_AUTHORIZED: station is authorized to send frames (802.1X) | ||
100 | * @STATION_FLAG_SHORT_PREAMBLE: station is capable of receiving frames | ||
101 | * with short preambles | ||
102 | * @STATION_FLAG_WME: station is WME/QoS capable | ||
103 | */ | ||
104 | enum station_flags { | ||
105 | STATION_FLAG_CHANGED = 1<<0, | ||
106 | STATION_FLAG_AUTHORIZED = 1<<NL80211_STA_FLAG_AUTHORIZED, | ||
107 | STATION_FLAG_SHORT_PREAMBLE = 1<<NL80211_STA_FLAG_SHORT_PREAMBLE, | ||
108 | STATION_FLAG_WME = 1<<NL80211_STA_FLAG_WME, | ||
109 | }; | ||
110 | |||
111 | /** | ||
112 | * struct station_parameters - station parameters | ||
113 | * | ||
114 | * Used to change and create a new station. | ||
115 | * | ||
116 | * @vlan: vlan interface station should belong to | ||
117 | * @supported_rates: supported rates in IEEE 802.11 format | ||
118 | * (or NULL for no change) | ||
119 | * @supported_rates_len: number of supported rates | ||
120 | * @station_flags: station flags (see &enum station_flags) | ||
121 | * @listen_interval: listen interval or -1 for no change | ||
122 | * @aid: AID or zero for no change | ||
123 | */ | ||
124 | struct station_parameters { | ||
125 | u8 *supported_rates; | ||
126 | struct net_device *vlan; | ||
127 | u32 station_flags; | ||
128 | int listen_interval; | ||
129 | u16 aid; | ||
130 | u8 supported_rates_len; | ||
131 | }; | ||
132 | |||
92 | /* from net/wireless.h */ | 133 | /* from net/wireless.h */ |
93 | struct wiphy; | 134 | struct wiphy; |
94 | 135 | ||
@@ -130,6 +171,12 @@ struct wiphy; | |||
130 | * interface. This should reject the call when no beacon has been | 171 | * interface. This should reject the call when no beacon has been |
131 | * configured. | 172 | * configured. |
132 | * @del_beacon: Remove beacon configuration and stop sending the beacon. | 173 | * @del_beacon: Remove beacon configuration and stop sending the beacon. |
174 | * | ||
175 | * @add_station: Add a new station. | ||
176 | * | ||
177 | * @del_station: Remove a station; @mac may be NULL to remove all stations. | ||
178 | * | ||
179 | * @change_station: Modify a given station. | ||
133 | */ | 180 | */ |
134 | struct cfg80211_ops { | 181 | struct cfg80211_ops { |
135 | int (*add_virtual_intf)(struct wiphy *wiphy, char *name, | 182 | int (*add_virtual_intf)(struct wiphy *wiphy, char *name, |
@@ -155,6 +202,14 @@ struct cfg80211_ops { | |||
155 | int (*set_beacon)(struct wiphy *wiphy, struct net_device *dev, | 202 | int (*set_beacon)(struct wiphy *wiphy, struct net_device *dev, |
156 | struct beacon_parameters *info); | 203 | struct beacon_parameters *info); |
157 | int (*del_beacon)(struct wiphy *wiphy, struct net_device *dev); | 204 | int (*del_beacon)(struct wiphy *wiphy, struct net_device *dev); |
205 | |||
206 | |||
207 | int (*add_station)(struct wiphy *wiphy, struct net_device *dev, | ||
208 | u8 *mac, struct station_parameters *params); | ||
209 | int (*del_station)(struct wiphy *wiphy, struct net_device *dev, | ||
210 | u8 *mac); | ||
211 | int (*change_station)(struct wiphy *wiphy, struct net_device *dev, | ||
212 | u8 *mac, struct station_parameters *params); | ||
158 | }; | 213 | }; |
159 | 214 | ||
160 | #endif /* __NET_CFG80211_H */ | 215 | #endif /* __NET_CFG80211_H */ |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 306ae019ea81..431835126e88 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -76,6 +76,12 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
76 | .len = IEEE80211_MAX_DATA_LEN }, | 76 | .len = IEEE80211_MAX_DATA_LEN }, |
77 | [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY, | 77 | [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY, |
78 | .len = IEEE80211_MAX_DATA_LEN }, | 78 | .len = IEEE80211_MAX_DATA_LEN }, |
79 | [NL80211_ATTR_STA_AID] = { .type = NLA_U16 }, | ||
80 | [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED }, | ||
81 | [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 }, | ||
82 | [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY, | ||
83 | .len = NL80211_MAX_SUPP_RATES }, | ||
84 | [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 }, | ||
79 | }; | 85 | }; |
80 | 86 | ||
81 | /* message building helper */ | 87 | /* message building helper */ |
@@ -715,6 +721,210 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) | |||
715 | return err; | 721 | return err; |
716 | } | 722 | } |
717 | 723 | ||
724 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | ||
725 | [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG }, | ||
726 | [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG }, | ||
727 | [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG }, | ||
728 | }; | ||
729 | |||
730 | static int parse_station_flags(struct nlattr *nla, u32 *staflags) | ||
731 | { | ||
732 | struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; | ||
733 | int flag; | ||
734 | |||
735 | *staflags = 0; | ||
736 | |||
737 | if (!nla) | ||
738 | return 0; | ||
739 | |||
740 | if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX, | ||
741 | nla, sta_flags_policy)) | ||
742 | return -EINVAL; | ||
743 | |||
744 | *staflags = STATION_FLAG_CHANGED; | ||
745 | |||
746 | for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) | ||
747 | if (flags[flag]) | ||
748 | *staflags |= (1<<flag); | ||
749 | |||
750 | return 0; | ||
751 | } | ||
752 | |||
753 | static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | ||
754 | { | ||
755 | return -EOPNOTSUPP; | ||
756 | } | ||
757 | |||
758 | /* | ||
759 | * Get vlan interface making sure it is on the right wiphy. | ||
760 | */ | ||
761 | static int get_vlan(struct nlattr *vlanattr, | ||
762 | struct cfg80211_registered_device *rdev, | ||
763 | struct net_device **vlan) | ||
764 | { | ||
765 | *vlan = NULL; | ||
766 | |||
767 | if (vlanattr) { | ||
768 | *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr)); | ||
769 | if (!*vlan) | ||
770 | return -ENODEV; | ||
771 | if (!(*vlan)->ieee80211_ptr) | ||
772 | return -EINVAL; | ||
773 | if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy) | ||
774 | return -EINVAL; | ||
775 | } | ||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | ||
780 | { | ||
781 | struct cfg80211_registered_device *drv; | ||
782 | int err; | ||
783 | struct net_device *dev; | ||
784 | struct station_parameters params; | ||
785 | u8 *mac_addr = NULL; | ||
786 | |||
787 | memset(¶ms, 0, sizeof(params)); | ||
788 | |||
789 | params.listen_interval = -1; | ||
790 | |||
791 | if (info->attrs[NL80211_ATTR_STA_AID]) | ||
792 | return -EINVAL; | ||
793 | |||
794 | if (!info->attrs[NL80211_ATTR_MAC]) | ||
795 | return -EINVAL; | ||
796 | |||
797 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
798 | |||
799 | if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) { | ||
800 | params.supported_rates = | ||
801 | nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); | ||
802 | params.supported_rates_len = | ||
803 | nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); | ||
804 | } | ||
805 | |||
806 | if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) | ||
807 | params.listen_interval = | ||
808 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | ||
809 | |||
810 | if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], | ||
811 | ¶ms.station_flags)) | ||
812 | return -EINVAL; | ||
813 | |||
814 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | ||
815 | if (err) | ||
816 | return err; | ||
817 | |||
818 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); | ||
819 | if (err) | ||
820 | goto out; | ||
821 | |||
822 | if (!drv->ops->change_station) { | ||
823 | err = -EOPNOTSUPP; | ||
824 | goto out; | ||
825 | } | ||
826 | |||
827 | rtnl_lock(); | ||
828 | err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, ¶ms); | ||
829 | rtnl_unlock(); | ||
830 | |||
831 | out: | ||
832 | if (params.vlan) | ||
833 | dev_put(params.vlan); | ||
834 | cfg80211_put_dev(drv); | ||
835 | dev_put(dev); | ||
836 | return err; | ||
837 | } | ||
838 | |||
839 | static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | ||
840 | { | ||
841 | struct cfg80211_registered_device *drv; | ||
842 | int err; | ||
843 | struct net_device *dev; | ||
844 | struct station_parameters params; | ||
845 | u8 *mac_addr = NULL; | ||
846 | |||
847 | memset(¶ms, 0, sizeof(params)); | ||
848 | |||
849 | if (!info->attrs[NL80211_ATTR_MAC]) | ||
850 | return -EINVAL; | ||
851 | |||
852 | if (!info->attrs[NL80211_ATTR_STA_AID]) | ||
853 | return -EINVAL; | ||
854 | |||
855 | if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) | ||
856 | return -EINVAL; | ||
857 | |||
858 | if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) | ||
859 | return -EINVAL; | ||
860 | |||
861 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
862 | params.supported_rates = | ||
863 | nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); | ||
864 | params.supported_rates_len = | ||
865 | nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); | ||
866 | params.listen_interval = | ||
867 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | ||
868 | params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); | ||
869 | |||
870 | if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], | ||
871 | ¶ms.station_flags)) | ||
872 | return -EINVAL; | ||
873 | |||
874 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | ||
875 | if (err) | ||
876 | return err; | ||
877 | |||
878 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); | ||
879 | if (err) | ||
880 | goto out; | ||
881 | |||
882 | if (!drv->ops->add_station) { | ||
883 | err = -EOPNOTSUPP; | ||
884 | goto out; | ||
885 | } | ||
886 | |||
887 | rtnl_lock(); | ||
888 | err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, ¶ms); | ||
889 | rtnl_unlock(); | ||
890 | |||
891 | out: | ||
892 | if (params.vlan) | ||
893 | dev_put(params.vlan); | ||
894 | cfg80211_put_dev(drv); | ||
895 | dev_put(dev); | ||
896 | return err; | ||
897 | } | ||
898 | |||
899 | static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | ||
900 | { | ||
901 | struct cfg80211_registered_device *drv; | ||
902 | int err; | ||
903 | struct net_device *dev; | ||
904 | u8 *mac_addr = NULL; | ||
905 | |||
906 | if (info->attrs[NL80211_ATTR_MAC]) | ||
907 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
908 | |||
909 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | ||
910 | if (err) | ||
911 | return err; | ||
912 | |||
913 | if (!drv->ops->del_station) { | ||
914 | err = -EOPNOTSUPP; | ||
915 | goto out; | ||
916 | } | ||
917 | |||
918 | rtnl_lock(); | ||
919 | err = drv->ops->del_station(&drv->wiphy, dev, mac_addr); | ||
920 | rtnl_unlock(); | ||
921 | |||
922 | out: | ||
923 | cfg80211_put_dev(drv); | ||
924 | dev_put(dev); | ||
925 | return err; | ||
926 | } | ||
927 | |||
718 | static struct genl_ops nl80211_ops[] = { | 928 | static struct genl_ops nl80211_ops[] = { |
719 | { | 929 | { |
720 | .cmd = NL80211_CMD_GET_WIPHY, | 930 | .cmd = NL80211_CMD_GET_WIPHY, |
@@ -796,6 +1006,31 @@ static struct genl_ops nl80211_ops[] = { | |||
796 | .flags = GENL_ADMIN_PERM, | 1006 | .flags = GENL_ADMIN_PERM, |
797 | .doit = nl80211_del_beacon, | 1007 | .doit = nl80211_del_beacon, |
798 | }, | 1008 | }, |
1009 | { | ||
1010 | .cmd = NL80211_CMD_GET_STATION, | ||
1011 | .doit = nl80211_get_station, | ||
1012 | /* TODO: implement dumpit */ | ||
1013 | .policy = nl80211_policy, | ||
1014 | .flags = GENL_ADMIN_PERM, | ||
1015 | }, | ||
1016 | { | ||
1017 | .cmd = NL80211_CMD_SET_STATION, | ||
1018 | .doit = nl80211_set_station, | ||
1019 | .policy = nl80211_policy, | ||
1020 | .flags = GENL_ADMIN_PERM, | ||
1021 | }, | ||
1022 | { | ||
1023 | .cmd = NL80211_CMD_NEW_STATION, | ||
1024 | .doit = nl80211_new_station, | ||
1025 | .policy = nl80211_policy, | ||
1026 | .flags = GENL_ADMIN_PERM, | ||
1027 | }, | ||
1028 | { | ||
1029 | .cmd = NL80211_CMD_DEL_STATION, | ||
1030 | .doit = nl80211_del_station, | ||
1031 | .policy = nl80211_policy, | ||
1032 | .flags = GENL_ADMIN_PERM, | ||
1033 | }, | ||
799 | }; | 1034 | }; |
800 | 1035 | ||
801 | /* multicast groups */ | 1036 | /* multicast groups */ |