fix path to .config (#2722)
[oweals/openwrt.git] / package / hostapd / patches / 006-use-nl80211-for-sta.patch
1 ---
2  hostapd/driver_devicescape.c |  332 ++++++++++++++++++++++++++++++++-----------
3  1 file changed, 251 insertions(+), 81 deletions(-)
4
5 --- hostap.orig/hostapd/driver_devicescape.c    2007-11-14 17:31:15.000000000 +0100
6 +++ hostap/hostapd/driver_devicescape.c 2007-11-14 17:31:16.000000000 +0100
7 @@ -75,8 +75,14 @@ struct i802_driver_data {
8  
9  #define HAPD_DECL      struct hostapd_data *hapd = iface->bss[0]
10  
11 -static int i802_sta_set_flags(void *priv, const u8 *addr,
12 -                             int total_flags, int flags_or, int flags_and);
13 +/* helper for netlink get routines */
14 +static int ack_wait_handler(struct nl_msg *msg, void *arg)
15 +{
16 +       int *finished = arg;
17 +
18 +       *finished = 1;
19 +       return NL_STOP;
20 +}
21  
22  
23  static int hostapd_set_iface_flags(struct i802_driver_data *drv, int dev_up)
24 @@ -255,14 +261,6 @@ static int get_key_handler(struct nl_msg
25         return NL_SKIP;
26  }
27  
28 -static int ack_wait_handler(struct nl_msg *msg, void *arg)
29 -{
30 -       int *finished = arg;
31 -
32 -       *finished = 1;
33 -       return NL_STOP;
34 -}
35 -
36  static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
37                            int idx, u8 *seq)
38  {
39 @@ -629,43 +627,126 @@ static int i802_get_retry(void *priv, in
40  static int i802_flush(void *priv)
41  {
42         struct i802_driver_data *drv = priv;
43 -       struct prism2_hostapd_param param;
44 +       struct nl_msg *msg;
45 +       int ret = -1;
46  
47 -       memset(&param, 0, sizeof(param));
48 -       param.cmd = PRISM2_HOSTAPD_FLUSH;
49 -       return hostapd_ioctl(drv, &param, sizeof(param));
50 +       msg = nlmsg_alloc();
51 +       if (!msg)
52 +               goto out;
53 +
54 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
55 +                   0, NL80211_CMD_NEW_STATION, 0);
56 +
57 +       /*
58 +        * XXX: FIX! this needs to flush all VLANs too
59 +        */
60 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
61 +                   if_nametoindex(drv->iface));
62 +
63 +       ret = 0;
64 +
65 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
66 +           nl_wait_for_ack(drv->nl_handle) < 0) {
67 +               ret = -1;
68 +       }
69 +
70 + nla_put_failure:
71 +       nlmsg_free(msg);
72 +
73 + out:
74 +       return ret;
75  }
76  
77  
78 +static int get_sta_handler(struct nl_msg *msg, void *arg)
79 +{
80 +       struct nlattr *tb[NL80211_ATTR_MAX + 1];
81 +       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
82 +       struct hostap_sta_driver_data *data = arg;
83 +       struct nlattr *stats[NL80211_STA_STAT_MAX + 1];
84 +       static struct nla_policy stats_policy[NL80211_STA_STAT_MAX + 1] = {
85 +               [NL80211_STA_STAT_INACTIVE_TIME] = { .type = NLA_U32 },
86 +               [NL80211_STA_STAT_RX_BYTES] = { .type = NLA_U32 },
87 +               [NL80211_STA_STAT_TX_BYTES] = { .type = NLA_U32 },
88 +       };
89 +
90 +       nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
91 +                 genlmsg_attrlen(gnlh, 0), NULL);
92 +
93 +       /*
94 +        * TODO: validate the interface and mac address!
95 +        * Otherwise, there's a race condition as soon as
96 +        * the kernel starts sending station notifications.
97 +        */
98 +
99 +       if (!tb[NL80211_ATTR_STA_STATS]) {
100 +               printf("sta stats missing!\n");
101 +               return NL_SKIP;
102 +       }
103 +       if (nla_parse_nested(stats, NL80211_STA_STAT_MAX,
104 +                            tb[NL80211_ATTR_STA_STATS],
105 +                            stats_policy)) {
106 +               printf("failed to parse nested attributes!\n");
107 +               return NL_SKIP;
108 +       }
109 +
110 +       if (stats[NL80211_STA_STAT_INACTIVE_TIME])
111 +               data->inactive_msec =
112 +                       nla_get_u32(stats[NL80211_STA_STAT_INACTIVE_TIME]);
113 +       if (stats[NL80211_STA_STAT_RX_BYTES])
114 +               data->rx_bytes = nla_get_u32(stats[NL80211_STA_STAT_RX_BYTES]);
115 +       if (stats[NL80211_STA_STAT_TX_BYTES])
116 +               data->rx_bytes = nla_get_u32(stats[NL80211_STA_STAT_TX_BYTES]);
117 +
118 +       return NL_SKIP;
119 +}
120 +
121  static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,
122                               const u8 *addr)
123  {
124         struct i802_driver_data *drv = priv;
125 -       struct prism2_hostapd_param param;
126 +       struct nl_msg *msg;
127 +       struct nl_cb *cb = NULL;
128 +       int ret = -1;
129 +       int err = 0;
130 +       int finished = 0;
131 +
132 +       msg = nlmsg_alloc();
133 +       if (!msg)
134 +               goto out;
135  
136 -       memset(data, 0, sizeof(*data));
137 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
138 +                   0, NL80211_CMD_GET_STATION, 0);
139  
140 -       memset(&param, 0, sizeof(param));
141 -       param.cmd = PRISM2_HOSTAPD_GET_INFO_STA;
142 -       memcpy(param.sta_addr, addr, ETH_ALEN);
143 -       if (hostapd_ioctl(drv, &param, sizeof(param))) {
144 -               printf("  Could not get station info from kernel driver.\n");
145 -               return -1;
146 -       }
147 +       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
148 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
149 +
150 +       cb = nl_cb_alloc(NL_CB_CUSTOM);
151 +       if (!cb)
152 +               goto out;
153 +
154 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
155 +               goto out;
156 +
157 +       nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_sta_handler, data);
158 +       nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished);
159 +
160 +       err = nl_recvmsgs(drv->nl_handle, cb);
161 +
162 +       if (!finished)
163 +               err = nl_wait_for_ack(drv->nl_handle);
164 +
165 +       if (err < 0)
166 +               goto out;
167 +
168 +       ret = 0;
169 +
170 + out:
171 +       nl_cb_put(cb);
172 + nla_put_failure:
173 +       nlmsg_free(msg);
174 +       return ret;
175  
176 -       data->inactive_msec = param.u.get_info_sta.inactive_msec;
177 -       data->rx_packets = param.u.get_info_sta.rx_packets;
178 -       data->tx_packets = param.u.get_info_sta.tx_packets;
179 -       data->rx_bytes = param.u.get_info_sta.rx_bytes;
180 -       data->tx_bytes = param.u.get_info_sta.tx_bytes;
181 -       data->current_tx_rate = param.u.get_info_sta.current_tx_rate;
182 -       data->flags = param.u.get_info_sta.flags;
183 -       data->num_ps_buf_frames = param.u.get_info_sta.num_ps_buf_frames;
184 -       data->tx_retry_failed = param.u.get_info_sta.tx_retry_failed;
185 -       data->tx_retry_count = param.u.get_info_sta.tx_retry_count;
186 -       data->last_rssi = param.u.get_info_sta.last_rssi;
187 -       data->last_ack_rssi = param.u.get_info_sta.last_ack_rssi;
188 -       return 0;
189  }
190  
191  
192 @@ -744,35 +825,70 @@ static int i802_sta_add(const char *ifna
193                         size_t supp_rates_len, int flags)
194  {
195         struct i802_driver_data *drv = priv;
196 -       struct prism2_hostapd_param param;
197 -       size_t len;
198 +       struct nl_msg *msg;
199 +       int ret = -1;
200  
201 -       memset(&param, 0, sizeof(param));
202 -       param.cmd = PRISM2_HOSTAPD_ADD_STA;
203 -       memcpy(param.sta_addr, addr, ETH_ALEN);
204 -       param.u.add_sta.aid = aid;
205 -       param.u.add_sta.capability = capability;
206 -       len = supp_rates_len;
207 -       if (len > sizeof(param.u.add_sta.supp_rates))
208 -               len = sizeof(param.u.add_sta.supp_rates);
209 -       memcpy(param.u.add_sta.supp_rates, supp_rates, len);
210 -       return hostapd_ioctl_iface(ifname, drv, &param, sizeof(param));
211 +       msg = nlmsg_alloc();
212 +       if (!msg)
213 +               goto out;
214 +
215 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
216 +                   0, NL80211_CMD_NEW_STATION, 0);
217 +
218 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
219 +                   if_nametoindex(drv->iface));
220 +       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
221 +       NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, aid);
222 +       NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, supp_rates_len,
223 +               supp_rates);
224 +       NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, 0);
225 +
226 +       ret = nl_send_auto_complete(drv->nl_handle, msg);
227 +       if (ret < 0)
228 +               goto nla_put_failure;
229 +
230 +       ret = nl_wait_for_ack(drv->nl_handle);
231 +       /* ignore EEXIST, this happens if a STA associates while associated */
232 +       if (ret == -EEXIST || ret >= 0)
233 +               ret = 0;
234 +
235 + nla_put_failure:
236 +       nlmsg_free(msg);
237 +
238 + out:
239 +       return ret;
240  }
241  
242  
243  static int i802_sta_remove(void *priv, const u8 *addr)
244  {
245         struct i802_driver_data *drv = priv;
246 -       struct prism2_hostapd_param param;
247 +       struct nl_msg *msg;
248 +       int ret = -1;
249  
250 -       i802_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED);
251 +       msg = nlmsg_alloc();
252 +       if (!msg)
253 +               goto out;
254  
255 -       memset(&param, 0, sizeof(param));
256 -       param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
257 -       memcpy(param.sta_addr, addr, ETH_ALEN);
258 -       if (hostapd_ioctl(drv, &param, sizeof(param)))
259 -               return -1;
260 -       return 0;
261 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
262 +                   0, NL80211_CMD_DEL_STATION, 0);
263 +
264 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
265 +                   if_nametoindex(drv->iface));
266 +       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
267 +
268 +       ret = 0;
269 +
270 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
271 +           nl_wait_for_ack(drv->nl_handle) < 0) {
272 +               ret = -1;
273 +       }
274 +
275 + nla_put_failure:
276 +       nlmsg_free(msg);
277 +
278 + out:
279 +       return ret;
280  }
281  
282  
283 @@ -780,14 +896,51 @@ static int i802_sta_set_flags(void *priv
284                               int total_flags, int flags_or, int flags_and)
285  {
286         struct i802_driver_data *drv = priv;
287 -       struct prism2_hostapd_param param;
288 +       struct nl_msg *msg, *flags = NULL;
289 +       int ret = -1;
290  
291 -       memset(&param, 0, sizeof(param));
292 -       param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA;
293 -       memcpy(param.sta_addr, addr, ETH_ALEN);
294 -       param.u.set_flags_sta.flags_or = flags_or;
295 -       param.u.set_flags_sta.flags_and = flags_and;
296 -       return hostapd_ioctl(drv, &param, sizeof(param));
297 +       msg = nlmsg_alloc();
298 +       if (!msg)
299 +               goto out;
300 +
301 +       flags = nlmsg_alloc();
302 +       if (!flags)
303 +               goto free_msg;
304 +
305 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
306 +                   0, NL80211_CMD_SET_STATION, 0);
307 +
308 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
309 +                   if_nametoindex(drv->iface));
310 +       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
311 +
312 +       if (total_flags & WLAN_STA_AUTHORIZED)
313 +               NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED);
314 +
315 +       if (total_flags & WLAN_STA_WME)
316 +               NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME);
317 +
318 +       if (total_flags & WLAN_STA_SHORT_PREAMBLE)
319 +               NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE);
320 +
321 +       if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))
322 +               goto nla_put_failure;
323 +
324 +       ret = 0;
325 +
326 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
327 +           nl_wait_for_ack(drv->nl_handle) < 0) {
328 +               ret = -1;
329 +       }
330 +
331 + nla_put_failure:
332 +       nlmsg_free(flags);
333 +
334 + free_msg:
335 +       nlmsg_free(msg);
336 +
337 + out:
338 +       return ret;
339  }
340  
341  
342 @@ -1257,18 +1410,38 @@ static struct hostapd_hw_modes * i802_ge
343  }
344  
345  
346 -static int i802_set_sta_vlan(void *priv, const u8 *addr, const char *ifname,
347 -                            int vlan_id)
348 +static int i802_set_sta_vlan(void *priv, const u8 *addr,
349 +                            const char *ifname, int vlan_id)
350  {
351         struct i802_driver_data *drv = priv;
352 -       struct prism2_hostapd_param param;
353 +       struct nl_msg *msg;
354 +       int ret = -1;
355  
356 -       memset(&param, 0, sizeof(param));
357 -       param.cmd = PRISM2_HOSTAPD_SET_STA_VLAN;
358 -       memcpy(param.sta_addr, addr, ETH_ALEN);
359 -       os_strlcpy(param.u.set_sta_vlan.vlan_name, ifname, IFNAMSIZ);
360 -       param.u.set_sta_vlan.vlan_id = vlan_id;
361 -       return hostapd_ioctl(drv, &param, sizeof(param));
362 +       msg = nlmsg_alloc();
363 +       if (!msg)
364 +               goto out;
365 +
366 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
367 +                   0, NL80211_CMD_SET_STATION, 0);
368 +
369 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
370 +                   if_nametoindex(drv->iface));
371 +       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
372 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
373 +                   if_nametoindex(ifname));
374 +
375 +       ret = 0;
376 +
377 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
378 +           nl_wait_for_ack(drv->nl_handle) < 0) {
379 +               ret = -1;
380 +       }
381 +
382 + nla_put_failure:
383 +       nlmsg_free(msg);
384 +
385 + out:
386 +       return ret;
387  }
388  
389  
390 @@ -1752,17 +1925,14 @@ static int i802_init_sockets(struct i802
391  
392  static int i802_get_inact_sec(void *priv, const u8 *addr)
393  {
394 -       struct i802_driver_data *drv = priv;
395 -       struct prism2_hostapd_param param;
396 +       struct hostap_sta_driver_data data;
397 +       int ret;
398  
399 -       memset(&param, 0, sizeof(param));
400 -       param.cmd = PRISM2_HOSTAPD_GET_INFO_STA;
401 -       memcpy(param.sta_addr, addr, ETH_ALEN);
402 -       if (hostapd_ioctl(drv, &param, sizeof(param))) {
403 +       data.inactive_msec = -1;
404 +       ret = i802_read_sta_data(priv, &data, addr);
405 +       if (ret || data.inactive_msec == -1)
406                 return -1;
407 -       }
408 -
409 -       return param.u.get_info_sta.inactive_msec / 1000;
410 +       return data.inactive_msec / 1000;
411  }
412  
413