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