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