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