From b78bc3a37e6af1c7fb725e16def7de758dc0a73d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 15 Nov 2009 12:07:27 +0200 Subject: [PATCH] WPS ER: Add ctrl_iface notifications for AP/Enrollee add/remove --- src/common/wpa_ctrl.h | 6 +++ src/wps/wps.h | 49 ++++++++++++++++++++- src/wps/wps_er.c | 58 ++++++++++++++++++++++++- wpa_supplicant/wps_supplicant.c | 77 +++++++++++++++++++++++++++++++++ 4 files changed, 188 insertions(+), 2 deletions(-) diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 3f511d069..913353259 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -69,6 +69,12 @@ extern "C" { /** WPS enrollment attempt timed out and was terminated */ #define WPS_EVENT_TIMEOUT "WPS-TIMEOUT " +/* WPS ER events */ +#define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD " +#define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE " +#define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD " +#define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE " + /* hostapd control interface - fixed message prefixes */ #define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED " #define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS " diff --git a/src/wps/wps.h b/src/wps/wps.h index 7798ad8da..e9aace54b 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -351,7 +351,27 @@ enum wps_event { /** * WPS_EV_PBC_TIMEOUT - PBC walktime expired before protocol run start */ - WPS_EV_PBC_TIMEOUT + WPS_EV_PBC_TIMEOUT, + + /** + * WPS_EV_ER_AP_ADD - ER: AP added + */ + WPS_EV_ER_AP_ADD, + + /** + * WPS_EV_ER_AP_REMOVE - ER: AP removed + */ + WPS_EV_ER_AP_REMOVE, + + /** + * WPS_EV_ER_ENROLLEE_ADD - ER: Enrollee added + */ + WPS_EV_ER_ENROLLEE_ADD, + + /** + * WPS_EV_ER_ENROLLEE_REMOVE - ER: Enrollee removed + */ + WPS_EV_ER_ENROLLEE_REMOVE }; /** @@ -390,6 +410,33 @@ union wps_event_data { int enrollee; int part; } pwd_auth_fail; + + struct wps_event_er_ap { + const u8 *uuid; + const char *friendly_name; + const char *manufacturer; + const char *manufacturer_url; + const char *model_description; + const char *model_name; + const char *model_number; + const char *model_url; + const char *serial_number; + const char *upc; + } ap; + + struct wps_event_er_enrollee { + const u8 *uuid; + const u8 *mac_addr; + int m1_received; + u16 config_methods; + u16 dev_passwd_id; + const u8 *pri_dev_type; + const char *dev_name; + const char *manufacturer; + const char *model_name; + const char *model_number; + const char *serial_number; + } enrollee; }; /** diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c index 2bd428f5f..adb34f4a5 100644 --- a/src/wps/wps_er.c +++ b/src/wps/wps_er.c @@ -100,6 +100,31 @@ struct wps_er { }; +static void wps_er_sta_event(struct wps_context *wps, struct wps_er_sta *sta, + enum wps_event event) +{ + union wps_event_data data; + struct wps_event_er_enrollee *ev = &data.enrollee; + + if (wps->event_cb == NULL) + return; + + os_memset(&data, 0, sizeof(data)); + ev->uuid = sta->uuid; + ev->mac_addr = sta->addr; + ev->m1_received = sta->m1_received; + ev->config_methods = sta->config_methods; + ev->dev_passwd_id = sta->dev_passwd_id; + ev->pri_dev_type = sta->pri_dev_type; + ev->dev_name = sta->dev_name; + ev->manufacturer = sta->manufacturer; + ev->model_name = sta->model_name; + ev->model_number = sta->model_number; + ev->serial_number = sta->serial_number; + wps->event_cb(wps->cb_ctx, event, &data); +} + + static struct wps_er_sta * wps_er_sta_get(struct wps_er_ap *ap, const u8 *addr) { struct wps_er_sta *sta = ap->sta; @@ -114,6 +139,7 @@ static struct wps_er_sta * wps_er_sta_get(struct wps_er_ap *ap, const u8 *addr) static void wps_er_sta_free(struct wps_er_sta *sta) { + wps_er_sta_event(sta->ap->er->wps, sta, WPS_EV_ER_ENROLLEE_REMOVE); if (sta->wps) wps_deinit(sta->wps); os_free(sta->manufacturer); @@ -165,6 +191,30 @@ static struct wps_er_ap * wps_er_ap_get_id(struct wps_er *er, unsigned int id) } +static void wps_er_ap_event(struct wps_context *wps, struct wps_er_ap *ap, + enum wps_event event) +{ + union wps_event_data data; + struct wps_event_er_ap *evap = &data.ap; + + if (wps->event_cb == NULL) + return; + + os_memset(&data, 0, sizeof(data)); + evap->uuid = ap->uuid; + evap->friendly_name = ap->friendly_name; + evap->manufacturer = ap->manufacturer; + evap->manufacturer_url = ap->manufacturer_url; + evap->model_description = ap->model_description; + evap->model_name = ap->model_name; + evap->model_number = ap->model_number; + evap->model_url = ap->model_url; + evap->serial_number = ap->serial_number; + evap->upc = ap->upc; + wps->event_cb(wps->cb_ctx, event, &data); +} + + static void wps_er_ap_free(struct wps_er *er, struct wps_er_ap *ap) { /* TODO: if ap->subscribed, unsubscribe from events if the AP is still @@ -172,6 +222,7 @@ static void wps_er_ap_free(struct wps_er *er, struct wps_er_ap *ap) wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)", inet_ntoa(ap->addr), ap->location); eloop_cancel_timeout(wps_er_ap_timeout, er, ap); + wps_er_ap_event(er->wps, ap, WPS_EV_ER_AP_REMOVE); os_free(ap->location); http_client_free(ap->http); @@ -213,6 +264,7 @@ static void wps_er_http_subscribe_cb(void *ctx, struct http_client *c, switch (event) { case HTTP_CLIENT_OK: wpa_printf(MSG_DEBUG, "WPS ER: Subscribed to events"); + wps_er_ap_event(ap->er->wps, ap, WPS_EV_ER_AP_ADD); break; case HTTP_CLIENT_FAILED: case HTTP_CLIENT_INVALID_REPLY: @@ -615,6 +667,7 @@ static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap, int probe_req) { struct wps_er_sta *sta = wps_er_sta_get(ap, addr); + int new_sta = 0; if (sta == NULL) { sta = os_zalloc(sizeof(*sta)); @@ -624,6 +677,7 @@ static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap, sta->ap = ap; sta->next = ap->sta; ap->sta = sta; + new_sta = 1; } if (!probe_req) @@ -691,7 +745,9 @@ static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap, eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); eloop_register_timeout(300, 0, wps_er_sta_timeout, sta, NULL); - /* TODO: wpa_msg indication if new STA */ + if (!probe_req || new_sta) + wps_er_sta_event(ap->er->wps, sta, + WPS_EV_ER_ENROLLEE_ADD); return sta; } diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index ea9dbf7f1..62d1cd692 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -410,6 +410,69 @@ static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s) } +static void wpa_supplicant_wps_event_er_ap_add(struct wpa_supplicant *wpa_s, + struct wps_event_er_ap *ap) +{ + char uuid_str[100]; + uuid_bin2str(ap->uuid, uuid_str, sizeof(uuid_str)); + wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_ADD "%s|%s|%s|%s|%s|%s|%s", + uuid_str, + ap->friendly_name ? ap->friendly_name : "", + ap->manufacturer ? ap->manufacturer : "", + ap->model_description ? ap->model_description : "", + ap->model_name ? ap->model_name : "", + ap->manufacturer_url ? ap->manufacturer_url : "", + ap->model_url ? ap->model_url : ""); +} + + +static void wpa_supplicant_wps_event_er_ap_remove(struct wpa_supplicant *wpa_s, + struct wps_event_er_ap *ap) +{ + char uuid_str[100]; + uuid_bin2str(ap->uuid, uuid_str, sizeof(uuid_str)); + wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_REMOVE "%s", uuid_str); +} + + +static void wpa_supplicant_wps_event_er_enrollee_add( + struct wpa_supplicant *wpa_s, struct wps_event_er_enrollee *enrollee) +{ + char uuid_str[100]; + char dev_type[20]; + + uuid_bin2str(enrollee->uuid, uuid_str, sizeof(uuid_str)); + if (enrollee->pri_dev_type) + os_snprintf(dev_type, sizeof(dev_type), "%u-%08X-%u", + WPA_GET_BE16(enrollee->pri_dev_type), + WPA_GET_BE32(enrollee->pri_dev_type + 2), + WPA_GET_BE16(enrollee->pri_dev_type + 6)); + else + dev_type[0] = '\0'; + + wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_ENROLLEE_ADD "%s " MACSTR + " M1=%d config_methods=0x%x dev_passwd_id=%d pri_dev_type=%s " + "|%s|%s|%s|%s|%s|", + uuid_str, MAC2STR(enrollee->mac_addr), enrollee->m1_received, + enrollee->config_methods, enrollee->dev_passwd_id, dev_type, + enrollee->dev_name ? enrollee->dev_name : "", + enrollee->manufacturer ? enrollee->manufacturer : "", + enrollee->model_name ? enrollee->model_name : "", + enrollee->model_number ? enrollee->model_number : "", + enrollee->serial_number ? enrollee->serial_number : ""); +} + + +static void wpa_supplicant_wps_event_er_enrollee_remove( + struct wpa_supplicant *wpa_s, struct wps_event_er_enrollee *enrollee) +{ + char uuid_str[100]; + uuid_bin2str(enrollee->uuid, uuid_str, sizeof(uuid_str)); + wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_ENROLLEE_REMOVE "%s " MACSTR, + uuid_str, MAC2STR(enrollee->mac_addr)); +} + + static void wpa_supplicant_wps_event(void *ctx, enum wps_event event, union wps_event_data *data) { @@ -430,6 +493,20 @@ static void wpa_supplicant_wps_event(void *ctx, enum wps_event event, break; case WPS_EV_PBC_TIMEOUT: break; + case WPS_EV_ER_AP_ADD: + wpa_supplicant_wps_event_er_ap_add(wpa_s, &data->ap); + break; + case WPS_EV_ER_AP_REMOVE: + wpa_supplicant_wps_event_er_ap_remove(wpa_s, &data->ap); + break; + case WPS_EV_ER_ENROLLEE_ADD: + wpa_supplicant_wps_event_er_enrollee_add(wpa_s, + &data->enrollee); + break; + case WPS_EV_ER_ENROLLEE_REMOVE: + wpa_supplicant_wps_event_er_enrollee_remove(wpa_s, + &data->enrollee); + break; } }