22a7b9162c854bf385d22b39f3c2b4f2649cf270
[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 static int hostapd_sta_flags_to_drv(int 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_set_ap_wps_ie(struct hostapd_data *hapd)
45 {
46         struct wpabuf *beacon, *proberesp, *assocresp = NULL;
47         int ret;
48
49         if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
50                 return 0;
51
52         beacon = hapd->wps_beacon_ie;
53         proberesp = hapd->wps_probe_resp_ie;
54
55 #ifdef CONFIG_P2P
56         if (hapd->wps_beacon_ie == NULL && hapd->p2p_beacon_ie == NULL)
57                 beacon = NULL;
58         else {
59                 beacon = wpabuf_alloc((hapd->wps_beacon_ie ?
60                                        wpabuf_len(hapd->wps_beacon_ie) : 0) +
61                                       (hapd->p2p_beacon_ie ?
62                                        wpabuf_len(hapd->p2p_beacon_ie) : 0));
63                 if (beacon == NULL)
64                         return -1;
65                 if (hapd->wps_beacon_ie)
66                         wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
67                 if (hapd->p2p_beacon_ie)
68                         wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
69         }
70
71         if (hapd->wps_probe_resp_ie == NULL && hapd->p2p_probe_resp_ie == NULL)
72                 proberesp = NULL;
73         else {
74                 proberesp = wpabuf_alloc(
75                         (hapd->wps_probe_resp_ie ?
76                          wpabuf_len(hapd->wps_probe_resp_ie) : 0) +
77                         (hapd->p2p_probe_resp_ie ?
78                          wpabuf_len(hapd->p2p_probe_resp_ie) : 0));
79                 if (proberesp == NULL) {
80                         wpabuf_free(beacon);
81                         return -1;
82                 }
83                 if (hapd->wps_probe_resp_ie)
84                         wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
85                 if (hapd->p2p_probe_resp_ie)
86                         wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
87         }
88 #endif /* CONFIG_P2P */
89
90 #ifdef CONFIG_P2P_MANAGER
91         if (hapd->conf->p2p & P2P_MANAGE) {
92                 struct wpabuf *a;
93
94                 a = wpabuf_alloc(100 + (beacon ? wpabuf_len(beacon) : 0));
95                 if (a) {
96                         u8 *start, *p;
97                         if (beacon)
98                                 wpabuf_put_buf(a, beacon);
99                         if (beacon != hapd->wps_beacon_ie)
100                                 wpabuf_free(beacon);
101                         start = wpabuf_put(a, 0);
102                         p = hostapd_eid_p2p_manage(hapd, start);
103                         wpabuf_put(a, p - start);
104                         beacon = a;
105                 }
106
107                 a = wpabuf_alloc(100 + (proberesp ? wpabuf_len(proberesp) :
108                                         0));
109                 if (a) {
110                         u8 *start, *p;
111                         if (proberesp)
112                                 wpabuf_put_buf(a, proberesp);
113                         if (proberesp != hapd->wps_probe_resp_ie)
114                                 wpabuf_free(proberesp);
115                         start = wpabuf_put(a, 0);
116                         p = hostapd_eid_p2p_manage(hapd, start);
117                         wpabuf_put(a, p - start);
118                         proberesp = a;
119                 }
120         }
121 #endif /* CONFIG_P2P_MANAGER */
122
123 #ifdef CONFIG_WPS2
124         if (hapd->conf->wps_state)
125                 assocresp = wps_build_assoc_resp_ie();
126 #endif /* CONFIG_WPS2 */
127
128 #ifdef CONFIG_P2P_MANAGER
129         if (hapd->conf->p2p & P2P_MANAGE) {
130                 struct wpabuf *a;
131                 a = wpabuf_alloc(100 + (assocresp ? wpabuf_len(assocresp) :
132                                         0));
133                 if (a) {
134                         u8 *start, *p;
135                         start = wpabuf_put(a, 0);
136                         p = hostapd_eid_p2p_manage(hapd, start);
137                         wpabuf_put(a, p - start);
138                         if (assocresp) {
139                                 wpabuf_put_buf(a, assocresp);
140                                 wpabuf_free(assocresp);
141                         }
142                         assocresp = a;
143                 }
144         }
145 #endif /* CONFIG_P2P_MANAGER */
146
147         ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
148                                           assocresp);
149
150         if (beacon != hapd->wps_beacon_ie)
151                 wpabuf_free(beacon);
152         if (proberesp != hapd->wps_probe_resp_ie)
153                 wpabuf_free(proberesp);
154         wpabuf_free(assocresp);
155
156         return ret;
157 }
158
159
160 int hostapd_set_authorized(struct hostapd_data *hapd,
161                            struct sta_info *sta, int authorized)
162 {
163         if (authorized) {
164                 return hostapd_sta_set_flags(hapd, sta->addr,
165                                              hostapd_sta_flags_to_drv(
166                                                      sta->flags),
167                                              WPA_STA_AUTHORIZED, ~0);
168         }
169
170         return hostapd_sta_set_flags(hapd, sta->addr,
171                                      hostapd_sta_flags_to_drv(sta->flags),
172                                      0, ~WPA_STA_AUTHORIZED);
173 }
174
175
176 int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta)
177 {
178         int set_flags, total_flags, flags_and, flags_or;
179         total_flags = hostapd_sta_flags_to_drv(sta->flags);
180         set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
181         if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
182              sta->auth_alg == WLAN_AUTH_FT) &&
183             sta->flags & WLAN_STA_AUTHORIZED)
184                 set_flags |= WPA_STA_AUTHORIZED;
185         flags_or = total_flags & set_flags;
186         flags_and = total_flags | ~set_flags;
187         return hostapd_sta_set_flags(hapd, sta->addr, total_flags,
188                                      flags_or, flags_and);
189 }
190
191
192 int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
193                               int enabled)
194 {
195         struct wpa_bss_params params;
196         os_memset(&params, 0, sizeof(params));
197         params.ifname = ifname;
198         params.enabled = enabled;
199         if (enabled) {
200                 params.wpa = hapd->conf->wpa;
201                 params.ieee802_1x = hapd->conf->ieee802_1x;
202                 params.wpa_group = hapd->conf->wpa_group;
203                 params.wpa_pairwise = hapd->conf->wpa_pairwise;
204                 params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
205                 params.rsn_preauth = hapd->conf->rsn_preauth;
206         }
207         return hostapd_set_ieee8021x(hapd, &params);
208 }
209
210
211 static int hostapd_set_ap_isolate(struct hostapd_data *hapd, int value)
212 {
213         if (hapd->driver == NULL || hapd->driver->set_intra_bss == NULL)
214                 return 0;
215         return hapd->driver->set_intra_bss(hapd->drv_priv, !value);
216 }
217
218
219 int hostapd_set_bss_params(struct hostapd_data *hapd, int use_protection)
220 {
221         int ret = 0;
222         int preamble;
223 #ifdef CONFIG_IEEE80211N
224         u8 buf[60], *ht_capab, *ht_oper, *pos;
225
226         pos = buf;
227         ht_capab = pos;
228         pos = hostapd_eid_ht_capabilities(hapd, pos);
229         ht_oper = pos;
230         pos = hostapd_eid_ht_operation(hapd, pos);
231         if (pos > ht_oper && ht_oper > ht_capab &&
232             hostapd_set_ht_params(hapd, ht_capab + 2, ht_capab[1],
233                                   ht_oper + 2, ht_oper[1])) {
234                 wpa_printf(MSG_ERROR, "Could not set HT capabilities "
235                            "for kernel driver");
236                 ret = -1;
237         }
238
239 #endif /* CONFIG_IEEE80211N */
240
241         if (hostapd_set_cts_protect(hapd, use_protection)) {
242                 wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel "
243                            "driver");
244                 ret = -1;
245         }
246
247         if (hapd->iface->current_mode &&
248             hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
249             hostapd_set_short_slot_time(hapd,
250                                         hapd->iface->num_sta_no_short_slot_time
251                                         > 0 ? 0 : 1)) {
252                 wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option "
253                            "in kernel driver");
254                 ret = -1;
255         }
256
257         if (hapd->iface->num_sta_no_short_preamble == 0 &&
258             hapd->iconf->preamble == SHORT_PREAMBLE)
259                 preamble = SHORT_PREAMBLE;
260         else
261                 preamble = LONG_PREAMBLE;
262         if (hostapd_set_preamble(hapd, preamble)) {
263                 wpa_printf(MSG_ERROR, "Could not set preamble for kernel "
264                            "driver");
265                 ret = -1;
266         }
267
268         if (hostapd_set_ap_isolate(hapd, hapd->conf->isolate) &&
269             hapd->conf->isolate) {
270                 wpa_printf(MSG_ERROR, "Could not enable AP isolation in "
271                            "kernel driver");
272                 ret = -1;
273         }
274
275         return ret;
276 }
277
278
279 int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
280 {
281         char force_ifname[IFNAMSIZ];
282         u8 if_addr[ETH_ALEN];
283         return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
284                               NULL, NULL, force_ifname, if_addr);
285 }
286
287
288 int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname)
289 {
290         return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
291 }
292
293
294 int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
295                         int val)
296 {
297         const char *bridge = NULL;
298
299         if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
300                 return 0;
301         if (hapd->conf->wds_bridge[0])
302                 bridge = hapd->conf->wds_bridge;
303         else if (hapd->conf->bridge[0])
304                 bridge = hapd->conf->bridge;
305         return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
306                                          bridge);
307 }
308
309
310 int hostapd_sta_add(struct hostapd_data *hapd,
311                     const u8 *addr, u16 aid, u16 capability,
312                     const u8 *supp_rates, size_t supp_rates_len,
313                     u16 listen_interval,
314                     const struct ieee80211_ht_capabilities *ht_capab)
315 {
316         struct hostapd_sta_add_params params;
317
318         if (hapd->driver == NULL)
319                 return 0;
320         if (hapd->driver->sta_add == NULL)
321                 return 0;
322
323         os_memset(&params, 0, sizeof(params));
324         params.addr = addr;
325         params.aid = aid;
326         params.capability = capability;
327         params.supp_rates = supp_rates;
328         params.supp_rates_len = supp_rates_len;
329         params.listen_interval = listen_interval;
330         params.ht_capabilities = ht_capab;
331         return hapd->driver->sta_add(hapd->drv_priv, &params);
332 }
333
334
335 int hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
336 {
337         if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
338                 return 0;
339         return hapd->driver->set_privacy(hapd->drv_priv, enabled);
340 }
341
342
343 int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
344                              size_t elem_len)
345 {
346         if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL)
347                 return 0;
348         return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len);
349 }
350
351
352 int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len)
353 {
354         if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL)
355                 return 0;
356         return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len);
357 }
358
359
360 int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
361 {
362         if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL)
363                 return 0;
364         return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len);
365 }
366
367
368 int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
369                    const char *ifname, const u8 *addr, void *bss_ctx,
370                    void **drv_priv, char *force_ifname, u8 *if_addr)
371 {
372         if (hapd->driver == NULL || hapd->driver->if_add == NULL)
373                 return -1;
374         return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
375                                     bss_ctx, drv_priv, force_ifname, if_addr);
376 }
377
378
379 int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
380                       const char *ifname)
381 {
382         if (hapd->driver == NULL || hapd->driver->if_remove == NULL)
383                 return -1;
384         return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
385 }
386
387
388 int hostapd_set_ieee8021x(struct hostapd_data *hapd,
389                           struct wpa_bss_params *params)
390 {
391         if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL)
392                 return 0;
393         return hapd->driver->set_ieee8021x(hapd->drv_priv, params);
394 }
395
396
397 int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
398                        const u8 *addr, int idx, u8 *seq)
399 {
400         if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL)
401                 return 0;
402         return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx,
403                                         seq);
404 }
405
406
407 int hostapd_flush(struct hostapd_data *hapd)
408 {
409         if (hapd->driver == NULL || hapd->driver->flush == NULL)
410                 return 0;
411         return hapd->driver->flush(hapd->drv_priv);
412 }
413
414
415 int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq,
416                      int channel, int ht_enabled, int sec_channel_offset)
417 {
418         struct hostapd_freq_params data;
419         if (hapd->driver == NULL)
420                 return 0;
421         if (hapd->driver->set_freq == NULL)
422                 return 0;
423         os_memset(&data, 0, sizeof(data));
424         data.mode = mode;
425         data.freq = freq;
426         data.channel = channel;
427         data.ht_enabled = ht_enabled;
428         data.sec_channel_offset = sec_channel_offset;
429         return hapd->driver->set_freq(hapd->drv_priv, &data);
430 }
431
432 int hostapd_set_rts(struct hostapd_data *hapd, int rts)
433 {
434         if (hapd->driver == NULL || hapd->driver->set_rts == NULL)
435                 return 0;
436         return hapd->driver->set_rts(hapd->drv_priv, rts);
437 }
438
439
440 int hostapd_set_frag(struct hostapd_data *hapd, int frag)
441 {
442         if (hapd->driver == NULL || hapd->driver->set_frag == NULL)
443                 return 0;
444         return hapd->driver->set_frag(hapd->drv_priv, frag);
445 }
446
447
448 int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
449                           int total_flags, int flags_or, int flags_and)
450 {
451         if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
452                 return 0;
453         return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
454                                            flags_or, flags_and);
455 }
456
457
458 int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
459                           int *basic_rates, int mode)
460 {
461         if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL)
462                 return 0;
463         return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates,
464                                            basic_rates, mode);
465 }
466
467
468 int hostapd_set_country(struct hostapd_data *hapd, const char *country)
469 {
470         if (hapd->driver == NULL ||
471             hapd->driver->set_country == NULL)
472                 return 0;
473         return hapd->driver->set_country(hapd->drv_priv, country);
474 }
475
476
477 int hostapd_set_cts_protect(struct hostapd_data *hapd, int value)
478 {
479         if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL)
480                 return 0;
481         return hapd->driver->set_cts_protect(hapd->drv_priv, value);
482 }
483
484
485 int hostapd_set_preamble(struct hostapd_data *hapd, int value)
486 {
487         if (hapd->driver == NULL || hapd->driver->set_preamble == NULL)
488                 return 0;
489         return hapd->driver->set_preamble(hapd->drv_priv, value);
490 }
491
492
493 int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value)
494 {
495         if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL)
496                 return 0;
497         return hapd->driver->set_short_slot_time(hapd->drv_priv, value);
498 }
499
500
501 int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
502                                 int cw_min, int cw_max, int burst_time)
503 {
504         if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL)
505                 return 0;
506         return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs,
507                                                  cw_min, cw_max, burst_time);
508 }
509
510
511 int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
512                            const u8 *mask)
513 {
514         if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL)
515                 return 1;
516         return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask);
517 }
518
519
520 struct hostapd_hw_modes *
521 hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
522                             u16 *flags)
523 {
524         if (hapd->driver == NULL ||
525             hapd->driver->get_hw_feature_data == NULL)
526                 return NULL;
527         return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
528                                                  flags);
529 }
530
531
532 int hostapd_driver_commit(struct hostapd_data *hapd)
533 {
534         if (hapd->driver == NULL || hapd->driver->commit == NULL)
535                 return 0;
536         return hapd->driver->commit(hapd->drv_priv);
537 }
538
539
540 int hostapd_set_ht_params(struct hostapd_data *hapd,
541                           const u8 *ht_capab, size_t ht_capab_len,
542                           const u8 *ht_oper, size_t ht_oper_len)
543 {
544         if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL ||
545             ht_capab == NULL || ht_oper == NULL)
546                 return 0;
547         return hapd->driver->set_ht_params(hapd->drv_priv,
548                                            ht_capab, ht_capab_len,
549                                            ht_oper, ht_oper_len);
550 }
551
552
553 int hostapd_drv_none(struct hostapd_data *hapd)
554 {
555         return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
556 }
557
558
559 int hostapd_driver_scan(struct hostapd_data *hapd,
560                         struct wpa_driver_scan_params *params)
561 {
562         if (hapd->driver && hapd->driver->scan2)
563                 return hapd->driver->scan2(hapd->drv_priv, params);
564         return -1;
565 }
566
567
568 struct wpa_scan_results * hostapd_driver_get_scan_results(
569         struct hostapd_data *hapd)
570 {
571         if (hapd->driver && hapd->driver->get_scan_results2)
572                 return hapd->driver->get_scan_results2(hapd->drv_priv);
573         return NULL;
574 }
575
576
577 int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
578                            int duration)
579 {
580         if (hapd->driver && hapd->driver->set_noa)
581                 return hapd->driver->set_noa(hapd->drv_priv, count, start,
582                                              duration);
583         return -1;
584 }
585
586
587 int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
588                         enum wpa_alg alg, const u8 *addr,
589                         int key_idx, int set_tx,
590                         const u8 *seq, size_t seq_len,
591                         const u8 *key, size_t key_len)
592 {
593         if (hapd->driver == NULL || hapd->driver->set_key == NULL)
594                 return 0;
595         return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
596                                      key_idx, set_tx, seq, seq_len, key,
597                                      key_len);
598 }
599
600
601 int hostapd_drv_send_mlme(struct hostapd_data *hapd,
602                           const void *msg, size_t len)
603 {
604         if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
605                 return 0;
606         return hapd->driver->send_mlme(hapd->drv_priv, msg, len);
607 }
608
609
610 int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
611                            const u8 *addr, int reason)
612 {
613         if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
614                 return 0;
615         return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
616                                         reason);
617 }
618
619
620 int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
621                              const u8 *addr, int reason)
622 {
623         if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
624                 return 0;
625         return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
626                                           reason);
627 }