Allow AP mode to disconnect STAs based on low ACK condition
[mech_eap.git] / src / ap / drv_callbacks.c
1 /*
2  * hostapd / Callback functions for driver wrappers
3  * Copyright (c) 2002-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 "utils/includes.h"
16
17 #include "utils/common.h"
18 #include "radius/radius.h"
19 #include "drivers/driver.h"
20 #include "common/ieee802_11_defs.h"
21 #include "common/ieee802_11_common.h"
22 #include "common/wpa_ctrl.h"
23 #include "crypto/random.h"
24 #include "p2p/p2p.h"
25 #include "wps/wps.h"
26 #include "hostapd.h"
27 #include "ieee802_11.h"
28 #include "sta_info.h"
29 #include "accounting.h"
30 #include "tkip_countermeasures.h"
31 #include "iapp.h"
32 #include "ieee802_1x.h"
33 #include "wpa_auth.h"
34 #include "wmm.h"
35 #include "wps_hostapd.h"
36 #include "ap_drv_ops.h"
37 #include "ap_config.h"
38
39
40 int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
41                         const u8 *ie, size_t ielen)
42 {
43         struct sta_info *sta;
44         int new_assoc, res;
45         struct ieee802_11_elems elems;
46 #ifdef CONFIG_P2P
47         const u8 *all_ies = ie;
48         size_t all_ies_len = ielen;
49 #endif /* CONFIG_P2P */
50
51         if (addr == NULL) {
52                 /*
53                  * This could potentially happen with unexpected event from the
54                  * driver wrapper. This was seen at least in one case where the
55                  * driver ended up being set to station mode while hostapd was
56                  * running, so better make sure we stop processing such an
57                  * event here.
58                  */
59                 wpa_printf(MSG_DEBUG, "hostapd_notif_assoc: Skip event with "
60                            "no address");
61                 return -1;
62         }
63         random_add_randomness(addr, ETH_ALEN);
64
65         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
66                        HOSTAPD_LEVEL_INFO, "associated");
67
68         ieee802_11_parse_elems(ie, ielen, &elems, 0);
69         if (elems.wps_ie) {
70                 ie = elems.wps_ie - 2;
71                 ielen = elems.wps_ie_len + 2;
72                 wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq");
73         } else if (elems.rsn_ie) {
74                 ie = elems.rsn_ie - 2;
75                 ielen = elems.rsn_ie_len + 2;
76                 wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq");
77         } else if (elems.wpa_ie) {
78                 ie = elems.wpa_ie - 2;
79                 ielen = elems.wpa_ie_len + 2;
80                 wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
81         } else {
82                 ie = NULL;
83                 ielen = 0;
84                 wpa_printf(MSG_DEBUG, "STA did not include WPS/RSN/WPA IE in "
85                            "(Re)AssocReq");
86         }
87
88         sta = ap_get_sta(hapd, addr);
89         if (sta) {
90                 accounting_sta_stop(hapd, sta);
91         } else {
92                 sta = ap_sta_add(hapd, addr);
93                 if (sta == NULL)
94                         return -1;
95         }
96         sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
97
98 #ifdef CONFIG_P2P
99         if (elems.p2p) {
100                 wpabuf_free(sta->p2p_ie);
101                 sta->p2p_ie = ieee802_11_vendor_ie_concat(all_ies, all_ies_len,
102                                                           P2P_IE_VENDOR_TYPE);
103         }
104 #endif /* CONFIG_P2P */
105
106         if (hapd->conf->wpa) {
107                 if (ie == NULL || ielen == 0) {
108                         if (hapd->conf->wps_state) {
109                                 wpa_printf(MSG_DEBUG, "STA did not include "
110                                            "WPA/RSN IE in (Re)Association "
111                                            "Request - possible WPS use");
112                                 sta->flags |= WLAN_STA_MAYBE_WPS;
113                                 goto skip_wpa_check;
114                         }
115
116                         wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
117                         return -1;
118                 }
119                 if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
120                     os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
121                         sta->flags |= WLAN_STA_WPS;
122                         goto skip_wpa_check;
123                 }
124
125                 if (sta->wpa_sm == NULL)
126                         sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
127                                                         sta->addr);
128                 if (sta->wpa_sm == NULL) {
129                         wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
130                                    "machine");
131                         return -1;
132                 }
133                 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
134                                           ie, ielen, NULL, 0);
135                 if (res != WPA_IE_OK) {
136                         int resp;
137                         wpa_printf(MSG_DEBUG, "WPA/RSN information element "
138                                    "rejected? (res %u)", res);
139                         wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
140                         if (res == WPA_INVALID_GROUP)
141                                 resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
142                         else if (res == WPA_INVALID_PAIRWISE)
143                                 resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
144                         else if (res == WPA_INVALID_AKMP)
145                                 resp = WLAN_REASON_AKMP_NOT_VALID;
146 #ifdef CONFIG_IEEE80211W
147                         else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
148                                 resp = WLAN_REASON_INVALID_IE;
149                         else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
150                                 resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
151 #endif /* CONFIG_IEEE80211W */
152                         else
153                                 resp = WLAN_REASON_INVALID_IE;
154                         hostapd_drv_sta_disassoc(hapd, sta->addr, resp);
155                         ap_free_sta(hapd, sta);
156                         return -1;
157                 }
158         } else if (hapd->conf->wps_state) {
159 #ifdef CONFIG_WPS_STRICT
160                 struct wpabuf *wps;
161                 wps = ieee802_11_vendor_ie_concat(ie, ielen,
162                                                   WPS_IE_VENDOR_TYPE);
163                 if (wps && wps_validate_assoc_req(wps) < 0) {
164                         hostapd_drv_sta_disassoc(hapd, sta->addr,
165                                                  WLAN_REASON_INVALID_IE);
166                         ap_free_sta(hapd, sta);
167                         wpabuf_free(wps);
168                         return -1;
169                 }
170                 wpabuf_free(wps);
171 #endif /* CONFIG_WPS_STRICT */
172                 if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
173                     os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
174                         sta->flags |= WLAN_STA_WPS;
175                 } else
176                         sta->flags |= WLAN_STA_MAYBE_WPS;
177         }
178 skip_wpa_check:
179
180         new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
181         sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
182         wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
183
184         hostapd_new_assoc_sta(hapd, sta, !new_assoc);
185
186         ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
187
188 #ifdef CONFIG_P2P
189         p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
190                               all_ies, all_ies_len);
191 #endif /* CONFIG_P2P */
192
193         return 0;
194 }
195
196
197 void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
198 {
199         struct sta_info *sta;
200
201         if (addr == NULL) {
202                 /*
203                  * This could potentially happen with unexpected event from the
204                  * driver wrapper. This was seen at least in one case where the
205                  * driver ended up reporting a station mode event while hostapd
206                  * was running, so better make sure we stop processing such an
207                  * event here.
208                  */
209                 wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event "
210                            "with no address");
211                 return;
212         }
213
214         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
215                        HOSTAPD_LEVEL_INFO, "disassociated");
216
217         sta = ap_get_sta(hapd, addr);
218         if (sta == NULL) {
219                 wpa_printf(MSG_DEBUG, "Disassociation notification for "
220                            "unknown STA " MACSTR, MAC2STR(addr));
221                 return;
222         }
223
224         sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
225         wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
226                 MAC2STR(sta->addr));
227         wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
228         sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
229         ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
230         ap_free_sta(hapd, sta);
231 }
232
233
234 void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
235 {
236         struct sta_info *sta = ap_get_sta(hapd, addr);
237
238         if (!sta || !hapd->conf->disassoc_low_ack)
239                 return;
240
241         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
242                        HOSTAPD_LEVEL_INFO, "disconnected due to excessive "
243                        "missing ACKs");
244         hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
245         if (sta)
246                 ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
247 }
248
249
250 #ifdef HOSTAPD
251
252 #ifdef NEED_AP_MLME
253
254 static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
255 {
256         u16 fc, type, stype;
257
258         /*
259          * PS-Poll frames are 16 bytes. All other frames are
260          * 24 bytes or longer.
261          */
262         if (len < 16)
263                 return NULL;
264
265         fc = le_to_host16(hdr->frame_control);
266         type = WLAN_FC_GET_TYPE(fc);
267         stype = WLAN_FC_GET_STYPE(fc);
268
269         switch (type) {
270         case WLAN_FC_TYPE_DATA:
271                 if (len < 24)
272                         return NULL;
273                 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
274                 case WLAN_FC_FROMDS | WLAN_FC_TODS:
275                 case WLAN_FC_TODS:
276                         return hdr->addr1;
277                 case WLAN_FC_FROMDS:
278                         return hdr->addr2;
279                 default:
280                         return NULL;
281                 }
282         case WLAN_FC_TYPE_CTRL:
283                 if (stype != WLAN_FC_STYPE_PSPOLL)
284                         return NULL;
285                 return hdr->addr1;
286         case WLAN_FC_TYPE_MGMT:
287                 return hdr->addr3;
288         default:
289                 return NULL;
290         }
291 }
292
293
294 #define HAPD_BROADCAST ((struct hostapd_data *) -1)
295
296 static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
297                                             const u8 *bssid)
298 {
299         size_t i;
300
301         if (bssid == NULL)
302                 return NULL;
303         if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
304             bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
305                 return HAPD_BROADCAST;
306
307         for (i = 0; i < iface->num_bss; i++) {
308                 if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)
309                         return iface->bss[i];
310         }
311
312         return NULL;
313 }
314
315
316 static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
317                                         const u8 *frame, size_t len)
318 {
319         const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame;
320         u16 fc = le_to_host16(hdr->frame_control);
321         hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
322         if (hapd == NULL || hapd == HAPD_BROADCAST)
323                 return;
324
325         ieee802_11_rx_from_unknown(hapd, hdr->addr2,
326                                    (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
327                                    (WLAN_FC_TODS | WLAN_FC_FROMDS));
328 }
329
330
331 static void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
332 {
333         struct hostapd_iface *iface = hapd->iface;
334         const struct ieee80211_hdr *hdr;
335         const u8 *bssid;
336         struct hostapd_frame_info fi;
337
338         hdr = (const struct ieee80211_hdr *) rx_mgmt->frame;
339         bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len);
340         if (bssid == NULL)
341                 return;
342
343         hapd = get_hapd_bssid(iface, bssid);
344         if (hapd == NULL) {
345                 u16 fc;
346                 fc = le_to_host16(hdr->frame_control);
347
348                 /*
349                  * Drop frames to unknown BSSIDs except for Beacon frames which
350                  * could be used to update neighbor information.
351                  */
352                 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
353                     WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
354                         hapd = iface->bss[0];
355                 else
356                         return;
357         }
358
359         os_memset(&fi, 0, sizeof(fi));
360         fi.datarate = rx_mgmt->datarate;
361         fi.ssi_signal = rx_mgmt->ssi_signal;
362
363         if (hapd == HAPD_BROADCAST) {
364                 size_t i;
365                 for (i = 0; i < iface->num_bss; i++)
366                         ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
367                                         rx_mgmt->frame_len, &fi);
368         } else
369                 ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi);
370
371         random_add_randomness(&fi, sizeof(fi));
372 }
373
374
375 static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
376                                size_t len, u16 stype, int ok)
377 {
378         struct ieee80211_hdr *hdr;
379         hdr = (struct ieee80211_hdr *) buf;
380         hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
381         if (hapd == NULL || hapd == HAPD_BROADCAST)
382                 return;
383         ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
384 }
385
386 #endif /* NEED_AP_MLME */
387
388
389 static int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
390                                 const u8 *ie, size_t ie_len)
391 {
392         size_t i;
393         int ret = 0;
394
395         if (sa)
396                 random_add_randomness(sa, ETH_ALEN);
397         for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
398                 if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
399                                             sa, ie, ie_len) > 0) {
400                         ret = 1;
401                         break;
402                 }
403         }
404         return ret;
405 }
406
407
408 static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
409 {
410         struct sta_info *sta = ap_get_sta(hapd, addr);
411         if (sta)
412                 return 0;
413
414         wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
415                    " - adding a new STA", MAC2STR(addr));
416         sta = ap_sta_add(hapd, addr);
417         if (sta) {
418                 hostapd_new_assoc_sta(hapd, sta, 0);
419         } else {
420                 wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
421                            MAC2STR(addr));
422                 return -1;
423         }
424
425         return 0;
426 }
427
428
429 static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
430                                    const u8 *data, size_t data_len)
431 {
432         struct hostapd_iface *iface = hapd->iface;
433         size_t j;
434
435         for (j = 0; j < iface->num_bss; j++) {
436                 if (ap_get_sta(iface->bss[j], src)) {
437                         hapd = iface->bss[j];
438                         break;
439                 }
440         }
441
442         ieee802_1x_receive(hapd, src, data, data_len);
443 }
444
445
446 void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
447                           union wpa_event_data *data)
448 {
449         struct hostapd_data *hapd = ctx;
450
451         switch (event) {
452         case EVENT_MICHAEL_MIC_FAILURE:
453                 michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
454                 break;
455         case EVENT_SCAN_RESULTS:
456                 if (hapd->iface->scan_cb)
457                         hapd->iface->scan_cb(hapd->iface);
458                 break;
459 #ifdef CONFIG_IEEE80211R
460         case EVENT_FT_RRB_RX:
461                 wpa_ft_rrb_rx(hapd->wpa_auth, data->ft_rrb_rx.src,
462                               data->ft_rrb_rx.data, data->ft_rrb_rx.data_len);
463                 break;
464 #endif /* CONFIG_IEEE80211R */
465         case EVENT_WPS_BUTTON_PUSHED:
466                 hostapd_wps_button_pushed(hapd);
467                 break;
468 #ifdef NEED_AP_MLME
469         case EVENT_TX_STATUS:
470                 switch (data->tx_status.type) {
471                 case WLAN_FC_TYPE_MGMT:
472                         hostapd_mgmt_tx_cb(hapd, data->tx_status.data,
473                                            data->tx_status.data_len,
474                                            data->tx_status.stype,
475                                            data->tx_status.ack);
476                         break;
477                 case WLAN_FC_TYPE_DATA:
478                         hostapd_tx_status(hapd, data->tx_status.dst,
479                                           data->tx_status.data,
480                                           data->tx_status.data_len,
481                                           data->tx_status.ack);
482                         break;
483                 }
484                 break;
485         case EVENT_RX_FROM_UNKNOWN:
486                 hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame,
487                                             data->rx_from_unknown.len);
488                 break;
489         case EVENT_RX_MGMT:
490                 hostapd_mgmt_rx(hapd, &data->rx_mgmt);
491                 break;
492 #endif /* NEED_AP_MLME */
493         case EVENT_RX_PROBE_REQ:
494                 hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
495                                      data->rx_probe_req.ie,
496                                      data->rx_probe_req.ie_len);
497                 break;
498         case EVENT_NEW_STA:
499                 hostapd_event_new_sta(hapd, data->new_sta.addr);
500                 break;
501         case EVENT_EAPOL_RX:
502                 hostapd_event_eapol_rx(hapd, data->eapol_rx.src,
503                                        data->eapol_rx.data,
504                                        data->eapol_rx.data_len);
505                 break;
506         case EVENT_ASSOC:
507                 hostapd_notif_assoc(hapd, data->assoc_info.addr,
508                                     data->assoc_info.req_ies,
509                                     data->assoc_info.req_ies_len);
510                 break;
511         case EVENT_DISASSOC:
512                 if (data)
513                         hostapd_notif_disassoc(hapd, data->disassoc_info.addr);
514                 break;
515         case EVENT_DEAUTH:
516                 if (data)
517                         hostapd_notif_disassoc(hapd, data->deauth_info.addr);
518                 break;
519         case EVENT_STATION_LOW_ACK:
520                 if (!data)
521                         break;
522                 hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
523                 break;
524         default:
525                 wpa_printf(MSG_DEBUG, "Unknown event %d", event);
526                 break;
527         }
528 }
529
530 #endif /* HOSTAPD */