Conver hostapd specific files to include common.h
[libeap.git] / hostapd / 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 "includes.h"
16
17 #include "common.h"
18 #include "hostapd.h"
19 #include "driver_i.h"
20 #include "ieee802_11.h"
21 #include "radius/radius.h"
22 #include "sta_flags.h"
23 #include "sta_info.h"
24 #include "accounting.h"
25 #include "tkip_countermeasures.h"
26 #include "ieee802_1x.h"
27 #include "wpa.h"
28 #include "iapp.h"
29 #include "wme.h"
30 #include "wps_hostapd.h"
31
32
33 struct prune_data {
34         struct hostapd_data *hapd;
35         const u8 *addr;
36 };
37
38 static int prune_associations(struct hostapd_iface *iface, void *ctx)
39 {
40         struct prune_data *data = ctx;
41         struct sta_info *osta;
42         struct hostapd_data *ohapd;
43         size_t j;
44
45         for (j = 0; j < iface->num_bss; j++) {
46                 ohapd = iface->bss[j];
47                 if (ohapd == data->hapd)
48                         continue;
49                 osta = ap_get_sta(ohapd, data->addr);
50                 if (!osta)
51                         continue;
52
53                 ap_sta_disassociate(ohapd, osta, WLAN_REASON_UNSPECIFIED);
54         }
55
56         return 0;
57 }
58
59 /**
60  * hostapd_prune_associations - Remove extraneous associations
61  * @hapd: Pointer to BSS data for the most recent association
62  * @sta: Pointer to the associated STA data
63  *
64  * This function looks through all radios and BSS's for previous
65  * (stale) associations of STA. If any are found they are removed.
66  */
67 static void hostapd_prune_associations(struct hostapd_data *hapd,
68                                        struct sta_info *sta)
69 {
70         struct prune_data data;
71         data.hapd = hapd;
72         data.addr = sta->addr;
73         hostapd_for_each_interface(prune_associations, &data);
74 }
75
76
77 /**
78  * hostapd_new_assoc_sta - Notify that a new station associated with the AP
79  * @hapd: Pointer to BSS data
80  * @sta: Pointer to the associated STA data
81  * @reassoc: 1 to indicate this was a re-association; 0 = first association
82  *
83  * This function will be called whenever a station associates with the AP. It
84  * can be called from ieee802_11.c for drivers that export MLME to hostapd and
85  * from driver_*.c for drivers that take care of management frames (IEEE 802.11
86  * authentication and association) internally.
87  */
88 void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
89                            int reassoc)
90 {
91         if (hapd->tkip_countermeasures) {
92                 hostapd_sta_deauth(hapd, sta->addr,
93                                    WLAN_REASON_MICHAEL_MIC_FAILURE);
94                 return;
95         }
96
97         hostapd_prune_associations(hapd, sta);
98
99         /* IEEE 802.11F (IAPP) */
100         if (hapd->conf->ieee802_11f)
101                 iapp_new_station(hapd->iapp, sta);
102
103         /* Start accounting here, if IEEE 802.1X and WPA are not used.
104          * IEEE 802.1X/WPA code will start accounting after the station has
105          * been authorized. */
106         if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
107                 accounting_sta_start(hapd, sta);
108
109         hostapd_wmm_sta_config(hapd, sta);
110
111         /* Start IEEE 802.1X authentication process for new stations */
112         ieee802_1x_new_station(hapd, sta);
113         if (reassoc) {
114                 if (sta->auth_alg != WLAN_AUTH_FT &&
115                     !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
116                         wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
117         } else
118                 wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
119 }
120
121
122 void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
123                        const u8 *buf, size_t len, int ack)
124 {
125         struct sta_info *sta;
126         struct hostapd_iface *iface = hapd->iface;
127
128         sta = ap_get_sta(hapd, addr);
129         if (sta == NULL && iface->num_bss > 1) {
130                 size_t j;
131                 for (j = 0; j < iface->num_bss; j++) {
132                         hapd = iface->bss[j];
133                         sta = ap_get_sta(hapd, addr);
134                         if (sta)
135                                 break;
136                 }
137         }
138         if (sta == NULL)
139                 return;
140         if (sta->flags & WLAN_STA_PENDING_POLL) {
141                 wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
142                            "activity poll", MAC2STR(sta->addr),
143                            ack ? "ACKed" : "did not ACK");
144                 if (ack)
145                         sta->flags &= ~WLAN_STA_PENDING_POLL;
146         }
147
148         ieee802_1x_tx_status(hapd, sta, buf, len, ack);
149 }
150
151
152 static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
153 {
154         u16 fc, type, stype;
155
156         /*
157          * PS-Poll frames are 16 bytes. All other frames are
158          * 24 bytes or longer.
159          */
160         if (len < 16)
161                 return NULL;
162
163         fc = le_to_host16(hdr->frame_control);
164         type = WLAN_FC_GET_TYPE(fc);
165         stype = WLAN_FC_GET_STYPE(fc);
166
167         switch (type) {
168         case WLAN_FC_TYPE_DATA:
169                 if (len < 24)
170                         return NULL;
171                 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
172                 case WLAN_FC_TODS:
173                         return hdr->addr1;
174                 case WLAN_FC_FROMDS:
175                         return hdr->addr2;
176                 default:
177                         return NULL;
178                 }
179         case WLAN_FC_TYPE_CTRL:
180                 if (stype != WLAN_FC_STYPE_PSPOLL)
181                         return NULL;
182                 return hdr->addr1;
183         case WLAN_FC_TYPE_MGMT:
184                 return hdr->addr3;
185         default:
186                 return NULL;
187         }
188 }
189
190
191 #define HAPD_BROADCAST ((struct hostapd_data *) -1)
192
193 static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
194                                             const u8 *bssid)
195 {
196         size_t i;
197
198         if (bssid == NULL)
199                 return NULL;
200         if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
201             bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
202                 return HAPD_BROADCAST;
203
204         for (i = 0; i < iface->num_bss; i++) {
205                 if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)
206                         return iface->bss[i];
207         }
208
209         return NULL;
210 }
211
212
213 void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
214                                  const struct ieee80211_hdr *hdr, size_t len)
215 {
216         struct sta_info *sta;
217         const u8 *addr;
218
219         hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
220         if (hapd == NULL || hapd == HAPD_BROADCAST)
221                 return;
222
223         addr = hdr->addr2;
224         sta = ap_get_sta(hapd, addr);
225         if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
226                 wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated "
227                            "STA " MACSTR, MAC2STR(addr));
228                 if (sta && (sta->flags & WLAN_STA_AUTH))
229                         hostapd_sta_disassoc(
230                                 hapd, addr,
231                                 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
232                 else
233                         hostapd_sta_deauth(
234                                 hapd, addr,
235                                 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
236         }
237 }
238
239
240 int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
241                         const u8 *ie, size_t ielen)
242 {
243         struct sta_info *sta;
244         int new_assoc, res;
245
246         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
247                        HOSTAPD_LEVEL_INFO, "associated");
248
249         sta = ap_get_sta(hapd, addr);
250         if (sta) {
251                 accounting_sta_stop(hapd, sta);
252         } else {
253                 sta = ap_sta_add(hapd, addr);
254                 if (sta == NULL)
255                         return -1;
256         }
257         sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
258
259         if (hapd->conf->wpa) {
260                 if (ie == NULL || ielen == 0) {
261                         if (hapd->conf->wps_state) {
262                                 wpa_printf(MSG_DEBUG, "STA did not include "
263                                            "WPA/RSN IE in (Re)Association "
264                                            "Request - possible WPS use");
265                                 sta->flags |= WLAN_STA_MAYBE_WPS;
266                                 goto skip_wpa_check;
267                         }
268
269                         wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
270                         return -1;
271                 }
272                 if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
273                     os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
274                         sta->flags |= WLAN_STA_WPS;
275                         goto skip_wpa_check;
276                 }
277
278                 if (sta->wpa_sm == NULL)
279                         sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
280                                                         sta->addr);
281                 if (sta->wpa_sm == NULL) {
282                         wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
283                                    "machine");
284                         return -1;
285                 }
286                 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
287                                           ie, ielen, NULL, 0);
288                 if (res != WPA_IE_OK) {
289                         int resp;
290                         wpa_printf(MSG_DEBUG, "WPA/RSN information element "
291                                    "rejected? (res %u)", res);
292                         wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
293                         if (res == WPA_INVALID_GROUP)
294                                 resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
295                         else if (res == WPA_INVALID_PAIRWISE)
296                                 resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
297                         else if (res == WPA_INVALID_AKMP)
298                                 resp = WLAN_REASON_AKMP_NOT_VALID;
299 #ifdef CONFIG_IEEE80211W
300                         else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
301                                 resp = WLAN_REASON_INVALID_IE;
302                         else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
303                                 resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
304 #endif /* CONFIG_IEEE80211W */
305                         else
306                                 resp = WLAN_REASON_INVALID_IE;
307                         hostapd_sta_disassoc(hapd, sta->addr, resp);
308                         ap_free_sta(hapd, sta);
309                         return -1;
310                 }
311         } else if (hapd->conf->wps_state) {
312                 if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
313                     os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
314                         sta->flags |= WLAN_STA_WPS;
315                 } else
316                         sta->flags |= WLAN_STA_MAYBE_WPS;
317         }
318 skip_wpa_check:
319
320         new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
321         sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
322         wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
323
324         hostapd_new_assoc_sta(hapd, sta, !new_assoc);
325
326         ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
327
328         return 0;
329 }
330
331
332 void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
333 {
334         struct sta_info *sta;
335
336         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
337                        HOSTAPD_LEVEL_INFO, "disassociated");
338
339         sta = ap_get_sta(hapd, addr);
340         if (sta == NULL) {
341                 wpa_printf(MSG_DEBUG, "Disassociation notification for "
342                            "unknown STA " MACSTR, MAC2STR(addr));
343                 return;
344         }
345
346         sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
347         wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
348         sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
349         ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
350         ap_free_sta(hapd, sta);
351 }
352
353
354 void hostapd_eapol_receive(struct hostapd_data *hapd, const u8 *sa,
355                            const u8 *buf, size_t len)
356 {
357         ieee802_1x_receive(hapd, sa, buf, len);
358 }
359
360
361 #ifdef NEED_AP_MLME
362 void hostapd_mgmt_rx(struct hostapd_data *hapd, u8 *buf, size_t len,
363                      u16 stype, struct hostapd_frame_info *fi)
364 {
365         struct hostapd_iface *iface = hapd->iface;
366         struct ieee80211_hdr *hdr;
367         const u8 *bssid;
368
369         hdr = (struct ieee80211_hdr *) buf;
370         bssid = get_hdr_bssid(hdr, len);
371         if (bssid == NULL)
372                 return;
373
374         hapd = get_hapd_bssid(iface, bssid);
375         if (hapd == NULL) {
376                 u16 fc;
377                 fc = le_to_host16(hdr->frame_control);
378
379                 /*
380                  * Drop frames to unknown BSSIDs except for Beacon frames which
381                  * could be used to update neighbor information.
382                  */
383                 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
384                     WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
385                         hapd = iface->bss[0];
386                 else
387                         return;
388         }
389
390         if (hapd == HAPD_BROADCAST) {
391                 size_t i;
392                 for (i = 0; i < iface->num_bss; i++)
393                         ieee802_11_mgmt(iface->bss[i], buf, len, stype, fi);
394         } else
395                 ieee802_11_mgmt(hapd, buf, len, stype, fi);
396 }
397
398
399 void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
400                         u16 stype, int ok)
401 {
402         struct ieee80211_hdr *hdr;
403         hdr = (struct ieee80211_hdr *) buf;
404         hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
405         if (hapd == NULL || hapd == HAPD_BROADCAST)
406                 return;
407         ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
408 }
409 #endif /* NEED_AP_MLME */
410
411
412 void hostapd_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr)
413 {
414         michael_mic_failure(hapd, addr, 1);
415 }
416
417
418 struct hostapd_data * hostapd_sta_get_bss(struct hostapd_data *hapd,
419                                           const u8 *addr)
420 {
421         struct hostapd_iface *iface = hapd->iface;
422         size_t j;
423
424         for (j = 0; j < iface->num_bss; j++) {
425                 hapd = iface->bss[j];
426                 if (ap_get_sta(hapd, addr))
427                         return hapd;
428         }
429
430         return NULL;
431 }
432
433
434 #ifndef CONFIG_AP
435 void wpa_supplicant_event(void *ctx, wpa_event_type event,
436                           union wpa_event_data *data)
437 {
438         struct hostapd_data *hapd = ctx;
439
440         switch (event) {
441         case EVENT_MICHAEL_MIC_FAILURE:
442                 michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
443                 break;
444         case EVENT_SCAN_RESULTS:
445                 if (hapd->iface->scan_cb)
446                         hapd->iface->scan_cb(hapd->iface);
447                 break;
448         default:
449                 wpa_printf(MSG_DEBUG, "Unknown event %d", event);
450                 break;
451         }
452 }
453 #endif /* CONFIG_AP */
454
455
456 void hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
457                          const u8 *ie, size_t ie_len)
458 {
459         size_t i;
460
461         for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
462                 hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
463                                         sa, ie, ie_len);
464 }
465
466
467 void hostapd_button_pushed(struct hostapd_data *hapd)
468 {
469         hostapd_wps_button_pushed(hapd);
470 }