drv_callbacks.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
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 40int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, 41 const u8 *ie, size_t ielen, int reassoc) 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 if (ie) { 161 struct wpabuf *wps; 162 wps = ieee802_11_vendor_ie_concat(ie, ielen, 163 WPS_IE_VENDOR_TYPE); 164 if (wps && wps_validate_assoc_req(wps) < 0) { 165 hostapd_drv_sta_disassoc( 166 hapd, sta->addr, 167 WLAN_REASON_INVALID_IE); 168 ap_free_sta(hapd, sta); 169 wpabuf_free(wps); 170 return -1; 171 } 172 wpabuf_free(wps); 173 } 174#endif /* CONFIG_WPS_STRICT */ 175 if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 && 176 os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { 177 sta->flags |= WLAN_STA_WPS; 178 } else 179 sta->flags |= WLAN_STA_MAYBE_WPS; 180 } 181skip_wpa_check: 182 183 new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; 184 sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; 185 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); 186 187 hostapd_new_assoc_sta(hapd, sta, !new_assoc); 188 189 ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); 190 191#ifdef CONFIG_P2P 192 p2p_group_notif_assoc(hapd->p2p_group, sta->addr, 193 all_ies, all_ies_len); 194#endif /* CONFIG_P2P */ 195 196 return 0; 197} 198 199 200void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) 201{ 202 struct sta_info *sta; 203 204 if (addr == NULL) { 205 /* 206 * This could potentially happen with unexpected event from the 207 * driver wrapper. This was seen at least in one case where the 208 * driver ended up reporting a station mode event while hostapd 209 * was running, so better make sure we stop processing such an 210 * event here. 211 */ 212 wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event " 213 "with no address"); 214 return; 215 } 216 217 hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, 218 HOSTAPD_LEVEL_INFO, "disassociated"); 219 220 sta = ap_get_sta(hapd, addr); 221 if (sta == NULL) { 222 wpa_printf(MSG_DEBUG, "Disassociation notification for " 223 "unknown STA " MACSTR, MAC2STR(addr)); 224 return; 225 } 226 227 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); 228 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR, 229 MAC2STR(sta->addr)); 230 wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); 231 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; 232 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); 233 ap_free_sta(hapd, sta); 234} 235 236 237void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr) 238{ 239 struct sta_info *sta = ap_get_sta(hapd, addr); 240 241 if (!sta || !hapd->conf->disassoc_low_ack) 242 return; 243 244 hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, 245 HOSTAPD_LEVEL_INFO, "disconnected due to excessive " 246 "missing ACKs"); 247 hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK); 248 if (sta) 249 ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK); 250} 251 252 253int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, 254 const u8 *ie, size_t ie_len) 255{ 256 size_t i; 257 int ret = 0; 258 259 if (sa == NULL || ie == NULL) 260 return -1; 261 262 random_add_randomness(sa, ETH_ALEN); 263 for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) { 264 if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, 265 sa, ie, ie_len) > 0) { 266 ret = 1; 267 break; 268 } 269 } 270 return ret; 271} 272 273 274#ifdef HOSTAPD 275 276#ifdef NEED_AP_MLME 277 278static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len) 279{ 280 u16 fc, type, stype; 281 282 /* 283 * PS-Poll frames are 16 bytes. All other frames are 284 * 24 bytes or longer. 285 */ 286 if (len < 16) 287 return NULL; 288 289 fc = le_to_host16(hdr->frame_control); 290 type = WLAN_FC_GET_TYPE(fc); 291 stype = WLAN_FC_GET_STYPE(fc); 292 293 switch (type) { 294 case WLAN_FC_TYPE_DATA: 295 if (len < 24) 296 return NULL; 297 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) { 298 case WLAN_FC_FROMDS | WLAN_FC_TODS: 299 case WLAN_FC_TODS: 300 return hdr->addr1; 301 case WLAN_FC_FROMDS: 302 return hdr->addr2; 303 default: 304 return NULL; 305 } 306 case WLAN_FC_TYPE_CTRL: 307 if (stype != WLAN_FC_STYPE_PSPOLL) 308 return NULL; 309 return hdr->addr1; 310 case WLAN_FC_TYPE_MGMT: 311 return hdr->addr3; 312 default: 313 return NULL; 314 } 315} 316 317 318#define HAPD_BROADCAST ((struct hostapd_data *) -1) 319 320static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface, 321 const u8 *bssid) 322{ 323 size_t i; 324 325 if (bssid == NULL) 326 return NULL; 327 if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff && 328 bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff) 329 return HAPD_BROADCAST; 330 331 for (i = 0; i < iface->num_bss; i++) { 332 if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) 333 return iface->bss[i]; 334 } 335 336 return NULL; 337} 338 339 340static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd, 341 const u8 *frame, size_t len) 342{ 343 const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame; 344 u16 fc = le_to_host16(hdr->frame_control); 345 hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len)); 346 if (hapd == NULL || hapd == HAPD_BROADCAST) 347 return; 348 349 ieee802_11_rx_from_unknown(hapd, hdr->addr2, 350 (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == 351 (WLAN_FC_TODS | WLAN_FC_FROMDS)); 352} 353 354 355static void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt) 356{ 357 struct hostapd_iface *iface = hapd->iface; 358 const struct ieee80211_hdr *hdr; 359 const u8 *bssid; 360 struct hostapd_frame_info fi; 361 362 hdr = (const struct ieee80211_hdr *) rx_mgmt->frame; 363 bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len); 364 if (bssid == NULL) 365 return; 366 367 hapd = get_hapd_bssid(iface, bssid); 368 if (hapd == NULL) { 369 u16 fc; 370 fc = le_to_host16(hdr->frame_control); 371 372 /* 373 * Drop frames to unknown BSSIDs except for Beacon frames which 374 * could be used to update neighbor information. 375 */ 376 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && 377 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) 378 hapd = iface->bss[0]; 379 else 380 return; 381 } 382 383 os_memset(&fi, 0, sizeof(fi)); 384 fi.datarate = rx_mgmt->datarate; 385 fi.ssi_signal = rx_mgmt->ssi_signal; 386 387 if (hapd == HAPD_BROADCAST) { 388 size_t i; 389 for (i = 0; i < iface->num_bss; i++) 390 ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame, 391 rx_mgmt->frame_len, &fi); 392 } else 393 ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi); 394 395 random_add_randomness(&fi, sizeof(fi)); 396} 397 398 399static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf, 400 size_t len, 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 410#endif /* NEED_AP_MLME */ 411 412 413static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr) 414{ 415 struct sta_info *sta = ap_get_sta(hapd, addr); 416 if (sta) 417 return 0; 418 419 wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR 420 " - adding a new STA", MAC2STR(addr)); 421 sta = ap_sta_add(hapd, addr); 422 if (sta) { 423 hostapd_new_assoc_sta(hapd, sta, 0); 424 } else { 425 wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR, 426 MAC2STR(addr)); 427 return -1; 428 } 429 430 return 0; 431} 432 433 434static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src, 435 const u8 *data, size_t data_len) 436{ 437 struct hostapd_iface *iface = hapd->iface; 438 size_t j; 439 440 for (j = 0; j < iface->num_bss; j++) { 441 if (ap_get_sta(iface->bss[j], src)) { 442 hapd = iface->bss[j]; 443 break; 444 } 445 } 446 447 ieee802_1x_receive(hapd, src, data, data_len); 448} 449 450 451void wpa_supplicant_event(void *ctx, enum wpa_event_type event, 452 union wpa_event_data *data) 453{ 454 struct hostapd_data *hapd = ctx; 455 456 switch (event) { 457 case EVENT_MICHAEL_MIC_FAILURE: 458 michael_mic_failure(hapd, data->michael_mic_failure.src, 1); 459 break; 460 case EVENT_SCAN_RESULTS: 461 if (hapd->iface->scan_cb) 462 hapd->iface->scan_cb(hapd->iface); 463 break; 464#ifdef CONFIG_IEEE80211R 465 case EVENT_FT_RRB_RX: 466 wpa_ft_rrb_rx(hapd->wpa_auth, data->ft_rrb_rx.src, 467 data->ft_rrb_rx.data, data->ft_rrb_rx.data_len); 468 break; 469#endif /* CONFIG_IEEE80211R */ 470 case EVENT_WPS_BUTTON_PUSHED: 471 hostapd_wps_button_pushed(hapd, NULL); 472 break; 473#ifdef NEED_AP_MLME 474 case EVENT_TX_STATUS: 475 switch (data->tx_status.type) { 476 case WLAN_FC_TYPE_MGMT: 477 hostapd_mgmt_tx_cb(hapd, data->tx_status.data, 478 data->tx_status.data_len, 479 data->tx_status.stype, 480 data->tx_status.ack); 481 break; 482 case WLAN_FC_TYPE_DATA: 483 hostapd_tx_status(hapd, data->tx_status.dst, 484 data->tx_status.data, 485 data->tx_status.data_len, 486 data->tx_status.ack); 487 break; 488 } 489 break; 490 case EVENT_RX_FROM_UNKNOWN: 491 hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame, 492 data->rx_from_unknown.len); 493 break; 494 case EVENT_RX_MGMT: 495 hostapd_mgmt_rx(hapd, &data->rx_mgmt); 496 break; 497#endif /* NEED_AP_MLME */ 498 case EVENT_RX_PROBE_REQ: 499 if (data->rx_probe_req.sa == NULL || 500 data->rx_probe_req.ie == NULL) 501 break; 502 hostapd_probe_req_rx(hapd, data->rx_probe_req.sa, 503 data->rx_probe_req.ie, 504 data->rx_probe_req.ie_len); 505 break; 506 case EVENT_NEW_STA: 507 hostapd_event_new_sta(hapd, data->new_sta.addr); 508 break; 509 case EVENT_EAPOL_RX: 510 hostapd_event_eapol_rx(hapd, data->eapol_rx.src, 511 data->eapol_rx.data, 512 data->eapol_rx.data_len); 513 break; 514 case EVENT_ASSOC: 515 hostapd_notif_assoc(hapd, data->assoc_info.addr, 516 data->assoc_info.req_ies, 517 data->assoc_info.req_ies_len, 518 data->assoc_info.reassoc); 519 break; 520 case EVENT_DISASSOC: 521 if (data) 522 hostapd_notif_disassoc(hapd, data->disassoc_info.addr); 523 break; 524 case EVENT_DEAUTH: 525 if (data) 526 hostapd_notif_disassoc(hapd, data->deauth_info.addr); 527 break; 528 case EVENT_STATION_LOW_ACK: 529 if (!data) 530 break; 531 hostapd_event_sta_low_ack(hapd, data->low_ack.addr); 532 break; 533 default: 534 wpa_printf(MSG_DEBUG, "Unknown event %d", event); 535 break; 536 } 537} 538 539#endif /* HOSTAPD */ 540