diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 6c197743a..a0da48fdd 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -1830,9 +1830,9 @@ static int supp_rates_11b_only(struct ieee802_11_elems *elems) } -static void p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, - const u8 *dst, const u8 *bssid, const u8 *ie, - size_t ie_len) +static enum p2p_probe_req_status +p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *dst, + const u8 *bssid, const u8 *ie, size_t ie_len) { struct ieee802_11_elems elems; struct wpabuf *buf; @@ -1842,55 +1842,55 @@ static void p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, if (!p2p->in_listen || !p2p->drv_in_listen) { /* not in Listen state - ignore Probe Request */ - return; + return P2P_PREQ_NOT_LISTEN; } if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) == ParseFailed) { /* Ignore invalid Probe Request frames */ - return; + return P2P_PREQ_MALFORMED; } if (elems.p2p == NULL) { /* not a P2P probe - ignore it */ - return; + return P2P_PREQ_NOT_P2P; } if (dst && !is_broadcast_ether_addr(dst) && os_memcmp(dst, p2p->cfg->dev_addr, ETH_ALEN) != 0) { /* Not sent to the broadcast address or our P2P Device Address */ - return; + return P2P_PREQ_NOT_PROCESSED; } if (bssid && !is_broadcast_ether_addr(bssid)) { /* Not sent to the Wildcard BSSID */ - return; + return P2P_PREQ_NOT_PROCESSED; } if (elems.ssid == NULL || elems.ssid_len != P2P_WILDCARD_SSID_LEN || os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) != 0) { /* not using P2P Wildcard SSID - ignore */ - return; + return P2P_PREQ_NOT_PROCESSED; } if (supp_rates_11b_only(&elems)) { /* Indicates support for 11b rates only */ - return; + return P2P_PREQ_NOT_P2P; } os_memset(&msg, 0, sizeof(msg)); if (p2p_parse_ies(ie, ie_len, &msg) < 0) { /* Could not parse P2P attributes */ - return; + return P2P_PREQ_NOT_P2P; } if (msg.device_id && os_memcmp(msg.device_id, p2p->cfg->dev_addr, ETH_ALEN != 0)) { /* Device ID did not match */ p2p_parse_free(&msg); - return; + return P2P_PREQ_NOT_PROCESSED; } /* Check Requested Device Type match */ @@ -1898,12 +1898,14 @@ static void p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, !p2p_match_dev_type(p2p, msg.wps_attributes)) { /* No match with Requested Device Type */ p2p_parse_free(&msg); - return; + return P2P_PREQ_NOT_PROCESSED; } p2p_parse_free(&msg); - if (!p2p->cfg->send_probe_resp) - return; /* Response generated elsewhere */ + if (!p2p->cfg->send_probe_resp) { + /* Response generated elsewhere */ + return P2P_PREQ_NOT_PROCESSED; + } wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Reply to P2P Probe Request in Listen state"); @@ -1916,12 +1918,12 @@ static void p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, */ ies = p2p_build_probe_resp_ies(p2p); if (ies == NULL) - return; + return P2P_PREQ_NOT_PROCESSED; buf = wpabuf_alloc(200 + wpabuf_len(ies)); if (buf == NULL) { wpabuf_free(ies); - return; + return P2P_PREQ_NOT_PROCESSED; } resp = NULL; @@ -1964,15 +1966,20 @@ static void p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf); wpabuf_free(buf); + + return P2P_PREQ_NOT_PROCESSED; } -int p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst, - const u8 *bssid, const u8 *ie, size_t ie_len) +enum p2p_probe_req_status +p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst, + const u8 *bssid, const u8 *ie, size_t ie_len) { + enum p2p_probe_req_status res; + p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len); - p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len); + res = p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len); if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) && p2p->go_neg_peer && @@ -1983,7 +1990,7 @@ int p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst, "P2P: Found GO Negotiation peer - try to start GO " "negotiation from timeout"); eloop_register_timeout(0, 0, p2p_go_neg_start, p2p, NULL); - return 1; + return P2P_PREQ_PROCESSED; } if ((p2p->state == P2P_INVITE || p2p->state == P2P_INVITE_LISTEN) && @@ -1995,10 +2002,10 @@ int p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst, "P2P: Found Invite peer - try to start Invite from " "timeout"); eloop_register_timeout(0, 0, p2p_invite_start, p2p, NULL); - return 1; + return P2P_PREQ_PROCESSED; } - return 0; + return res; } diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 31d5cd120..a4d425690 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1086,6 +1086,23 @@ void p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *addr); /* Event notifications from lower layer driver operations */ +/** + * enum p2p_probe_req_status + * + * @P2P_PREQ_MALFORMED: frame was not well-formed + * @P2P_PREQ_NOT_LISTEN: device isn't in listen state, frame ignored + * @P2P_PREQ_NOT_P2P: frame was not a P2P probe request + * @P2P_PREQ_P2P_NOT_PROCESSED: frame was P2P but wasn't processed + * @P2P_PREQ_P2P_PROCESSED: frame has been processed by P2P + */ +enum p2p_probe_req_status { + P2P_PREQ_MALFORMED, + P2P_PREQ_NOT_LISTEN, + P2P_PREQ_NOT_P2P, + P2P_PREQ_NOT_PROCESSED, + P2P_PREQ_PROCESSED +}; + /** * p2p_probe_req_rx - Report reception of a Probe Request frame * @p2p: P2P module context from p2p_init() @@ -1094,10 +1111,11 @@ void p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *addr); * @bssid: BSSID if available or %NULL * @ie: Information elements from the Probe Request frame body * @ie_len: Length of ie buffer in octets - * Returns: 0 to indicate the frame was not processed or 1 if it was + * Returns: value indicating the type and status of the probe request */ -int p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst, - const u8 *bssid, const u8 *ie, size_t ie_len); +enum p2p_probe_req_status +p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst, + const u8 *bssid, const u8 *ie, size_t ie_len); /** * p2p_rx_action - Report received Action frame diff --git a/wpa_supplicant/dbus/dbus_common_i.h b/wpa_supplicant/dbus/dbus_common_i.h index 9dab1ee72..bb56bf7f7 100644 --- a/wpa_supplicant/dbus/dbus_common_i.h +++ b/wpa_supplicant/dbus/dbus_common_i.h @@ -25,6 +25,10 @@ struct wpas_dbus_priv { struct wpa_global *global; u32 next_objid; int dbus_new_initialized; + +#if defined(CONFIG_CTRL_IFACE_DBUS_NEW) && defined(CONFIG_AP) + int dbus_noc_refcnt; +#endif /* CONFIG_CTRL_IFACE_DBUS_NEW && CONFIG_AP */ }; #endif /* DBUS_COMMON_I_H */ diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index 5f9489754..bd75a6051 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -31,6 +31,99 @@ #include "dbus_new_handlers_p2p.h" #include "p2p/p2p.h" +#ifdef CONFIG_AP /* until needed by something else */ + +/* + * NameOwnerChanged handling + * + * Some services we provide allow an application to register for + * a signal that it needs. While it can also unregister, we must + * be prepared for the case where the application simply crashes + * and thus doesn't clean up properly. The way to handle this in + * DBus is to register for the NameOwnerChanged signal which will + * signal an owner change to NULL if the peer closes the socket + * for whatever reason. + * + * Handle this signal via a filter function whenever necessary. + * The code below also handles refcounting in case in the future + * there will be multiple instances of this subscription scheme. + */ +static const char wpas_dbus_noc_filter_str[] = + "interface=org.freedesktop.DBus,member=NameOwnerChanged"; + + +static DBusHandlerResult noc_filter(DBusConnection *conn, + DBusMessage *message, void *data) +{ + struct wpas_dbus_priv *priv = data; + + if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, + "NameOwnerChanged")) { + const char *name; + const char *prev_owner; + const char *new_owner; + DBusError derr; + struct wpa_supplicant *wpa_s; + + dbus_error_init(&derr); + + if (!dbus_message_get_args(message, &derr, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &prev_owner, + DBUS_TYPE_STRING, &new_owner, + DBUS_TYPE_INVALID)) { + /* Ignore this error */ + dbus_error_free(&derr); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + for (wpa_s = priv->global->ifaces; wpa_s; wpa_s = wpa_s->next) + { + if (wpa_s->preq_notify_peer != NULL && + os_strcmp(name, wpa_s->preq_notify_peer) == 0 && + (new_owner == NULL || os_strlen(new_owner) == 0)) { + /* probe request owner disconnected */ + os_free(wpa_s->preq_notify_peer); + wpa_s->preq_notify_peer = NULL; + wpas_dbus_unsubscribe_noc(priv); + } + } + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + + +void wpas_dbus_subscribe_noc(struct wpas_dbus_priv *priv) +{ + priv->dbus_noc_refcnt++; + if (priv->dbus_noc_refcnt > 1) + return; + + if (!dbus_connection_add_filter(priv->con, noc_filter, priv, NULL)) { + wpa_printf(MSG_ERROR, "dbus: failed to add filter"); + return; + } + + dbus_bus_add_match(priv->con, wpas_dbus_noc_filter_str, NULL); +} + + +void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv) +{ + priv->dbus_noc_refcnt--; + if (priv->dbus_noc_refcnt > 0) + return; + + dbus_bus_remove_match(priv->con, wpas_dbus_noc_filter_str, NULL); + dbus_connection_remove_filter(priv->con, noc_filter, priv); +} + +#endif /* CONFIG_AP */ + /** * wpas_dbus_signal_interface - Send a interface related event signal @@ -2487,6 +2580,20 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { END_ARGS } }, +#ifdef CONFIG_AP + { "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq, + { + END_ARGS + } + }, + { "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq, + { + END_ARGS + } + }, +#endif /* CONFIG_AP */ { NULL, NULL, NULL, { END_ARGS } } }; @@ -2813,6 +2920,14 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = { } }, #endif /* CONFIG_P2P */ +#ifdef CONFIG_AP + { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE, + { + { "args", "a{sv}", ARG_OUT }, + END_ARGS + } + }, +#endif /* CONFIG_AP */ { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE, { { "certification", "a{sv}", ARG_OUT }, @@ -2886,6 +3001,15 @@ int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s) wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'", wpa_s->dbus_new_path); + +#ifdef CONFIG_AP + if (wpa_s->preq_notify_peer) { + wpas_dbus_unsubscribe_noc(ctrl_iface); + os_free(wpa_s->preq_notify_peer); + wpa_s->preq_notify_peer = NULL; + } +#endif /* CONFIG_AP */ + if (wpa_dbus_unregister_object_per_iface(ctrl_iface, wpa_s->dbus_new_path)) return -1; diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h index 93ce7229c..a2d701139 100644 --- a/wpa_supplicant/dbus/dbus_new.h +++ b/wpa_supplicant/dbus/dbus_new.h @@ -115,6 +115,17 @@ enum wpas_dbus_bss_prop { #define WPAS_DBUS_ERROR_BLOB_UNKNOWN \ WPAS_DBUS_NEW_INTERFACE ".BlobUnknown" +#define WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE \ + WPAS_DBUS_NEW_INTERFACE ".SubscriptionInUse" +#define WPAS_DBUS_ERROR_NO_SUBSCRIPTION \ + WPAS_DBUS_NEW_INTERFACE ".NoSubscription" +#define WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM \ + WPAS_DBUS_NEW_INTERFACE ".SubscriptionNotYou" + + +void wpas_dbus_subscribe_noc(struct wpas_dbus_priv *priv); +void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv); + #ifdef CONFIG_CTRL_IFACE_DBUS_NEW @@ -210,6 +221,9 @@ void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s, int depth, const char *subject, const char *cert_hash, const struct wpabuf *cert); +void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s, + const u8 *addr, const u8 *dst, const u8 *bssid, + const u8 *ie, size_t ie_len, u32 ssi_signal); #else /* CONFIG_CTRL_IFACE_DBUS_NEW */ @@ -467,6 +481,14 @@ static inline void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s, { } +static inline void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s, + const u8 *addr, const u8 *dst, + const u8 *bssid, + const u8 *ie, size_t ie_len, + u32 ssi_signal) +{ +} + #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 b5d02d1f4..3a5bcab53 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -32,6 +32,7 @@ #include "dbus_new.h" #include "dbus_new_handlers.h" #include "dbus_dict_helpers.h" +#include "dbus_common_i.h" extern int wpa_debug_level; extern int wpa_debug_show_keys; @@ -3412,3 +3413,139 @@ dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter, dbus_message_iter_recurse(iter, &variant_iter); return set_network_properties(net->wpa_s, ssid, &variant_iter, error); } + + +#ifdef CONFIG_AP + +DBusMessage * wpas_dbus_handler_subscribe_preq( + DBusMessage *message, struct wpa_supplicant *wpa_s) +{ + struct wpas_dbus_priv *priv = wpa_s->global->dbus; + char *name; + + if (wpa_s->preq_notify_peer != NULL) { + if (os_strcmp(dbus_message_get_sender(message), + wpa_s->preq_notify_peer) == 0) + return NULL; + + return dbus_message_new_error(message, + WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE, + "Another application is already subscribed"); + } + + name = os_strdup(dbus_message_get_sender(message)); + if (!name) + return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, + "out of memory"); + + wpa_s->preq_notify_peer = name; + + /* Subscribe to clean up if application closes socket */ + wpas_dbus_subscribe_noc(priv); + + /* + * Double-check it's still alive to make sure that we didn't + * miss the NameOwnerChanged signal, e.g. while strdup'ing. + */ + if (!dbus_bus_name_has_owner(priv->con, name, NULL)) { + /* + * Application no longer exists, clean up. + * The return value is irrelevant now. + * + * Need to check if the NameOwnerChanged handling + * already cleaned up because we have processed + * DBus messages while checking if the name still + * has an owner. + */ + if (!wpa_s->preq_notify_peer) + return NULL; + os_free(wpa_s->preq_notify_peer); + wpa_s->preq_notify_peer = NULL; + wpas_dbus_unsubscribe_noc(priv); + } + + return NULL; +} + + +DBusMessage * wpas_dbus_handler_unsubscribe_preq( + DBusMessage *message, struct wpa_supplicant *wpa_s) +{ + struct wpas_dbus_priv *priv = wpa_s->global->dbus; + + if (!wpa_s->preq_notify_peer) + return dbus_message_new_error(message, + WPAS_DBUS_ERROR_NO_SUBSCRIPTION, + "Not subscribed"); + + if (os_strcmp(wpa_s->preq_notify_peer, + dbus_message_get_sender(message))) + return dbus_message_new_error(message, + WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM, + "Can't unsubscribe others"); + + os_free(wpa_s->preq_notify_peer); + wpa_s->preq_notify_peer = NULL; + wpas_dbus_unsubscribe_noc(priv); + return NULL; +} + + +void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s, + const u8 *addr, const u8 *dst, const u8 *bssid, + const u8 *ie, size_t ie_len, u32 ssi_signal) +{ + DBusMessage *msg; + DBusMessageIter iter, dict_iter; + struct wpas_dbus_priv *priv = wpa_s->global->dbus; + + /* Do nothing if the control interface is not turned on */ + if (priv == NULL) + return; + + if (wpa_s->preq_notify_peer == NULL) + return; + + msg = dbus_message_new_signal(wpa_s->dbus_new_path, + WPAS_DBUS_NEW_IFACE_INTERFACE, + "ProbeRequest"); + if (msg == NULL) + return; + + dbus_message_set_destination(msg, wpa_s->preq_notify_peer); + + dbus_message_iter_init_append(msg, &iter); + + if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) + goto fail; + if (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr", + (const char *) addr, + ETH_ALEN)) + goto fail; + if (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst", + (const char *) dst, + ETH_ALEN)) + goto fail; + if (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid", + (const char *) bssid, + ETH_ALEN)) + goto fail; + if (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies", + (const char *) ie, + ie_len)) + goto fail; + if (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal", + ssi_signal)) + goto fail; + if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) + goto fail; + + dbus_connection_send(priv->con, msg, NULL); + goto out; +fail: + wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); +out: + dbus_message_unref(msg); +} + +#endif /* CONFIG_AP */ diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h index 6383d9868..d78aa2084 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/wpa_supplicant/dbus/dbus_new_handlers.h @@ -266,4 +266,9 @@ DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message, DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message, const char *arg); +DBusMessage * wpas_dbus_handler_subscribe_preq( + DBusMessage *message, struct wpa_supplicant *wpa_s); +DBusMessage * wpas_dbus_handler_unsubscribe_preq( + DBusMessage *message, struct wpa_supplicant *wpa_s); + #endif /* CTRL_IFACE_DBUS_HANDLERS_NEW_H */ diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 1f4084050..cd45cd19e 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2309,15 +2309,17 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, ap_rx_from_unknown_sta(wpa_s, data->rx_from_unknown.addr, data->rx_from_unknown.wds); break; - case EVENT_RX_MGMT: + case EVENT_RX_MGMT: { + u16 fc, stype; + const struct ieee80211_mgmt *mgmt; + + mgmt = (const struct ieee80211_mgmt *) + data->rx_mgmt.frame; + fc = le_to_host16(mgmt->frame_control); + stype = WLAN_FC_GET_STYPE(fc); + if (wpa_s->ap_iface == NULL) { #ifdef CONFIG_P2P - u16 fc, stype; - const struct ieee80211_mgmt *mgmt; - mgmt = (const struct ieee80211_mgmt *) - data->rx_mgmt.frame; - fc = le_to_host16(mgmt->frame_control); - stype = WLAN_FC_GET_STYPE(fc); if (stype == WLAN_FC_STYPE_PROBE_REQ && data->rx_mgmt.frame_len > 24) { const u8 *src = mgmt->sa; @@ -2336,8 +2338,23 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, "management frame in non-AP mode"); break; } + + if (stype == WLAN_FC_STYPE_PROBE_REQ && + data->rx_mgmt.frame_len > 24) { + const u8 *ie = mgmt->u.probe_req.variable; + size_t ie_len = data->rx_mgmt.frame_len - + (mgmt->u.probe_req.variable - + data->rx_mgmt.frame); + + wpas_notify_preq(wpa_s, mgmt->sa, mgmt->da, + mgmt->bssid, ie, ie_len, + data->rx_mgmt.ssi_signal); + break; + } + ap_mgmt_rx(wpa_s, &data->rx_mgmt); break; + } #endif /* CONFIG_AP */ case EVENT_RX_ACTION: wpa_dbg(wpa_s, MSG_DEBUG, "Received Action frame: SA=" MACSTR diff --git a/wpa_supplicant/examples/dbus-listen-preq.py b/wpa_supplicant/examples/dbus-listen-preq.py new file mode 100755 index 000000000..5ac9859f7 --- /dev/null +++ b/wpa_supplicant/examples/dbus-listen-preq.py @@ -0,0 +1,62 @@ +#!/usr/bin/python + +import dbus +import sys +import time +import gobject +from dbus.mainloop.glib import DBusGMainLoop + +WPAS_DBUS_SERVICE = "fi.w1.wpa_supplicant1" +WPAS_DBUS_INTERFACE = "fi.w1.wpa_supplicant1" +WPAS_DBUS_OPATH = "/fi/w1/wpa_supplicant1" +WPAS_DBUS_INTERFACES_INTERFACE = "fi.w1.wpa_supplicant1.Interface" + +def usage(): + print "Usage: %s " % sys.argv[0] + print "Press Ctrl-C to stop" + +def ProbeRequest(args): + if 'addr' in args: + print '%.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['addr']), + if 'dst' in args: + print '-> %.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['dst']), + if 'bssid' in args: + print '(bssid %.2x:%.2x:%.2x:%.2x:%.2x:%.2x)' % tuple(args['dst']), + if 'signal' in args: + print 'signal:%d' % args['signal'], + if 'ies' in args: + print 'have IEs (%d bytes)' % len(args['ies']), + print '' + +if __name__ == "__main__": + global bus + global wpas_obj + global if_obj + global p2p_iface + + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + bus = dbus.SystemBus() + wpas_obj = bus.get_object(WPAS_DBUS_SERVICE, WPAS_DBUS_OPATH) + + # Print list of i/f if no one is specified + if (len(sys.argv) < 2) : + usage() + sys.exit(0) + + wpas = dbus.Interface(wpas_obj, WPAS_DBUS_INTERFACE) + + ifname = sys.argv[1] + + path = wpas.GetInterface(ifname) + + if_obj = bus.get_object(WPAS_DBUS_SERVICE, path) + iface = dbus.Interface(if_obj, WPAS_DBUS_INTERFACES_INTERFACE) + + bus.add_signal_receiver(ProbeRequest, + dbus_interface=WPAS_DBUS_INTERFACES_INTERFACE, + signal_name="ProbeRequest") + + iface.SubscribeProbeReq() + + gobject.MainLoop().run() diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c index da98a14c4..6e84dc06b 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -602,3 +602,13 @@ void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth, /* notify the new DBus API */ wpas_dbus_signal_certification(wpa_s, depth, subject, cert_hash, cert); } + + +void wpas_notify_preq(struct wpa_supplicant *wpa_s, + const u8 *addr, const u8 *dst, const u8 *bssid, + const u8 *ie, size_t ie_len, u32 ssi_signal) +{ +#ifdef CONFIG_AP + wpas_dbus_signal_preq(wpa_s, addr, dst, bssid, ie, ie_len, ssi_signal); +#endif /* CONFIG_AP */ +} diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h index bd99a7618..0c483bc13 100644 --- a/wpa_supplicant/notify.h +++ b/wpa_supplicant/notify.h @@ -121,5 +121,8 @@ void wpas_notify_p2p_wps_failed(struct wpa_supplicant *wpa_s, void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth, const char *subject, const char *cert_hash, const struct wpabuf *cert); +void wpas_notify_preq(struct wpa_supplicant *wpa_s, + const u8 *addr, const u8 *dst, const u8 *bssid, + const u8 *ie, size_t ie_len, u32 ssi_signal); #endif /* NOTIFY_H */ diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index bf5804ddc..ebd248671 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -3704,8 +3704,20 @@ int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr, if (wpa_s->global->p2p == NULL) return 0; - return p2p_probe_req_rx(wpa_s->global->p2p, addr, dst, bssid, - ie, ie_len); + switch (p2p_probe_req_rx(wpa_s->global->p2p, addr, dst, bssid, + ie, ie_len)) { + case P2P_PREQ_NOT_P2P: + wpas_notify_preq(wpa_s, addr, dst, bssid, ie, ie_len, + ssi_signal); + /* fall through */ + case P2P_PREQ_MALFORMED: + case P2P_PREQ_NOT_LISTEN: + case P2P_PREQ_NOT_PROCESSED: + default: /* make gcc happy */ + return 0; + case P2P_PREQ_PROCESSED: + return 1; + } } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index d31538f40..14ef278fe 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -265,6 +265,9 @@ struct wpa_supplicant { #ifdef CONFIG_CTRL_IFACE_DBUS_NEW char *dbus_new_path; char *dbus_groupobj_path; +#ifdef CONFIG_AP + char *preq_notify_peer; +#endif /* CONFIG_AP */ #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ char bridge_ifname[16];