From: Damien Dejean <damiendejean@xxxxxxxxxxxx> Adds the "InterworkingSelect" method to the DBus API to trigger an interworking scan with ANQP fetches. When a BSS that matches a set of credentials is found, the result is emitted using the signal "InterworkingAPAdded". Signed-off-by: Damien Dejean <damiendejean@xxxxxxxxxxxx> --- tests/hwsim/test_dbus.py | 66 ++++++++++++++ wpa_supplicant/dbus/dbus_new.c | 113 ++++++++++++++++++++++++ wpa_supplicant/dbus/dbus_new.h | 19 ++++ wpa_supplicant/dbus/dbus_new_handlers.c | 19 ++++ wpa_supplicant/dbus/dbus_new_handlers.h | 3 + wpa_supplicant/interworking.c | 11 +-- wpa_supplicant/notify.c | 26 ++++++ wpa_supplicant/notify.h | 5 ++ 8 files changed, 255 insertions(+), 7 deletions(-) diff --git a/tests/hwsim/test_dbus.py b/tests/hwsim/test_dbus.py index 1822e0a2c..c9e2db028 100644 --- a/tests/hwsim/test_dbus.py +++ b/tests/hwsim/test_dbus.py @@ -6117,3 +6117,69 @@ def test_dbus_creds(dev, apdev): iface.RemoveCred(path) if not "FAIL" in dev[0].get_cred(0, 'domain'): raise Exception("Credential remove failed") + +def test_dbus_interworking(dev, apdev): + "D-Bus interworking selection" + (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0]) + iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE) + + params = {"ssid": "test-interworking", "wpa": "2", + "wpa_key_mgmt": "WPA-EAP", "rsn_pairwise": "CCMP", + "ieee8021x": "1", "eapol_version": "2", + "eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf", + "ca_cert": "auth_serv/ca.pem", + "server_cert": "auth_serv/server.pem", + "private_key": "auth_serv/server.key", + "interworking": "1", + "domain_name": "server.w1.fi", + "nai_realm": "0,server.w1.fi,21[2:4][5:7]", + "roaming_consortium": "2233445566", + "hs20": "1", "anqp_domain_id": "1234"} + + hapd = hostapd.add_ap(apdev[0], params) + + class TestDbusInterworking(TestDbus): + def __init__(self, bus): + TestDbus.__init__(self, bus) + self.interworking_ap_seen = False + self.interworking_select_done = False + + def __enter__(self): + gobject.timeout_add(1, self.run_select) + gobject.timeout_add(15000, self.timeout) + self.add_signal(self.interworkingAPAdded, WPAS_DBUS_IFACE, + "InterworkingAPAdded") + self.add_signal(self.interworkingSelectDone, WPAS_DBUS_IFACE, + "InterworkingSelectDone") + self.loop.run() + return self + + def interworkingAPAdded(self, bss, cred, properties): + logger.debug("interworkingAPAdded: bss=%s cred=%s %s" % (bss, cred, str(properties))) + if self.cred == cred: + self.interworking_ap_seen = True + + def interworkingSelectDone(self): + logger.debug("interworkingSelectDone") + self.interworking_select_done = True + self.loop.quit() + + def run_select(self, *args): + args = {"domain": "server.w1.fi", + "realm": "server.w1.fi", + "eap": "TTLS", + "phase2": "auth=MSCHAPV2", + "username": "user", + "password": "password", + "domain_suffix_match": "server.w1.fi", + "ca_cert": "auth_serv/ca.pem"} + self.cred = iface.AddCred(dbus.Dictionary(args, signature='sv')) + iface.InterworkingSelect() + return False + + def success(self): + return self.interworking_ap_seen and self.interworking_select_done + + with TestDbusInterworking(bus) as t: + if not t.success(): + raise Exception("Expected signals not seen") diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index 413396a9f..22971acff 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -937,6 +937,98 @@ void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, #endif /* CONFIG_MESH */ +#ifdef CONFIG_INTERWORKING + +void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, + struct wpa_cred *cred, + const char *type, + int excluded, + int bh, + int bss_load, + int conn_capab) +{ + struct wpas_dbus_priv *iface; + DBusMessage *msg; + DBusMessageIter iter, dict_iter; + char bss_path[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path; + char cred_path[WPAS_DBUS_OBJECT_PATH_MAX], *cred_obj_path; + + iface = wpa_s->global->dbus; + + /* Do nothing if the control interface is not turned on */ + if (!iface || !wpa_s->dbus_new_path) + return; + + msg = dbus_message_new_signal(wpa_s->dbus_new_path, + WPAS_DBUS_NEW_IFACE_INTERFACE, + "InterworkingAPAdded"); + if (!msg) + return; + + os_snprintf(bss_path, WPAS_DBUS_OBJECT_PATH_MAX, + "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", + wpa_s->dbus_new_path, bss->id); + bss_obj_path = bss_path; + + os_snprintf(cred_path, WPAS_DBUS_OBJECT_PATH_MAX, + "%s/" WPAS_DBUS_NEW_CREDENTIALS_PART "/%u", + wpa_s->dbus_new_path, cred->id); + cred_obj_path = cred_path; + + dbus_message_iter_init_append(msg, &iter); + if (!dbus_message_iter_append_basic(&iter, + DBUS_TYPE_OBJECT_PATH, &bss_obj_path) || + !dbus_message_iter_append_basic(&iter, + DBUS_TYPE_OBJECT_PATH, &cred_obj_path) || + !wpa_dbus_dict_open_write(&iter, &dict_iter) || + !wpa_dbus_dict_append_string(&dict_iter, "type", type) || + !wpa_dbus_dict_append_int32(&dict_iter, "excluded", excluded) || + !wpa_dbus_dict_append_int32(&dict_iter, "priority", cred->priority) || + !wpa_dbus_dict_append_int32(&dict_iter, + "sp_priority", cred->sp_priority) || + !wpa_dbus_dict_append_int32(&dict_iter, "below_min_backhaul", bh) || + !wpa_dbus_dict_append_int32(&dict_iter, + "over_max_bss_load", bss_load) || + !wpa_dbus_dict_append_int32(&dict_iter, + "conn_capab_missing", conn_capab) || + !wpa_dbus_dict_close_write(&iter, &dict_iter)) + wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); + else { + dbus_connection_send(iface->con, msg, NULL); + } + dbus_message_unref(msg); +} + + +void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s) +{ + struct wpas_dbus_priv *iface; + DBusMessage *msg; + + iface = wpa_s->global->dbus; + + /* Do nothing if the control interface is not turned on */ + if (iface == NULL) + return; + + if (!iface || !wpa_s->dbus_new_path) + return; + + msg = dbus_message_new_signal(wpa_s->dbus_new_path, + WPAS_DBUS_NEW_IFACE_INTERFACE, + "InterworkingSelectDone"); + if (msg == NULL) + return; + + dbus_connection_send(iface->con, msg, NULL); + + dbus_message_unref(msg); +} + +#endif /* CONFIG_INTERWORKING */ + + void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s, int depth, const char *subject, const char *altsubject[], @@ -3586,6 +3678,12 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { END_ARGS } }, + { "InterworkingSelect", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_interworking_select, + { + END_ARGS + } + }, #endif /* CONFIG_INTERWORKING */ { NULL, NULL, NULL, { END_ARGS } } }; @@ -4154,6 +4252,21 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = { } }, #endif /* CONFIG_MESH */ +#ifdef CONFIG_INTERWORKING + { "InterworkingAPAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, + { + { "bss", "o", ARG_OUT }, + { "cred", "o", ARG_OUT }, + { "properties", "a{sv}", ARG_OUT }, + END_ARGS + } + }, + { "InterworkingSelectDone", WPAS_DBUS_NEW_IFACE_INTERFACE, + { + END_ARGS + } + }, +#endif /* CONFIG_INTERWORKING */ { NULL, NULL, { END_ARGS } } }; diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h index 8ae0afeaa..46aeb1d77 100644 --- a/wpa_supplicant/dbus/dbus_new.h +++ b/wpa_supplicant/dbus/dbus_new.h @@ -17,6 +17,7 @@ struct wpa_global; struct wpa_supplicant; struct wpa_ssid; struct wpa_cred; +struct wpa_bss; struct wps_event_m2d; struct wps_event_fail; struct wps_credential; @@ -268,6 +269,11 @@ void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s, const u8 *peer_addr); void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int reason); +void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, struct wpa_cred *cred, + const char *type, int excluded, int bh, int bss_load, + int conn_capab); +void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s); #else /* CONFIG_CTRL_IFACE_DBUS_NEW */ @@ -620,6 +626,19 @@ void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, { } +static inline +void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, struct wpa_cred *cred, + const char *type, int excluded, int bh, int bss_load, + int conn_capab) +{ +} + +static inline +void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s) +{ +} + #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ #endif /* CTRL_IFACE_DBUS_H_NEW */ diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 2b2cefb76..14e55211c 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -26,6 +26,7 @@ #include "../scan.h" #include "../autoscan.h" #include "../ap.h" +#include "../interworking.h" #include "dbus_new_helpers.h" #include "dbus_new.h" #include "dbus_new_handlers.h" @@ -1743,6 +1744,24 @@ out: return reply; } +DBusMessage * wpas_dbus_handler_interworking_select(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + int result; + DBusMessage *reply = NULL; + + result = interworking_select(wpa_s, /*auto_select=*/0, /*freqs=*/NULL); + if (result < 0) { + wpa_printf(MSG_ERROR, + "%s[dbus]: failed to start interworking selection", + __func__); + reply = wpas_dbus_error_scan_error( + message, + "error starting interworking selection."); + } + + return reply; +} /** * wpas_dbus_handler_signal_poll - Request immediate signal properties * @message: Pointer to incoming dbus message diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h index 5b01ab527..90e523e00 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/wpa_supplicant/dbus/dbus_new_handlers.h @@ -155,6 +155,9 @@ DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message, DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message, struct wpa_supplicant *wpa_s); +DBusMessage * wpas_dbus_handler_interworking_select(DBusMessage *message, + struct wpa_supplicant *wpa_s); + DECLARE_ACCESSOR(wpas_dbus_getter_capabilities); DECLARE_ACCESSOR(wpas_dbus_getter_state); DECLARE_ACCESSOR(wpas_dbus_getter_scanning); diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 066e344a0..2cb198459 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -2503,13 +2503,8 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s) bh = cred_below_min_backhaul(wpa_s, cred, bss); bss_load = cred_over_max_bss_load(wpa_s, cred, bss); conn_capab = cred_conn_capab_missing(wpa_s, cred, bss); - wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d", - excluded ? INTERWORKING_EXCLUDED : INTERWORKING_AP, - MAC2STR(bss->bssid), type, - bh ? " below_min_backhaul=1" : "", - bss_load ? " over_max_bss_load=1" : "", - conn_capab ? " conn_capab_missing=1" : "", - cred->id, cred->priority, cred->sp_priority); + wpas_notify_interworking_ap_added(wpa_s, bss, cred, excluded, type, bh, + bss_load, conn_capab); if (excluded) continue; if (wpa_s->auto_select || @@ -2600,6 +2595,8 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s) wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); } + wpas_notify_interworking_select_done(wpa_s); + if (selected) { wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR, MAC2STR(selected->bssid)); diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c index fe5e072c2..50ec3df03 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -19,6 +19,7 @@ #include "rsn_supp/wpa.h" #include "fst/fst.h" #include "crypto/tls.h" +#include "bss.h" #include "driver_i.h" #include "scan.h" #include "p2p_supplicant.h" @@ -943,3 +944,28 @@ void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_MESH */ + +#ifdef CONFIG_INTERWORKING + +void wpas_notify_interworking_ap_added(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, struct wpa_cred *cred, int excluded, + const char *type, int bh, int bss_load, int conn_capab) +{ + wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d", + excluded ? INTERWORKING_EXCLUDED : INTERWORKING_AP, + MAC2STR(bss->bssid), type, + bh ? " below_min_backhaul=1" : "", + bss_load ? " over_max_bss_load=1" : "", + conn_capab ? " conn_capab_missing=1" : "", + cred->id, cred->priority, cred->sp_priority); + + wpas_dbus_signal_interworking_ap_added(wpa_s, bss, cred, type, excluded, + bh, bss_load, conn_capab); +} + +void wpas_notify_interworking_select_done(struct wpa_supplicant *wpa_s) +{ + wpas_dbus_signal_interworking_select_done(wpa_s); +} + +#endif /* CONFIG_INTERWORKING */ diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h index e843aa124..c70b31a92 100644 --- a/wpa_supplicant/notify.h +++ b/wpa_supplicant/notify.h @@ -15,6 +15,7 @@ struct wps_credential; struct wps_event_m2d; struct wps_event_fail; struct tls_cert_data; +struct wpa_cred; int wpas_notify_supplicant_initialized(struct wpa_global *global); void wpas_notify_supplicant_deinitialized(struct wpa_global *global); @@ -156,5 +157,9 @@ void wpas_notify_mesh_peer_connected(struct wpa_supplicant *wpa_s, const u8 *peer_addr); void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, const u8 *peer_addr, u16 reason_code); +void wpas_notify_interworking_ap_added(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, struct wpa_cred *cred, int excluded, + const char *type, int bh, int bss_load, int conn_capab); +void wpas_notify_interworking_select_done(struct wpa_supplicant *wpa_s); #endif /* NOTIFY_H */ -- 2.33.0.1079.g6e70778dc9-goog _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap