Interworking: Add support for configuring Roaming Consortium List
[mech_eap.git] / src / ap / ap_drv_ops.c
1 /*
2  * hostapd - Driver operations
3  * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "utils/includes.h"
16
17 #include "utils/common.h"
18 #include "drivers/driver.h"
19 #include "common/ieee802_11_defs.h"
20 #include "wps/wps.h"
21 #include "hostapd.h"
22 #include "ieee802_11.h"
23 #include "sta_info.h"
24 #include "ap_config.h"
25 #include "p2p_hostapd.h"
26 #include "ap_drv_ops.h"
27
28
29 u32 hostapd_sta_flags_to_drv(u32 flags)
30 {
31         int res = 0;
32         if (flags & WLAN_STA_AUTHORIZED)
33                 res |= WPA_STA_AUTHORIZED;
34         if (flags & WLAN_STA_WMM)
35                 res |= WPA_STA_WMM;
36         if (flags & WLAN_STA_SHORT_PREAMBLE)
37                 res |= WPA_STA_SHORT_PREAMBLE;
38         if (flags & WLAN_STA_MFP)
39                 res |= WPA_STA_MFP;
40         return res;
41 }
42
43
44 int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
45                                struct wpabuf **beacon_ret,
46                                struct wpabuf **proberesp_ret,
47                                struct wpabuf **assocresp_ret)
48 {
49         struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL;
50         u8 buf[200], *pos;
51
52         *beacon_ret = *proberesp_ret = *assocresp_ret = NULL;
53
54         pos = buf;
55         pos = hostapd_eid_ext_capab(hapd, pos);
56         if (pos != buf) {
57                 if (wpabuf_resize(&assocresp, pos - buf) != 0)
58                         goto fail;
59                 wpabuf_put_data(assocresp, buf, pos - buf);
60         }
61         pos = hostapd_eid_interworking(hapd, pos);
62         pos = hostapd_eid_adv_proto(hapd, pos);
63         pos = hostapd_eid_roaming_consortium(hapd, pos);
64         if (pos != buf) {
65                 if (wpabuf_resize(&beacon, pos - buf) != 0)
66                         goto fail;
67                 wpabuf_put_data(beacon, buf, pos - buf);
68
69                 if (wpabuf_resize(&proberesp, pos - buf) != 0)
70                         goto fail;
71                 wpabuf_put_data(proberesp, buf, pos - buf);
72         }
73
74         if (hapd->wps_beacon_ie) {
75                 if (wpabuf_resize(&beacon, wpabuf_len(hapd->wps_beacon_ie)) <
76                     0)
77                         goto fail;
78                 wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
79         }
80
81         if (hapd->wps_probe_resp_ie) {
82                 if (wpabuf_resize(&proberesp,
83                                   wpabuf_len(hapd->wps_probe_resp_ie)) < 0)
84                         goto fail;
85                 wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
86         }
87
88 #ifdef CONFIG_P2P
89         if (hapd->p2p_beacon_ie) {
90                 if (wpabuf_resize(&beacon, wpabuf_len(hapd->p2p_beacon_ie)) <
91                     0)
92                         goto fail;
93                 wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
94         }
95
96         if (hapd->p2p_probe_resp_ie) {
97                 if (wpabuf_resize(&beacon, wpabuf_len(hapd->p2p_probe_resp_ie))
98                     < 0)
99                         goto fail;
100                 wpabuf_put_buf(beacon, hapd->p2p_probe_resp_ie);
101         }
102 #endif /* CONFIG_P2P */
103
104 #ifdef CONFIG_P2P_MANAGER
105         if (hapd->conf->p2p & P2P_MANAGE) {
106                 if (wpabuf_resize(&beacon, 100) == 0) {
107                         u8 *start, *p;
108                         start = wpabuf_put(beacon, 0);
109                         p = hostapd_eid_p2p_manage(hapd, start);
110                         wpabuf_put(beacon, p - start);
111                 }
112
113                 if (wpabuf_resize(&proberesp, 100) == 0) {
114                         u8 *start, *p;
115                         start = wpabuf_put(proberesp, 0);
116                         p = hostapd_eid_p2p_manage(hapd, start);
117                         wpabuf_put(proberesp, p - start);
118                 }
119         }
120 #endif /* CONFIG_P2P_MANAGER */
121
122 #ifdef CONFIG_WPS2
123         if (hapd->conf->wps_state) {
124                 struct wpabuf *a = wps_build_assoc_resp_ie();
125                 if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
126                         wpabuf_put_buf(assocresp, a);
127                 wpabuf_free(a);
128         }
129 #endif /* CONFIG_WPS2 */
130
131 #ifdef CONFIG_P2P_MANAGER
132         if (hapd->conf->p2p & P2P_MANAGE) {
133                 if (wpabuf_resize(&assocresp, 100) == 0) {
134                         u8 *start, *p;
135                         start = wpabuf_put(assocresp, 0);
136                         p = hostapd_eid_p2p_manage(hapd, start);
137                         wpabuf_put(assocresp, p - start);
138                 }
139         }
140 #endif /* CONFIG_P2P_MANAGER */
141
142         *beacon_ret = beacon;
143         *proberesp_ret = proberesp;
144         *assocresp_ret = assocresp;
145
146         return 0;
147
148 fail:
149         wpabuf_free(beacon);
150         wpabuf_free(proberesp);
151         wpabuf_free(assocresp);
152         return -1;
153 }
154
155
156 void hostapd_free_ap_extra_ies(struct hostapd_data *hapd,
157                                struct wpabuf *beacon,
158                                struct wpabuf *proberesp,
159                                struct wpabuf *assocresp)
160 {
161         wpabuf_free(beacon);
162         wpabuf_free(proberesp);
163         wpabuf_free(assocresp);
164 }
165
166
167 int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
168 {
169         struct wpabuf *beacon, *proberesp, *assocresp;
170         int ret;
171
172         if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
173                 return 0;
174
175         if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
176             0)
177                 return -1;
178
179         ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
180                                           assocresp);
181
182         hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
183
184         return ret;
185 }
186
187
188 int hostapd_set_authorized(struct hostapd_data *hapd,
189                            struct sta_info *sta, int authorized)
190 {
191         if (authorized) {
192                 return hostapd_sta_set_flags(hapd, sta->addr,
193                                              hostapd_sta_flags_to_drv(
194                                                      sta->flags),
195                                              WPA_STA_AUTHORIZED, ~0);
196         }
197
198         return hostapd_sta_set_flags(hapd, sta->addr,
199                                      hostapd_sta_flags_to_drv(sta->flags),
200                                      0, ~WPA_STA_AUTHORIZED);
201 }
202
203
204 int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta)
205 {
206         int set_flags, total_flags, flags_and, flags_or;
207         total_flags = hostapd_sta_flags_to_drv(sta->flags);
208         set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
209         if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
210              sta->auth_alg == WLAN_AUTH_FT) &&
211             sta->flags & WLAN_STA_AUTHORIZED)
212                 set_flags |= WPA_STA_AUTHORIZED;
213         flags_or = total_flags & set_flags;
214         flags_and = total_flags | ~set_flags;
215         return hostapd_sta_set_flags(hapd, sta->addr, total_flags,
216                                      flags_or, flags_and);
217 }
218
219
220 int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
221                               int enabled)
222 {
223         struct wpa_bss_params params;
224         os_memset(&params, 0, sizeof(params));
225         params.ifname = ifname;
226         params.enabled = enabled;
227         if (enabled) {
228                 params.wpa = hapd->conf->wpa;
229                 params.ieee802_1x = hapd->conf->ieee802_1x;
230                 params.wpa_group = hapd->conf->wpa_group;
231                 params.wpa_pairwise = hapd->conf->wpa_pairwise;
232                 params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
233                 params.rsn_preauth = hapd->conf->rsn_preauth;
234 #ifdef CONFIG_IEEE80211W
235                 params.ieee80211w = hapd->conf->ieee80211w;
236 #endif /* CONFIG_IEEE80211W */
237         }
238         return hostapd_set_ieee8021x(hapd, &params);
239 }
240
241
242 int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
243 {
244         char force_ifname[IFNAMSIZ];
245         u8 if_addr[ETH_ALEN];
246         return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
247                               NULL, NULL, force_ifname, if_addr, NULL);
248 }
249
250
251 int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname)
252 {
253         return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
254 }
255
256
257 int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
258                         int val)
259 {
260         const char *bridge = NULL;
261
262         if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
263                 return 0;
264         if (hapd->conf->wds_bridge[0])
265                 bridge = hapd->conf->wds_bridge;
266         else if (hapd->conf->bridge[0])
267                 bridge = hapd->conf->bridge;
268         return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
269                                          bridge);
270 }
271
272
273 int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
274                          u16 auth_alg)
275 {
276         if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
277                 return 0;
278         return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
279 }
280
281
282 int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
283                      u16 seq, u16 status, const u8 *ie, size_t len)
284 {
285         if (hapd->driver == NULL || hapd->driver->sta_auth == NULL)
286                 return 0;
287         return hapd->driver->sta_auth(hapd->drv_priv, hapd->own_addr, addr,
288                                       seq, status, ie, len);
289 }
290
291
292 int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
293                       int reassoc, u16 status, const u8 *ie, size_t len)
294 {
295         if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL)
296                 return 0;
297         return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr,
298                                        reassoc, status, ie, len);
299 }
300
301
302 int hostapd_sta_add(struct hostapd_data *hapd,
303                     const u8 *addr, u16 aid, u16 capability,
304                     const u8 *supp_rates, size_t supp_rates_len,
305                     u16 listen_interval,
306                     const struct ieee80211_ht_capabilities *ht_capab,
307                     u32 flags)
308 {
309         struct hostapd_sta_add_params params;
310
311         if (hapd->driver == NULL)
312                 return 0;
313         if (hapd->driver->sta_add == NULL)
314                 return 0;
315
316         os_memset(&params, 0, sizeof(params));
317         params.addr = addr;
318         params.aid = aid;
319         params.capability = capability;
320         params.supp_rates = supp_rates;
321         params.supp_rates_len = supp_rates_len;
322         params.listen_interval = listen_interval;
323         params.ht_capabilities = ht_capab;
324         params.flags = hostapd_sta_flags_to_drv(flags);
325         return hapd->driver->sta_add(hapd->drv_priv, &params);
326 }
327
328
329 int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
330                       u8 *tspec_ie, size_t tspec_ielen)
331 {
332         if (hapd->driver == NULL || hapd->driver->add_tspec == NULL)
333                 return 0;
334         return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie,
335                                        tspec_ielen);
336 }
337
338
339 int hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
340 {
341         if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
342                 return 0;
343         return hapd->driver->set_privacy(hapd->drv_priv, enabled);
344 }
345
346
347 int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
348                              size_t elem_len)
349 {
350         if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL)
351                 return 0;
352         return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len);
353 }
354
355
356 int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len)
357 {
358         if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL)
359                 return 0;
360         return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len);
361 }
362
363
364 int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
365 {
366         if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL)
367                 return 0;
368         return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len);
369 }
370
371
372 int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
373                    const char *ifname, const u8 *addr, void *bss_ctx,
374                    void **drv_priv, char *force_ifname, u8 *if_addr,
375                    const char *bridge)
376 {
377         if (hapd->driver == NULL || hapd->driver->if_add == NULL)
378                 return -1;
379         return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
380                                     bss_ctx, drv_priv, force_ifname, if_addr,
381                                     bridge);
382 }
383
384
385 int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
386                       const char *ifname)
387 {
388         if (hapd->driver == NULL || hapd->driver->if_remove == NULL)
389                 return -1;
390         return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
391 }
392
393
394 int hostapd_set_ieee8021x(struct hostapd_data *hapd,
395                           struct wpa_bss_params *params)
396 {
397         if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL)
398                 return 0;
399         return hapd->driver->set_ieee8021x(hapd->drv_priv, params);
400 }
401
402
403 int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
404                        const u8 *addr, int idx, u8 *seq)
405 {
406         if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL)
407                 return 0;
408         return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx,
409                                         seq);
410 }
411
412
413 int hostapd_flush(struct hostapd_data *hapd)
414 {
415         if (hapd->driver == NULL || hapd->driver->flush == NULL)
416                 return 0;
417         return hapd->driver->flush(hapd->drv_priv);
418 }
419
420
421 int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq,
422                      int channel, int ht_enabled, int sec_channel_offset)
423 {
424         struct hostapd_freq_params data;
425         if (hapd->driver == NULL)
426                 return 0;
427         if (hapd->driver->set_freq == NULL)
428                 return 0;
429         os_memset(&data, 0, sizeof(data));
430         data.mode = mode;
431         data.freq = freq;
432         data.channel = channel;
433         data.ht_enabled = ht_enabled;
434         data.sec_channel_offset = sec_channel_offset;
435         return hapd->driver->set_freq(hapd->drv_priv, &data);
436 }
437
438 int hostapd_set_rts(struct hostapd_data *hapd, int rts)
439 {
440         if (hapd->driver == NULL || hapd->driver->set_rts == NULL)
441                 return 0;
442         return hapd->driver->set_rts(hapd->drv_priv, rts);
443 }
444
445
446 int hostapd_set_frag(struct hostapd_data *hapd, int frag)
447 {
448         if (hapd->driver == NULL || hapd->driver->set_frag == NULL)
449                 return 0;
450         return hapd->driver->set_frag(hapd->drv_priv, frag);
451 }
452
453
454 int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
455                           int total_flags, int flags_or, int flags_and)
456 {
457         if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
458                 return 0;
459         return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
460                                            flags_or, flags_and);
461 }
462
463
464 int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
465                           int *basic_rates, int mode)
466 {
467         if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL)
468                 return 0;
469         return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates,
470                                            basic_rates, mode);
471 }
472
473
474 int hostapd_set_country(struct hostapd_data *hapd, const char *country)
475 {
476         if (hapd->driver == NULL ||
477             hapd->driver->set_country == NULL)
478                 return 0;
479         return hapd->driver->set_country(hapd->drv_priv, country);
480 }
481
482
483 int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
484                                 int cw_min, int cw_max, int burst_time)
485 {
486         if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL)
487                 return 0;
488         return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs,
489                                                  cw_min, cw_max, burst_time);
490 }
491
492
493 int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
494                            const u8 *mask)
495 {
496         if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL)
497                 return 1;
498         return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask);
499 }
500
501
502 struct hostapd_hw_modes *
503 hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
504                             u16 *flags)
505 {
506         if (hapd->driver == NULL ||
507             hapd->driver->get_hw_feature_data == NULL)
508                 return NULL;
509         return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
510                                                  flags);
511 }
512
513
514 int hostapd_driver_commit(struct hostapd_data *hapd)
515 {
516         if (hapd->driver == NULL || hapd->driver->commit == NULL)
517                 return 0;
518         return hapd->driver->commit(hapd->drv_priv);
519 }
520
521
522 int hostapd_drv_none(struct hostapd_data *hapd)
523 {
524         return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
525 }
526
527
528 int hostapd_driver_scan(struct hostapd_data *hapd,
529                         struct wpa_driver_scan_params *params)
530 {
531         if (hapd->driver && hapd->driver->scan2)
532                 return hapd->driver->scan2(hapd->drv_priv, params);
533         return -1;
534 }
535
536
537 struct wpa_scan_results * hostapd_driver_get_scan_results(
538         struct hostapd_data *hapd)
539 {
540         if (hapd->driver && hapd->driver->get_scan_results2)
541                 return hapd->driver->get_scan_results2(hapd->drv_priv);
542         return NULL;
543 }
544
545
546 int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
547                            int duration)
548 {
549         if (hapd->driver && hapd->driver->set_noa)
550                 return hapd->driver->set_noa(hapd->drv_priv, count, start,
551                                              duration);
552         return -1;
553 }
554
555
556 int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
557                         enum wpa_alg alg, const u8 *addr,
558                         int key_idx, int set_tx,
559                         const u8 *seq, size_t seq_len,
560                         const u8 *key, size_t key_len)
561 {
562         if (hapd->driver == NULL || hapd->driver->set_key == NULL)
563                 return 0;
564         return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
565                                      key_idx, set_tx, seq, seq_len, key,
566                                      key_len);
567 }
568
569
570 int hostapd_drv_send_mlme(struct hostapd_data *hapd,
571                           const void *msg, size_t len)
572 {
573         if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
574                 return 0;
575         return hapd->driver->send_mlme(hapd->drv_priv, msg, len);
576 }
577
578
579 int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
580                            const u8 *addr, int reason)
581 {
582         if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
583                 return 0;
584         return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
585                                         reason);
586 }
587
588
589 int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
590                              const u8 *addr, int reason)
591 {
592         if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
593                 return 0;
594         return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
595                                           reason);
596 }