Move rest of the generic AP mode functionality into src/ap
[libeap.git] / src / ap / ap_drv_ops.c
1 /*
2  * hostapd - Driver operations
3  * Copyright (c) 2009, 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 "includes.h"
16
17 #include "common.h"
18 #include "ap/hostapd.h"
19 #include "ap/ieee802_11.h"
20 #include "ap/sta_info.h"
21 #include "driver_i.h"
22 #include "ap_drv_ops.h"
23
24
25 static int hostapd_sta_flags_to_drv(int flags)
26 {
27         int res = 0;
28         if (flags & WLAN_STA_AUTHORIZED)
29                 res |= WPA_STA_AUTHORIZED;
30         if (flags & WLAN_STA_WMM)
31                 res |= WPA_STA_WMM;
32         if (flags & WLAN_STA_SHORT_PREAMBLE)
33                 res |= WPA_STA_SHORT_PREAMBLE;
34         if (flags & WLAN_STA_MFP)
35                 res |= WPA_STA_MFP;
36         return res;
37 }
38
39
40 static int hostapd_set_ap_wps_ie(struct hostapd_data *hapd,
41                                  const struct wpabuf *beacon,
42                                  const struct wpabuf *proberesp)
43 {
44         if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
45                 return 0;
46         return hapd->driver->set_ap_wps_ie(hapd->conf->iface, hapd->drv_priv,
47                                            beacon, proberesp);
48 }
49
50
51 static int hostapd_send_mgmt_frame(struct hostapd_data *hapd, const void *msg,
52                            size_t len)
53 {
54         if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
55                 return 0;
56         return hapd->driver->send_mlme(hapd->drv_priv, msg, len);
57 }
58
59
60 static int hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr,
61                               const u8 *data, size_t data_len, int encrypt)
62 {
63         if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
64                 return 0;
65         return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
66                                              data_len, encrypt,
67                                              hapd->own_addr);
68 }
69
70
71 static int hostapd_set_authorized(struct hostapd_data *hapd,
72                                   struct sta_info *sta, int authorized)
73 {
74         if (authorized) {
75                 return hostapd_sta_set_flags(hapd, sta->addr,
76                                              hostapd_sta_flags_to_drv(
77                                                      sta->flags),
78                                              WPA_STA_AUTHORIZED, ~0);
79         }
80
81         return hostapd_sta_set_flags(hapd, sta->addr,
82                                      hostapd_sta_flags_to_drv(sta->flags),
83                                      0, ~WPA_STA_AUTHORIZED);
84 }
85
86
87 static int hostapd_set_key(const char *ifname, struct hostapd_data *hapd,
88                            wpa_alg alg, const u8 *addr, int key_idx,
89                            int set_tx, const u8 *seq, size_t seq_len,
90                            const u8 *key, size_t key_len)
91 {
92         if (hapd->driver == NULL || hapd->driver->set_key == NULL)
93                 return 0;
94         return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
95                                      key_idx, set_tx, seq, seq_len, key,
96                                      key_len);
97 }
98
99
100 static int hostapd_read_sta_data(struct hostapd_data *hapd,
101                                  struct hostap_sta_driver_data *data,
102                                  const u8 *addr)
103 {
104         if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL)
105                 return -1;
106         return hapd->driver->read_sta_data(hapd->drv_priv, data, addr);
107 }
108
109
110 static int hostapd_sta_clear_stats(struct hostapd_data *hapd, const u8 *addr)
111 {
112         if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL)
113                 return 0;
114         return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
115 }
116
117
118 static int hostapd_set_sta_flags(struct hostapd_data *hapd,
119                                  struct sta_info *sta)
120 {
121         int set_flags, total_flags, flags_and, flags_or;
122         total_flags = hostapd_sta_flags_to_drv(sta->flags);
123         set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
124         if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
125             sta->flags & WLAN_STA_AUTHORIZED)
126                 set_flags |= WPA_STA_AUTHORIZED;
127         flags_or = total_flags & set_flags;
128         flags_and = total_flags | ~set_flags;
129         return hostapd_sta_set_flags(hapd, sta->addr, total_flags,
130                                      flags_or, flags_and);
131 }
132
133
134 static int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd,
135                                      const char *ifname, int enabled)
136 {
137         struct wpa_bss_params params;
138         os_memset(&params, 0, sizeof(params));
139         params.ifname = ifname;
140         params.enabled = enabled;
141         if (enabled) {
142                 params.wpa = hapd->conf->wpa;
143                 params.ieee802_1x = hapd->conf->ieee802_1x;
144                 params.wpa_group = hapd->conf->wpa_group;
145                 params.wpa_pairwise = hapd->conf->wpa_pairwise;
146                 params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
147                 params.rsn_preauth = hapd->conf->rsn_preauth;
148         }
149         return hostapd_set_ieee8021x(hapd, &params);
150 }
151
152
153 static int hostapd_set_radius_acl_auth(struct hostapd_data *hapd,
154                                        const u8 *mac, int accepted,
155                                        u32 session_timeout)
156 {
157         if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL)
158                 return 0;
159         return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted,
160                                                  session_timeout);
161 }
162
163
164 static int hostapd_set_radius_acl_expire(struct hostapd_data *hapd,
165                                          const u8 *mac)
166 {
167         if (hapd->driver == NULL ||
168             hapd->driver->set_radius_acl_expire == NULL)
169                 return 0;
170         return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
171 }
172
173
174 static int hostapd_set_bss_params(struct hostapd_data *hapd,
175                                   int use_protection)
176 {
177         int ret = 0;
178         int preamble;
179 #ifdef CONFIG_IEEE80211N
180         u8 buf[60], *ht_capab, *ht_oper, *pos;
181
182         pos = buf;
183         ht_capab = pos;
184         pos = hostapd_eid_ht_capabilities(hapd, pos);
185         ht_oper = pos;
186         pos = hostapd_eid_ht_operation(hapd, pos);
187         if (pos > ht_oper && ht_oper > ht_capab &&
188             hostapd_set_ht_params(hapd->conf->iface, hapd,
189                                   ht_capab + 2, ht_capab[1],
190                                   ht_oper + 2, ht_oper[1])) {
191                 wpa_printf(MSG_ERROR, "Could not set HT capabilities "
192                            "for kernel driver");
193                 ret = -1;
194         }
195
196 #endif /* CONFIG_IEEE80211N */
197
198         if (hostapd_set_cts_protect(hapd, use_protection)) {
199                 wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel "
200                            "driver");
201                 ret = -1;
202         }
203
204         if (hapd->iface->current_mode &&
205             hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
206             hostapd_set_short_slot_time(hapd,
207                                         hapd->iface->num_sta_no_short_slot_time
208                                         > 0 ? 0 : 1)) {
209                 wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option "
210                            "in kernel driver");
211                 ret = -1;
212         }
213
214         if (hapd->iface->num_sta_no_short_preamble == 0 &&
215             hapd->iconf->preamble == SHORT_PREAMBLE)
216                 preamble = SHORT_PREAMBLE;
217         else
218                 preamble = LONG_PREAMBLE;
219         if (hostapd_set_preamble(hapd, preamble)) {
220                 wpa_printf(MSG_ERROR, "Could not set preamble for kernel "
221                            "driver");
222                 ret = -1;
223         }
224
225         return ret;
226 }
227
228
229 static int hostapd_set_beacon(const char *ifname, struct hostapd_data *hapd,
230                               const u8 *head, size_t head_len,
231                               const u8 *tail, size_t tail_len, int dtim_period,
232                               int beacon_int)
233 {
234         if (hapd->driver == NULL || hapd->driver->set_beacon == NULL)
235                 return 0;
236         return hapd->driver->set_beacon(ifname, hapd->drv_priv,
237                                         head, head_len, tail, tail_len,
238                                         dtim_period, beacon_int);
239 }
240
241
242 static int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
243 {
244         return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL);
245 }
246
247 static int hostapd_vlan_if_remove(struct hostapd_data *hapd,
248                                   const char *ifname)
249 {
250         return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
251 }
252
253
254 static int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr,
255                                int aid, int val)
256 {
257         if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
258                 return 0;
259         return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val);
260 }
261
262
263 static int hostapd_set_sta_vlan(const char *ifname, struct hostapd_data *hapd,
264                                 const u8 *addr, int vlan_id)
265 {
266         if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL)
267                 return 0;
268         return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname,
269                                           vlan_id);
270 }
271
272
273 static int hostapd_get_inact_sec(struct hostapd_data *hapd, const u8 *addr)
274 {
275         if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL)
276                 return 0;
277         return hapd->driver->get_inact_sec(hapd->drv_priv, addr);
278 }
279
280
281 static int hostapd_sta_deauth(struct hostapd_data *hapd, const u8 *addr,
282                               int reason)
283 {
284         if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
285                 return 0;
286         return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
287                                         reason);
288 }
289
290
291 static int hostapd_sta_disassoc(struct hostapd_data *hapd, const u8 *addr,
292                                 int reason)
293 {
294         if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
295                 return 0;
296         return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
297                                           reason);
298 }
299
300
301 static int hostapd_sta_add(const char *ifname, struct hostapd_data *hapd,
302                            const u8 *addr, u16 aid, u16 capability,
303                            const u8 *supp_rates, size_t supp_rates_len,
304                            u16 listen_interval,
305                            const struct ieee80211_ht_capabilities *ht_capab)
306 {
307         struct hostapd_sta_add_params params;
308
309         if (hapd->driver == NULL)
310                 return 0;
311         if (hapd->driver->sta_add == NULL)
312                 return 0;
313
314         os_memset(&params, 0, sizeof(params));
315         params.addr = addr;
316         params.aid = aid;
317         params.capability = capability;
318         params.supp_rates = supp_rates;
319         params.supp_rates_len = supp_rates_len;
320         params.listen_interval = listen_interval;
321         params.ht_capabilities = ht_capab;
322         return hapd->driver->sta_add(ifname, hapd->drv_priv, &params);
323 }
324
325
326 static int hostapd_sta_remove(struct hostapd_data *hapd, const u8 *addr)
327 {
328         if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
329                 return 0;
330         return hapd->driver->sta_remove(hapd->drv_priv, addr);
331 }
332
333
334 static int hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled)
335 {
336         if (hapd->driver == NULL ||
337             hapd->driver->hapd_set_countermeasures == NULL)
338                 return 0;
339         return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled);
340 }
341
342
343 void hostapd_set_driver_ops(struct hostapd_driver_ops *ops)
344 {
345         ops->set_ap_wps_ie = hostapd_set_ap_wps_ie;
346         ops->send_mgmt_frame = hostapd_send_mgmt_frame;
347         ops->send_eapol = hostapd_send_eapol;
348         ops->set_authorized = hostapd_set_authorized;
349         ops->set_key = hostapd_set_key;
350         ops->read_sta_data = hostapd_read_sta_data;
351         ops->sta_clear_stats = hostapd_sta_clear_stats;
352         ops->set_sta_flags = hostapd_set_sta_flags;
353         ops->set_drv_ieee8021x = hostapd_set_drv_ieee8021x;
354         ops->set_radius_acl_auth = hostapd_set_radius_acl_auth;
355         ops->set_radius_acl_expire = hostapd_set_radius_acl_expire;
356         ops->set_bss_params = hostapd_set_bss_params;
357         ops->set_beacon = hostapd_set_beacon;
358         ops->vlan_if_add = hostapd_vlan_if_add;
359         ops->vlan_if_remove = hostapd_vlan_if_remove;
360         ops->set_wds_sta = hostapd_set_wds_sta;
361         ops->set_sta_vlan = hostapd_set_sta_vlan;
362         ops->get_inact_sec = hostapd_get_inact_sec;
363         ops->sta_deauth = hostapd_sta_deauth;
364         ops->sta_disassoc = hostapd_sta_disassoc;
365         ops->sta_add = hostapd_sta_add;
366         ops->sta_remove = hostapd_sta_remove;
367         ops->set_countermeasures = hostapd_set_countermeasures;
368 }