drv_callbacks.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 
00018 #include "hostapd.h"
00019 #include "driver_i.h"
00020 #include "ieee802_11.h"
00021 #include "radius/radius.h"
00022 #include "sta_info.h"
00023 #include "accounting.h"
00024 #include "tkip_countermeasures.h"
00025 #include "ieee802_1x.h"
00026 #include "wpa.h"
00027 #include "iapp.h"
00028 #include "wme.h"
00029 #include "wps_hostapd.h"
00030 
00031 
00032 struct prune_data {
00033         struct hostapd_data *hapd;
00034         const u8 *addr;
00035 };
00036 
00037 static int prune_associations(struct hostapd_iface *iface, void *ctx)
00038 {
00039         struct prune_data *data = ctx;
00040         struct sta_info *osta;
00041         struct hostapd_data *ohapd;
00042         size_t j;
00043 
00044         for (j = 0; j < iface->num_bss; j++) {
00045                 ohapd = iface->bss[j];
00046                 if (ohapd == data->hapd)
00047                         continue;
00048                 osta = ap_get_sta(ohapd, data->addr);
00049                 if (!osta)
00050                         continue;
00051 
00052                 ap_sta_disassociate(ohapd, osta, WLAN_REASON_UNSPECIFIED);
00053         }
00054 
00055         return 0;
00056 }
00057 
00067 static void hostapd_prune_associations(struct hostapd_data *hapd,
00068                                        struct sta_info *sta)
00069 {
00070         struct prune_data data;
00071         data.hapd = hapd;
00072         data.addr = sta->addr;
00073         hostapd_for_each_interface(prune_associations, &data);
00074 }
00075 
00076 
00089 void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
00090                            int reassoc)
00091 {
00092         if (hapd->tkip_countermeasures) {
00093                 hostapd_sta_deauth(hapd, sta->addr,
00094                                    WLAN_REASON_MICHAEL_MIC_FAILURE);
00095                 return;
00096         }
00097 
00098         hostapd_prune_associations(hapd, sta);
00099 
00100         /* IEEE 802.11F (IAPP) */
00101         if (hapd->conf->ieee802_11f)
00102                 iapp_new_station(hapd->iapp, sta);
00103 
00104         /* Start accounting here, if IEEE 802.1X and WPA are not used.
00105          * IEEE 802.1X/WPA code will start accounting after the station has
00106          * been authorized. */
00107         if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
00108                 accounting_sta_start(hapd, sta);
00109 
00110         hostapd_wmm_sta_config(hapd, sta);
00111 
00112         /* Start IEEE 802.1X authentication process for new stations */
00113         ieee802_1x_new_station(hapd, sta);
00114         if (reassoc) {
00115                 if (sta->auth_alg != WLAN_AUTH_FT &&
00116                     !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
00117                         wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
00118         } else
00119                 wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
00120 }
00121 
00122 
00123 void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
00124                        const u8 *buf, size_t len, int ack)
00125 {
00126         struct sta_info *sta;
00127         struct hostapd_iface *iface = hapd->iface;
00128 
00129         sta = ap_get_sta(hapd, addr);
00130         if (sta == NULL && iface->num_bss > 1) {
00131                 size_t j;
00132                 for (j = 0; j < iface->num_bss; j++) {
00133                         hapd = iface->bss[j];
00134                         sta = ap_get_sta(hapd, addr);
00135                         if (sta)
00136                                 break;
00137                 }
00138         }
00139         if (sta == NULL)
00140                 return;
00141         if (sta->flags & WLAN_STA_PENDING_POLL) {
00142                 wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
00143                            "activity poll", MAC2STR(sta->addr),
00144                            ack ? "ACKed" : "did not ACK");
00145                 if (ack)
00146                         sta->flags &= ~WLAN_STA_PENDING_POLL;
00147         }
00148 
00149         ieee802_1x_tx_status(hapd, sta, buf, len, ack);
00150 }
00151 
00152 
00153 static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
00154 {
00155         u16 fc, type, stype;
00156 
00157         /*
00158          * PS-Poll frames are 16 bytes. All other frames are
00159          * 24 bytes or longer.
00160          */
00161         if (len < 16)
00162                 return NULL;
00163 
00164         fc = le_to_host16(hdr->frame_control);
00165         type = WLAN_FC_GET_TYPE(fc);
00166         stype = WLAN_FC_GET_STYPE(fc);
00167 
00168         switch (type) {
00169         case WLAN_FC_TYPE_DATA:
00170                 if (len < 24)
00171                         return NULL;
00172                 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
00173                 case WLAN_FC_TODS:
00174                         return hdr->addr1;
00175                 case WLAN_FC_FROMDS:
00176                         return hdr->addr2;
00177                 default:
00178                         return NULL;
00179                 }
00180         case WLAN_FC_TYPE_CTRL:
00181                 if (stype != WLAN_FC_STYPE_PSPOLL)
00182                         return NULL;
00183                 return hdr->addr1;
00184         case WLAN_FC_TYPE_MGMT:
00185                 return hdr->addr3;
00186         default:
00187                 return NULL;
00188         }
00189 }
00190 
00191 
00192 #define HAPD_BROADCAST ((struct hostapd_data *) -1)
00193 
00194 static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
00195                                             const u8 *bssid)
00196 {
00197         size_t i;
00198 
00199         if (bssid == NULL)
00200                 return NULL;
00201         if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
00202             bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
00203                 return HAPD_BROADCAST;
00204 
00205         for (i = 0; i < iface->num_bss; i++) {
00206                 if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)
00207                         return iface->bss[i];
00208         }
00209 
00210         return NULL;
00211 }
00212 
00213 
00214 void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
00215                                  const struct ieee80211_hdr *hdr, size_t len)
00216 {
00217         struct sta_info *sta;
00218         const u8 *addr;
00219 
00220         hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
00221         if (hapd == NULL || hapd == HAPD_BROADCAST)
00222                 return;
00223 
00224         addr = hdr->addr2;
00225         sta = ap_get_sta(hapd, addr);
00226         if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
00227                 wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated "
00228                            "STA " MACSTR, MAC2STR(addr));
00229                 if (sta && (sta->flags & WLAN_STA_AUTH))
00230                         hostapd_sta_disassoc(
00231                                 hapd, addr,
00232                                 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
00233                 else
00234                         hostapd_sta_deauth(
00235                                 hapd, addr,
00236                                 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
00237         }
00238 }
00239 
00240 
00241 int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
00242                         const u8 *ie, size_t ielen)
00243 {
00244         struct sta_info *sta;
00245         int new_assoc, res;
00246 
00247         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
00248                        HOSTAPD_LEVEL_INFO, "associated");
00249 
00250         sta = ap_get_sta(hapd, addr);
00251         if (sta) {
00252                 accounting_sta_stop(hapd, sta);
00253         } else {
00254                 sta = ap_sta_add(hapd, addr);
00255                 if (sta == NULL)
00256                         return -1;
00257         }
00258         sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
00259 
00260         if (hapd->conf->wpa) {
00261                 if (ie == NULL || ielen == 0) {
00262                         if (hapd->conf->wps_state) {
00263                                 wpa_printf(MSG_DEBUG, "STA did not include "
00264                                            "WPA/RSN IE in (Re)Association "
00265                                            "Request - possible WPS use");
00266                                 sta->flags |= WLAN_STA_MAYBE_WPS;
00267                                 goto skip_wpa_check;
00268                         }
00269 
00270                         wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
00271                         return -1;
00272                 }
00273                 if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
00274                     os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
00275                         sta->flags |= WLAN_STA_WPS;
00276                         goto skip_wpa_check;
00277                 }
00278 
00279                 if (sta->wpa_sm == NULL)
00280                         sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
00281                                                         sta->addr);
00282                 if (sta->wpa_sm == NULL) {
00283                         wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
00284                                    "machine");
00285                         return -1;
00286                 }
00287                 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
00288                                           ie, ielen, NULL, 0);
00289                 if (res != WPA_IE_OK) {
00290                         int resp;
00291                         wpa_printf(MSG_DEBUG, "WPA/RSN information element "
00292                                    "rejected? (res %u)", res);
00293                         wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
00294                         if (res == WPA_INVALID_GROUP)
00295                                 resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
00296                         else if (res == WPA_INVALID_PAIRWISE)
00297                                 resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
00298                         else if (res == WPA_INVALID_AKMP)
00299                                 resp = WLAN_REASON_AKMP_NOT_VALID;
00300 #ifdef CONFIG_IEEE80211W
00301                         else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
00302                                 resp = WLAN_REASON_INVALID_IE;
00303                         else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
00304                                 resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
00305 #endif /* CONFIG_IEEE80211W */
00306                         else
00307                                 resp = WLAN_REASON_INVALID_IE;
00308                         hostapd_sta_disassoc(hapd, sta->addr, resp);
00309                         ap_free_sta(hapd, sta);
00310                         return -1;
00311                 }
00312         } else if (hapd->conf->wps_state) {
00313                 if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
00314                     os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
00315                         sta->flags |= WLAN_STA_WPS;
00316                 } else
00317                         sta->flags |= WLAN_STA_MAYBE_WPS;
00318         }
00319 skip_wpa_check:
00320 
00321         new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
00322         sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
00323         wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
00324 
00325         hostapd_new_assoc_sta(hapd, sta, !new_assoc);
00326 
00327         ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
00328 
00329         return 0;
00330 }
00331 
00332 
00333 void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
00334 {
00335         struct sta_info *sta;
00336 
00337         hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
00338                        HOSTAPD_LEVEL_INFO, "disassociated");
00339 
00340         sta = ap_get_sta(hapd, addr);
00341         if (sta == NULL) {
00342                 wpa_printf(MSG_DEBUG, "Disassociation notification for "
00343                            "unknown STA " MACSTR, MAC2STR(addr));
00344                 return;
00345         }
00346 
00347         sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
00348         wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
00349         sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
00350         ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
00351         ap_free_sta(hapd, sta);
00352 }
00353 
00354 
00355 void hostapd_eapol_receive(struct hostapd_data *hapd, const u8 *sa,
00356                            const u8 *buf, size_t len)
00357 {
00358         ieee802_1x_receive(hapd, sa, buf, len);
00359 }
00360 
00361 
00362 #ifdef NEED_AP_MLME
00363 void hostapd_mgmt_rx(struct hostapd_data *hapd, u8 *buf, size_t len,
00364                      u16 stype, struct hostapd_frame_info *fi)
00365 {
00366         struct hostapd_iface *iface = hapd->iface;
00367         struct ieee80211_hdr *hdr;
00368         const u8 *bssid;
00369 
00370         hdr = (struct ieee80211_hdr *) buf;
00371         bssid = get_hdr_bssid(hdr, len);
00372         if (bssid == NULL)
00373                 return;
00374 
00375         hapd = get_hapd_bssid(iface, bssid);
00376         if (hapd == NULL) {
00377                 u16 fc;
00378                 fc = le_to_host16(hdr->frame_control);
00379 
00380                 /*
00381                  * Drop frames to unknown BSSIDs except for Beacon frames which
00382                  * could be used to update neighbor information.
00383                  */
00384                 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
00385                     WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
00386                         hapd = iface->bss[0];
00387                 else
00388                         return;
00389         }
00390 
00391         if (hapd == HAPD_BROADCAST) {
00392                 size_t i;
00393                 for (i = 0; i < iface->num_bss; i++)
00394                         ieee802_11_mgmt(iface->bss[i], buf, len, stype, fi);
00395         } else
00396                 ieee802_11_mgmt(hapd, buf, len, stype, fi);
00397 }
00398 
00399 
00400 void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
00401                         u16 stype, int ok)
00402 {
00403         struct ieee80211_hdr *hdr;
00404         hdr = (struct ieee80211_hdr *) buf;
00405         hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
00406         if (hapd == NULL || hapd == HAPD_BROADCAST)
00407                 return;
00408         ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
00409 }
00410 #endif /* NEED_AP_MLME */
00411 
00412 
00413 void hostapd_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr)
00414 {
00415         michael_mic_failure(hapd, addr, 1);
00416 }
00417 
00418 
00419 struct hostapd_data * hostapd_sta_get_bss(struct hostapd_data *hapd,
00420                                           const u8 *addr)
00421 {
00422         struct hostapd_iface *iface = hapd->iface;
00423         size_t j;
00424 
00425         for (j = 0; j < iface->num_bss; j++) {
00426                 hapd = iface->bss[j];
00427                 if (ap_get_sta(hapd, addr))
00428                         return hapd;
00429         }
00430 
00431         return NULL;
00432 }
00433 
00434 
00435 #ifndef CONFIG_AP
00436 void wpa_supplicant_event(void *ctx, wpa_event_type event,
00437                           union wpa_event_data *data)
00438 {
00439         struct hostapd_data *hapd = ctx;
00440 
00441         switch (event) {
00442         case EVENT_MICHAEL_MIC_FAILURE:
00443                 michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
00444                 break;
00445         case EVENT_SCAN_RESULTS:
00446                 if (hapd->iface->scan_cb)
00447                         hapd->iface->scan_cb(hapd->iface);
00448                 break;
00449         default:
00450                 wpa_printf(MSG_DEBUG, "Unknown event %d", event);
00451                 break;
00452         }
00453 }
00454 #endif /* CONFIG_AP */
00455 
00456 
00457 void hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
00458                          const u8 *ie, size_t ie_len)
00459 {
00460         size_t i;
00461 
00462         for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
00463                 hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
00464                                         sa, ie, ie_len);
00465 }
00466 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:47 2009 for hostapd by  doxygen 1.6.1