Use generic driver event notification for AP mode assoc/disassoc
authorJouni Malinen <j@w1.fi>
Sun, 3 Jan 2010 16:22:22 +0000 (18:22 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 3 Jan 2010 16:22:22 +0000 (18:22 +0200)
src/ap/drv_callbacks.c
src/ap/hostapd.h
src/drivers/driver.h
src/drivers/driver_atheros.c
src/drivers/driver_broadcom.c
src/drivers/driver_bsd.c
src/drivers/driver_madwifi.c
src/drivers/driver_ralink.c
src/drivers/driver_test.c
src/drivers/driver_wext.c
wpa_supplicant/events.c

index b03a541..61ca690 100644 (file)
@@ -397,6 +397,19 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                                       data->eapol_rx.data,
                                       data->eapol_rx.data_len);
                break;
+       case EVENT_ASSOC:
+               hostapd_notif_assoc(hapd, data->assoc_info.addr,
+                                   data->assoc_info.req_ies,
+                                   data->assoc_info.req_ies_len);
+               break;
+       case EVENT_DISASSOC:
+               if (data)
+                       hostapd_notif_disassoc(hapd, data->disassoc_info.addr);
+               break;
+       case EVENT_DEAUTH:
+               if (data)
+                       hostapd_notif_disassoc(hapd, data->deauth_info.addr);
+               break;
        default:
                wpa_printf(MSG_DEBUG, "Unknown event %d", event);
                break;
index 86676ff..7c6b0b7 100644 (file)
@@ -260,4 +260,9 @@ int hostapd_register_probereq_cb(struct hostapd_data *hapd,
                                 void *ctx);
 void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
 
+/* drv_callbacks.c (TODO: move to somewhere else?) */
+int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
+                       const u8 *ie, size_t ielen);
+void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
+
 #endif /* HOSTAPD_H */
index 77263b5..e338c0f 100644 (file)
@@ -1651,6 +1651,7 @@ enum wpa_event_type {
         * sending either of these frames to the current AP. If the driver
         * supports separate deauthentication event, EVENT_DISASSOC should only
         * be used for disassociation and EVENT_DEAUTH for deauthentication.
+        * In AP mode, union wpa_event_data::disassoc_info is required.
         */
        EVENT_DISASSOC,
 
@@ -1778,6 +1779,7 @@ enum wpa_event_type {
         * This event should be called when authentication is lost either due
         * to receiving deauthenticate frame from the AP or when sending that
         * frame to the current AP.
+        * In AP mode, union wpa_event_data::deauth_info is required.
         */
        EVENT_DEAUTH,
 
@@ -1920,7 +1922,7 @@ union wpa_event_data {
                 * This should start with the first IE (fixed fields before IEs
                 * are not included).
                 */
-               u8 *req_ies;
+               const u8 *req_ies;
 
                /**
                 * req_ies_len - Length of req_ies in bytes
@@ -1938,7 +1940,7 @@ union wpa_event_data {
                 * This should start with the first IE (fixed fields before IEs
                 * are not included).
                 */
-               u8 *resp_ies;
+               const u8 *resp_ies;
 
                /**
                 * resp_ies_len - Length of resp_ies in bytes
@@ -1961,7 +1963,7 @@ union wpa_event_data {
                 * This should start with the first IE (fixed fields before IEs
                 * are not included).
                 */
-               u8 *beacon_ies;
+               const u8 *beacon_ies;
 
                /**
                 * beacon_ies_len - Length of beacon_ies */
@@ -1971,9 +1973,34 @@ union wpa_event_data {
                 * freq - Frequency of the operational channel in MHz
                 */
                unsigned int freq;
+
+               /**
+                * addr - Station address (for AP mode)
+                */
+               const u8 *addr;
        } assoc_info;
 
        /**
+        * struct disassoc_info - Data for EVENT_DISASSOC events
+        */
+       struct disassoc_info {
+               /**
+                * addr - Station address (for AP mode)
+                */
+               const u8 *addr;
+       } disassoc_info;
+
+       /**
+        * struct deauth_info - Data for EVENT_DEAUTH events
+        */
+       struct deauth_info {
+               /**
+                * addr - Station address (for AP mode)
+                */
+               const u8 *addr;
+       } deauth_info;
+
+       /**
         * struct michael_mic_failure - Data for EVENT_MICHAEL_MIC_FAILURE
         */
        struct michael_mic_failure {
@@ -2253,10 +2280,29 @@ int wpa_scan_get_max_rate(const struct wpa_scan_res *res);
 void wpa_scan_results_free(struct wpa_scan_results *res);
 void wpa_scan_sort_results(struct wpa_scan_results *res);
 
-/* hostapd functions for driver wrappers */
 
-int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
-                       const u8 *ie, size_t ielen);
-void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
+/*
+ * The following inline functions are provided for convenience to simplify
+ * event indication for some of the common events.
+ */
+
+static inline void drv_event_assoc(void *ctx, const u8 *addr, const u8 *ie,
+                                  size_t ielen)
+{
+       union wpa_event_data event;
+       os_memset(&event, 0, sizeof(event));
+       event.assoc_info.req_ies = ie;
+       event.assoc_info.req_ies_len = ielen;
+       event.assoc_info.addr = addr;
+       wpa_supplicant_event(ctx, EVENT_ASSOC, &event);
+}
+
+static inline void drv_event_disassoc(void *ctx, const u8 *addr)
+{
+       union wpa_event_data event;
+       os_memset(&event, 0, sizeof(event));
+       event.disassoc_info.addr = addr;
+       wpa_supplicant_event(ctx, EVENT_DISASSOC, &event);
+}
 
 #endif /* DRIVER_H */
index e3a7e7d..1e72ec5 100644 (file)
@@ -732,12 +732,12 @@ madwifi_set_ap_wps_ie(const char *ifname, void *priv,
 #define madwifi_set_ap_wps_ie NULL
 #endif /* CONFIG_WPS */
 
-static int
+static void
 madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
 {
        struct hostapd_data *hapd = drv->hapd;
        struct ieee80211req_wpaie ie;
-       int ielen = 0, res;
+       int ielen = 0;
        u8 *iebuf = NULL;
 
        /*
@@ -778,15 +778,13 @@ madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
                ielen += 2;
 
 no_ie:
-       res = hostapd_notif_assoc(hapd, addr, iebuf, ielen);
+       drv_event_assoc(hapd, addr, iebuf, ielen);
 
        if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
                /* Cached accounting data is not valid anymore. */
                memset(drv->acct_mac, 0, ETH_ALEN);
                memset(&drv->acct_data, 0, sizeof(drv->acct_data));
        }
-
-       return res;
 }
 
 static void
@@ -904,8 +902,8 @@ madwifi_wireless_event_wireless(struct madwifi_driver_data *drv,
 
                switch (iwe->cmd) {
                case IWEVEXPIRED:
-                       hostapd_notif_disassoc(drv->hapd,
-                                              (u8 *) iwe->u.addr.sa_data);
+                       drv_event_disassoc(drv->hapd,
+                                          (u8 *) iwe->u.addr.sa_data);
                        break;
                case IWEVREGISTERED:
                        madwifi_new_sta(drv, (u8 *) iwe->u.addr.sa_data);
index 9b9644f..cb88543 100644 (file)
@@ -233,7 +233,8 @@ static void wpa_driver_broadcom_event_receive(int sock, void *ctx,
        int left;
        wl_wpa_header_t *wwh;
        union wpa_event_data data;
-       
+       u8 *resp_ies = NULL;
+
        if ((left = recv(sock, buf, sizeof buf, 0)) < 0)
                return;
 
@@ -257,21 +258,16 @@ static void wpa_driver_broadcom_event_receive(int sock, void *ctx,
                wpa_printf(MSG_DEBUG, "BROADCOM: ASSOC MESSAGE (left: %d)",
                           left);
                if (left > 0) {
-                       data.assoc_info.resp_ies = os_malloc(left);
-                       if (data.assoc_info.resp_ies == NULL)
+                       resp_ies = os_malloc(left);
+                       if (resp_ies == NULL)
                                return;
-                       os_memcpy(data.assoc_info.resp_ies,
-                                 buf + WL_WPA_HEADER_LEN, left);
+                       os_memcpy(resp_ies, buf + WL_WPA_HEADER_LEN, left);
+                       data.assoc_info.resp_ies = resp_ies;
                        data.assoc_info.resp_ies_len = left;
-                       wpa_hexdump(MSG_MSGDUMP, "BROADCOM: copying %d bytes "
-                                   "into resp_ies",
-                                   data.assoc_info.resp_ies, left);
                }
-               /* data.assoc_info.req_ies = NULL; */
-               /* data.assoc_info.req_ies_len = 0; */
 
-               wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
-               wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
+               wpa_supplicant_event(ctx, EVENT_ASSOC, &data);
+               os_free(resp_ies);
                break;
        case WLC_DISASSOC_MSG:
                wpa_printf(MSG_DEBUG, "BROADCOM: DISASSOC MESSAGE");
@@ -292,7 +288,6 @@ static void wpa_driver_broadcom_event_receive(int sock, void *ctx,
                           wwh->type);
                break;
        }
-       os_free(data.assoc_info.resp_ies);
 }      
 
 static void * wpa_driver_broadcom_init(void *ctx, const char *ifname)
index 5b232fd..ab01370 100644 (file)
@@ -569,7 +569,7 @@ bsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
        return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
 }
 
-static int
+static void
 bsd_new_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
 {
        struct hostapd_data *hapd = drv->hapd;
@@ -594,7 +594,7 @@ bsd_new_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
                ielen += 2;
 
 no_ie:
-       return hostapd_notif_assoc(hapd, addr, iebuf, ielen);
+       drv_event_assoc(hapd, addr, iebuf, ielen);
 }
 
 static void
@@ -634,7 +634,7 @@ bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
                        break;
                case RTM_IEEE80211_LEAVE:
                        leave = (struct ieee80211_leave_event *) &ifan[1];
-                       hostapd_notif_disassoc(drv->hapd, leave->iev_addr);
+                       drv_event_notif_disassoc(drv->hapd, leave->iev_addr);
                        break;
                case RTM_IEEE80211_JOIN:
 #ifdef RTM_IEEE80211_REJOIN
index 5c25ee3..67efaab 100644 (file)
@@ -835,12 +835,12 @@ madwifi_set_ap_wps_ie(const char *ifname, void *priv,
 #define madwifi_set_ap_wps_ie NULL
 #endif /* CONFIG_WPS */
 
-static int
+static void
 madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
 {
        struct hostapd_data *hapd = drv->hapd;
        struct ieee80211req_wpaie ie;
-       int ielen = 0, res;
+       int ielen = 0;
        u8 *iebuf = NULL;
 
        /*
@@ -879,15 +879,13 @@ madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
                ielen += 2;
 
 no_ie:
-       res = hostapd_notif_assoc(hapd, addr, iebuf, ielen);
+       drv_event_assoc(hapd, addr, iebuf, ielen);
 
        if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
                /* Cached accounting data is not valid anymore. */
                memset(drv->acct_mac, 0, ETH_ALEN);
                memset(&drv->acct_data, 0, sizeof(drv->acct_data));
        }
-
-       return res;
 }
 
 static void
@@ -980,8 +978,8 @@ madwifi_wireless_event_wireless(struct madwifi_driver_data *drv,
 
                switch (iwe->cmd) {
                case IWEVEXPIRED:
-                       hostapd_notif_disassoc(drv->hapd,
-                                              (u8 *) iwe->u.addr.sa_data);
+                       drv_event_disassoc(drv->hapd,
+                                          (u8 *) iwe->u.addr.sa_data);
                        break;
                case IWEVREGISTERED:
                        madwifi_new_sta(drv, (u8 *) iwe->u.addr.sa_data);
index e7fbfb6..6eebdd6 100644 (file)
@@ -452,6 +452,7 @@ wpa_driver_ralink_event_wireless_custom(struct wpa_driver_ralink_data *drv,
                                        void *ctx, char *custom)
 {
        union wpa_event_data data;
+       u8 *req_ies = NULL, *resp_ies = NULL;
 
        wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
 
@@ -480,12 +481,12 @@ wpa_driver_ralink_event_wireless_custom(struct wpa_driver_ralink_data *drv,
                 */
                bytes = drv->assoc_req_ies_len;
 
-               data.assoc_info.req_ies = os_malloc(bytes);
-               if (data.assoc_info.req_ies == NULL)
+               req_ies = os_malloc(bytes);
+               if (req_ies == NULL)
                        return;
-
+               os_memcpy(req_ies, spos, bytes);
+               data.assoc_info.req_ies = req_ies;
                data.assoc_info.req_ies_len = bytes;
-               os_memcpy(data.assoc_info.req_ies, spos, bytes);
 
                /* skip the '\0' byte */
                spos += bytes + 1;
@@ -501,21 +502,20 @@ wpa_driver_ralink_event_wireless_custom(struct wpa_driver_ralink_data *drv,
                        if (!bytes)
                                goto done;
 
-
-                       data.assoc_info.resp_ies = os_malloc(bytes);
-                       if (data.assoc_info.resp_ies == NULL)
+                       resp_ies = os_malloc(bytes);
+                       if (resp_ies == NULL)
                                goto done;
-
+                       os_memcpy(resp_ies, spos, bytes);
+                       data.assoc_info.resp_ies = resp_ies;
                        data.assoc_info.resp_ies_len = bytes;
-                       os_memcpy(data.assoc_info.resp_ies, spos, bytes);
                }
 
                wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
 
-               /* free allocated memory */
        done:
-               os_free(data.assoc_info.resp_ies);
-               os_free(data.assoc_info.req_ies);
+               /* free allocated memory */
+               os_free(resp_ies);
+               os_free(req_ies);
        }
 }
 
index c61535e..818c197 100644 (file)
@@ -622,10 +622,7 @@ static void test_driver_assoc(struct wpa_driver_test_data *drv,
        sendto(drv->test_socket, cmd, strlen(cmd), 0,
               (struct sockaddr *) from, fromlen);
 
-#ifdef HOSTAPD
-       if (hostapd_notif_assoc(bss->bss_ctx, cli->addr, ie, ielen) < 0)
-               wpa_printf(MSG_DEBUG, "test_driver: failed to add new STA");
-#endif /* HOSTAPD */
+       drv_event_assoc(bss->bss_ctx, cli->addr, ie, ielen);
 }
 
 
@@ -638,9 +635,7 @@ static void test_driver_disassoc(struct wpa_driver_test_data *drv,
        if (!cli)
                return;
 
-#ifdef HOSTAPD
-       hostapd_notif_disassoc(drv->ctx, cli->addr);
-#endif /* HOSTAPD */
+       drv_event_disassoc(drv->ctx, cli->addr);
 }
 
 
index 5bc2efe..210e29b 100644 (file)
@@ -246,6 +246,7 @@ wpa_driver_wext_event_wireless_custom(void *ctx, char *custom)
        } else if (os_strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) {
                char *spos;
                int bytes;
+               u8 *req_ies = NULL, *resp_ies = NULL;
 
                spos = custom + 17;
 
@@ -254,12 +255,12 @@ wpa_driver_wext_event_wireless_custom(void *ctx, char *custom)
                        return;
                bytes /= 2;
 
-               data.assoc_info.req_ies = os_malloc(bytes);
-               if (data.assoc_info.req_ies == NULL)
+               req_ies = os_malloc(bytes);
+               if (req_ies == NULL)
                        return;
-
+               hexstr2bin(spos, req_ies, bytes);
+               data.assoc_info.req_ies = req_ies;
                data.assoc_info.req_ies_len = bytes;
-               hexstr2bin(spos, data.assoc_info.req_ies, bytes);
 
                spos += bytes * 2;
 
@@ -274,19 +275,19 @@ wpa_driver_wext_event_wireless_custom(void *ctx, char *custom)
                                goto done;
                        bytes /= 2;
 
-                       data.assoc_info.resp_ies = os_malloc(bytes);
-                       if (data.assoc_info.resp_ies == NULL)
+                       resp_ies = os_malloc(bytes);
+                       if (resp_ies == NULL)
                                goto done;
-
+                       hexstr2bin(spos, resp_ies, bytes);
+                       data.assoc_info.resp_ies = resp_ies;
                        data.assoc_info.resp_ies_len = bytes;
-                       hexstr2bin(spos, data.assoc_info.resp_ies, bytes);
                }
 
                wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
 
        done:
-               os_free(data.assoc_info.resp_ies);
-               os_free(data.assoc_info.req_ies);
+               os_free(resp_ies);
+               os_free(req_ies);
 #ifdef CONFIG_PEERKEY
        } else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) {
                if (hwaddr_aton(custom + 17, data.stkstart.peer)) {
@@ -402,19 +403,19 @@ static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv)
        os_memset(&data, 0, sizeof(data));
        if (drv->assoc_req_ies) {
                data.assoc_info.req_ies = drv->assoc_req_ies;
-               drv->assoc_req_ies = NULL;
                data.assoc_info.req_ies_len = drv->assoc_req_ies_len;
        }
        if (drv->assoc_resp_ies) {
                data.assoc_info.resp_ies = drv->assoc_resp_ies;
-               drv->assoc_resp_ies = NULL;
                data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len;
        }
 
        wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
 
-       os_free(data.assoc_info.req_ies);
-       os_free(data.assoc_info.resp_ies);
+       os_free(drv->assoc_req_ies);
+       drv->assoc_req_ies = NULL;
+       os_free(drv->assoc_resp_ies);
+       drv->assoc_resp_ies = NULL;
 }
 
 
index 050ca1e..9fcfcba 100644 (file)
@@ -27,6 +27,7 @@
 #include "rsn_supp/pmksa_cache.h"
 #include "common/wpa_ctrl.h"
 #include "eap_peer/eap.h"
+#include "ap/hostapd.h"
 #include "notify.h"
 #include "common/ieee802_11_defs.h"
 #include "blacklist.h"
@@ -1009,10 +1010,21 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
                                       union wpa_event_data *data)
 {
        u8 bssid[ETH_ALEN];
-       int ft_completed = wpa_ft_is_completed(wpa_s->wpa);
+       int ft_completed;
        int bssid_changed;
        struct wpa_driver_capa capa;
 
+#ifdef CONFIG_AP
+       if (wpa_s->ap_iface) {
+               hostapd_notif_assoc(wpa_s->ap_iface->bss[0],
+                                   data->assoc_info.addr,
+                                   data->assoc_info.req_ies,
+                                   data->assoc_info.req_ies_len);
+               return;
+       }
+#endif /* CONFIG_AP */
+
+       ft_completed = wpa_ft_is_completed(wpa_s->wpa);
        if (data)
                wpa_supplicant_event_associnfo(wpa_s, data);
 
@@ -1425,10 +1437,24 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                wpa_supplicant_event_assoc(wpa_s, data);
                break;
        case EVENT_DISASSOC:
+#ifdef CONFIG_AP
+               if (wpa_s->ap_iface && data) {
+                       hostapd_notif_disassoc(wpa_s->ap_iface->bss[0],
+                                              data->disassoc_info.addr);
+                       break;
+               }
+#endif /* CONFIG_AP */
                if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
                        sme_event_disassoc(wpa_s, data);
                /* fall through */
        case EVENT_DEAUTH:
+#ifdef CONFIG_AP
+               if (wpa_s->ap_iface && data) {
+                       hostapd_notif_disassoc(wpa_s->ap_iface->bss[0],
+                                              data->deauth_info.addr);
+                       break;
+               }
+#endif /* CONFIG_AP */
                wpa_supplicant_event_disassoc(wpa_s);
                break;
        case EVENT_MICHAEL_MIC_FAILURE: