diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index a8e87d5a7..fcdf995e3 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -1735,10 +1735,12 @@ void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s, enum wpas_dbus_prop property) { char *prop; + dbus_bool_t flush; if (wpa_s->dbus_new_path == NULL) return; /* Skip signal since D-Bus setup is not yet ready */ + flush = FALSE; switch (property) { case WPAS_DBUS_PROP_AP_SCAN: prop = "ApScan"; @@ -1761,6 +1763,10 @@ void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s, case WPAS_DBUS_PROP_CURRENT_AUTH_MODE: prop = "CurrentAuthMode"; break; + case WPAS_DBUS_PROP_DISCONNECT_REASON: + prop = "DisconnectReason"; + flush = TRUE; + break; default: wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", __func__, property); @@ -1770,6 +1776,10 @@ void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s, wpa_dbus_mark_property_changed(wpa_s->global->dbus, wpa_s->dbus_new_path, WPAS_DBUS_NEW_IFACE_INTERFACE, prop); + if (flush) { + wpa_dbus_flush_object_changed_properties( + wpa_s->global->dbus->con, wpa_s->dbus_new_path); + } } @@ -2746,6 +2756,10 @@ static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { NULL }, #endif /* CONFIG_P2P */ + { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", + wpas_dbus_getter_disconnect_reason, + NULL + }, { NULL, NULL, NULL, NULL, NULL } }; diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h index 4d322a1e8..3b632c436 100644 --- a/wpa_supplicant/dbus/dbus_new.h +++ b/wpa_supplicant/dbus/dbus_new.h @@ -34,6 +34,7 @@ enum wpas_dbus_prop { WPAS_DBUS_PROP_CURRENT_NETWORK, WPAS_DBUS_PROP_CURRENT_AUTH_MODE, WPAS_DBUS_PROP_BSSS, + WPAS_DBUS_PROP_DISCONNECT_REASON, }; enum wpas_dbus_bss_prop { diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index bde2aff27..58b941cce 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -2351,6 +2351,27 @@ dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter, } +/** + * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect + * @iter: Pointer to incoming dbus message iter + * @error: Location to store error on failure + * @user_data: Function specific data + * Returns: TRUE on success, FALSE on failure + * + * Getter for "DisconnectReason" property. The reason is negative if it is + * locally generated. + */ +dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter, + DBusError *error, + void *user_data) +{ + struct wpa_supplicant *wpa_s = user_data; + dbus_int32_t reason = wpa_s->disconnect_reason; + return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, + &reason, error); +} + + /** * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age * @iter: Pointer to incoming dbus message iter diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h index 8cba72406..80a061f9c 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/wpa_supplicant/dbus/dbus_new_handlers.h @@ -150,6 +150,10 @@ dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter, DBusError *error, void *user_data); +dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter, + DBusError *error, + void *user_data); + dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter, DBusError *error, void *user_data); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 513a8e870..6685b6b25 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1761,6 +1761,11 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s, if (wpa_s->wpa_state >= WPA_AUTHENTICATING) wpas_connection_failed(wpa_s, bssid); wpa_sm_notify_disassoc(wpa_s->wpa); + if (locally_generated) + wpa_s->disconnect_reason = -reason_code; + else + wpa_s->disconnect_reason = reason_code; + wpas_notify_disconnect_reason(wpa_s); if (!is_zero_ether_addr(bssid) || wpa_s->wpa_state >= WPA_AUTHENTICATING) { wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c index c4d7e939f..0ede0d0fb 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -97,6 +97,12 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s, } +void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s) +{ + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_DISCONNECT_REASON); +} + + void wpas_notify_network_changed(struct wpa_supplicant *wpa_s) { wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_CURRENT_NETWORK); diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h index e2bf78842..58675ac0c 100644 --- a/wpa_supplicant/notify.h +++ b/wpa_supplicant/notify.h @@ -22,6 +22,7 @@ void wpas_notify_iface_removed(struct wpa_supplicant *wpa_s); void wpas_notify_state_changed(struct wpa_supplicant *wpa_s, enum wpa_states new_state, enum wpa_states old_state); +void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s); void wpas_notify_network_changed(struct wpa_supplicant *wpa_s); void wpas_notify_ap_scan_changed(struct wpa_supplicant *wpa_s); void wpas_notify_bssid_changed(struct wpa_supplicant *wpa_s); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 2d6ee3897..b608f2987 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -571,6 +571,9 @@ struct wpa_supplicant { } hw; int pno; + + /* WLAN_REASON_* reason codes. Negative if locally generated. */ + int disconnect_reason; };