fix up hostapd for mac80211
[openwrt/openwrt.git] / package / mac80211 / patches / 024-nl80211-get-sta.patch
1 Subject: cfg80211/nl80211: implement station attribute retrieval
2
3 After a station is added to the kernel's structures, userspace
4 has to be able to retrieve statistics about that station, especially
5 whether the station was idle and how much bytes were transferred
6 to and from it. This adds the necessary code to nl80211.
7
8 Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
9
10 ---
11 include/linux/nl80211.h | 28 ++++++++++++++++
12 include/net/cfg80211.h | 35 ++++++++++++++++++++
13 net/wireless/nl80211.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++-
14 3 files changed, 144 insertions(+), 1 deletion(-)
15
16 --- everything.orig/include/linux/nl80211.h 2007-11-08 17:15:15.961529840 +0100
17 +++ everything/include/linux/nl80211.h 2007-11-08 17:17:00.891547364 +0100
18 @@ -157,6 +157,9 @@ enum nl80211_commands {
19 * restriction (at most %NL80211_MAX_SUPP_RATES).
20 * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station
21 * to, or the AP interface the station was originally added to to.
22 + * @NL80211_ATTR_STA_STATS: statistics for a station, part of station info
23 + * given for %NL80211_CMD_GET_STATION, nested attribute containing
24 + * info as possible, see &enum nl80211_sta_stats.
25 *
26 * @NL80211_ATTR_MAX: highest attribute number currently defined
27 * @__NL80211_ATTR_AFTER_LAST: internal use
28 @@ -190,6 +193,7 @@ enum nl80211_attrs {
29 NL80211_ATTR_STA_LISTEN_INTERVAL,
30 NL80211_ATTR_STA_SUPPORTED_RATES,
31 NL80211_ATTR_STA_VLAN,
32 + NL80211_ATTR_STA_STATS,
33
34 /* add attributes here, update the policy in nl80211.c */
35
36 @@ -252,4 +256,28 @@ enum nl80211_sta_flags {
37 NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1
38 };
39
40 +/**
41 + * enum nl80211_sta_stats - station statistics
42 + *
43 + * These attribute types are used with %NL80211_ATTR_STA_STATS
44 + * when getting information about a station.
45 + *
46 + * @__NL80211_STA_STAT_INVALID: attribute number 0 is reserved
47 + * @NL80211_STA_STAT_INACTIVE_TIME: time since last activity (u32, msecs)
48 + * @NL80211_STA_STAT_RX_BYTES: total received bytes (u32, from this station)
49 + * @NL80211_STA_STAT_TX_BYTES: total transmitted bytes (u32, to this station)
50 + * @__NL80211_STA_STAT_AFTER_LAST: internal
51 + * @NL80211_STA_STAT_MAX: highest possible station stats attribute
52 + */
53 +enum nl80211_sta_stats {
54 + __NL80211_STA_STAT_INVALID,
55 + NL80211_STA_STAT_INACTIVE_TIME,
56 + NL80211_STA_STAT_RX_BYTES,
57 + NL80211_STA_STAT_TX_BYTES,
58 +
59 + /* keep last */
60 + __NL80211_STA_STAT_AFTER_LAST,
61 + NL80211_STA_STAT_MAX = __NL80211_STA_STAT_AFTER_LAST - 1
62 +};
63 +
64 #endif /* __LINUX_NL80211_H */
65 --- everything.orig/include/net/cfg80211.h 2007-11-08 17:15:15.971532444 +0100
66 +++ everything/include/net/cfg80211.h 2007-11-08 17:17:00.891547364 +0100
67 @@ -130,6 +130,39 @@ struct station_parameters {
68 u8 supported_rates_len;
69 };
70
71 +/**
72 + * enum station_stats_flags - station statistics flags
73 + *
74 + * Used by the driver to indicate which info in &struct station_stats
75 + * it has filled in during get_station().
76 + *
77 + * @STATION_STAT_INACTIVE_TIME: @inactive_time filled
78 + * @STATION_STAT_RX_BYTES: @rx_bytes filled
79 + * @STATION_STAT_TX_BYTES: @tx_bytes filled
80 + */
81 +enum station_stats_flags {
82 + STATION_STAT_INACTIVE_TIME = 1<<0,
83 + STATION_STAT_RX_BYTES = 1<<1,
84 + STATION_STAT_TX_BYTES = 1<<2,
85 +};
86 +
87 +/**
88 + * struct station_stats - station statistics
89 + *
90 + * Station information filled by driver for get_station().
91 + *
92 + * @filled: bitflag of flags from &enum station_stats_flags
93 + * @inactive_time: time since last station activity (tx/rx) in milliseconds
94 + * @rx_bytes: bytes received from this station
95 + * @tx_bytes: bytes transmitted to this station
96 + */
97 +struct station_stats {
98 + u32 filled;
99 + u32 inactive_time;
100 + u32 rx_bytes;
101 + u32 tx_bytes;
102 +};
103 +
104 /* from net/wireless.h */
105 struct wiphy;
106
107 @@ -209,6 +242,8 @@ struct cfg80211_ops {
108 u8 *mac);
109 int (*change_station)(struct wiphy *wiphy, struct net_device *dev,
110 u8 *mac, struct station_parameters *params);
111 + int (*get_station)(struct wiphy *wiphy, struct net_device *dev,
112 + u8 *mac, struct station_stats *stats);
113 };
114
115 #endif /* __NET_CFG80211_H */
116 --- everything.orig/net/wireless/nl80211.c 2007-11-08 17:15:15.981533909 +0100
117 +++ everything/net/wireless/nl80211.c 2007-11-08 17:17:00.901534235 +0100
118 @@ -751,9 +751,89 @@ static int parse_station_flags(struct nl
119 return 0;
120 }
121
122 +static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
123 + int flags, struct net_device *dev,
124 + u8 *mac_addr, struct station_stats *stats)
125 +{
126 + void *hdr;
127 + struct nlattr *statsattr;
128 +
129 + hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
130 + if (!hdr)
131 + return -1;
132 +
133 + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
134 + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
135 +
136 + statsattr = nla_nest_start(msg, NL80211_ATTR_STA_STATS);
137 + if (!statsattr)
138 + goto nla_put_failure;
139 + if (stats->filled & STATION_STAT_INACTIVE_TIME)
140 + NLA_PUT_U32(msg, NL80211_STA_STAT_INACTIVE_TIME,
141 + stats->inactive_time);
142 + if (stats->filled & STATION_STAT_RX_BYTES)
143 + NLA_PUT_U32(msg, NL80211_STA_STAT_RX_BYTES,
144 + stats->rx_bytes);
145 + if (stats->filled & STATION_STAT_TX_BYTES)
146 + NLA_PUT_U32(msg, NL80211_STA_STAT_TX_BYTES,
147 + stats->tx_bytes);
148 +
149 + nla_nest_end(msg, statsattr);
150 +
151 + return genlmsg_end(msg, hdr);
152 +
153 + nla_put_failure:
154 + return genlmsg_cancel(msg, hdr);
155 +}
156 +
157 +
158 static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
159 {
160 - return -EOPNOTSUPP;
161 + struct cfg80211_registered_device *drv;
162 + int err;
163 + struct net_device *dev;
164 + struct station_stats stats;
165 + struct sk_buff *msg;
166 + u8 *mac_addr = NULL;
167 +
168 + memset(&stats, 0, sizeof(stats));
169 +
170 + if (!info->attrs[NL80211_ATTR_MAC])
171 + return -EINVAL;
172 +
173 + mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
174 +
175 + err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
176 + if (err)
177 + return err;
178 +
179 + if (!drv->ops->get_station) {
180 + err = -EOPNOTSUPP;
181 + goto out;
182 + }
183 +
184 + rtnl_lock();
185 + err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &stats);
186 + rtnl_unlock();
187 +
188 + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
189 + if (!msg)
190 + goto out;
191 +
192 + if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
193 + dev, mac_addr, &stats) < 0)
194 + goto out_free;
195 +
196 + err = genlmsg_unicast(msg, info->snd_pid);
197 + goto out;
198 +
199 + out_free:
200 + nlmsg_free(msg);
201 +
202 + out:
203 + cfg80211_put_dev(drv);
204 + dev_put(dev);
205 + return err;
206 }
207
208 /*