aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/p2p/p2p.c53
-rw-r--r--src/p2p/p2p.h24
-rw-r--r--wpa_supplicant/dbus/dbus_common_i.h4
-rw-r--r--wpa_supplicant/dbus/dbus_new.c124
-rw-r--r--wpa_supplicant/dbus/dbus_new.h22
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers.c137
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers.h5
-rw-r--r--wpa_supplicant/events.c31
-rwxr-xr-xwpa_supplicant/examples/dbus-listen-preq.py62
-rw-r--r--wpa_supplicant/notify.c10
-rw-r--r--wpa_supplicant/notify.h3
-rw-r--r--wpa_supplicant/p2p_supplicant.c16
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h3
13 files changed, 459 insertions, 35 deletions
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 6c19774..a0da48f 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 31d5cd1..a4d4256 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1087,6 +1087,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()
* @addr: Source MAC address
@@ -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 9dab1ee..bb56bf7 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 5f94897..bd75a60 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 93ce722..a2d7011 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 b5d02d1..3a5bcab 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 6383d98..d78aa20 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 1f40840..cd45cd1 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 0000000..5ac9859
--- /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 <ifname>" % 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 da98a14..6e84dc0 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 bd99a76..0c483bc 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 bf5804d..ebd2486 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 d31538f..14ef278 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];