All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] Add a new frame watch API
@ 2020-01-06 12:39 Andrew Zaborowski
  2020-01-06 12:39 ` [PATCH 2/2] ap: Switch to " Andrew Zaborowski
  2020-01-13 17:51 ` [PATCH 1/2] Add a " Denis Kenzior
  0 siblings, 2 replies; 3+ messages in thread
From: Andrew Zaborowski @ 2020-01-06 12:39 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 15785 bytes --]

This new API is independent of netdev.c and allows actually
unregistering from receiving notifications of frames, although with some
quirks.  The current API only allowed the callback for a registration to
be forgotten but our process and/or the kernel would still be woken up
when matching frames were received because the kernel had no frame
unregister call.  In the new API you can supply a group-id paramter when
registering frames.  If it is non-zero the frame_watch_group_remove() call
can be used to remove all frame registrations that had a given group-id
by closing the netlink socket on which the notifications would be
received.  This means though that it's a slightly costly operation.

The file is named frame-xchg.c because I'm thinking of also adding
utilities for sending frames and waiting for one of a number of replies
and handling the acked/un-acked information.
---
 Makefile.am      |   1 +
 src/frame-xchg.c | 476 +++++++++++++++++++++++++++++++++++++++++++++++
 src/frame-xchg.h |  35 ++++
 3 files changed, 512 insertions(+)
 create mode 100644 src/frame-xchg.c
 create mode 100644 src/frame-xchg.h

diff --git a/Makefile.am b/Makefile.am
index 8c69d9f4..a9b48cd7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -227,6 +227,7 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h src/missing.h \
 					src/p2putil.h src/p2putil.c \
 					src/module.h src/module.c \
 					src/rrm.c \
+					src/frame-xchg.h src/frame-xchg.c \
 					$(eap_sources) \
 					$(builtin_sources)
 
diff --git a/src/frame-xchg.c b/src/frame-xchg.c
new file mode 100644
index 00000000..0a6c1fc6
--- /dev/null
+++ b/src/frame-xchg.c
@@ -0,0 +1,476 @@
+/*
+ *
+ *  Wireless daemon for Linux
+ *
+ *  Copyright (C) 2020  Intel Corporation. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+
+#include <ell/ell.h>
+
+#include "linux/nl80211.h"
+
+#include "src/iwd.h"
+#include "src/module.h"
+#include "src/mpdu.h"
+#include "src/util.h"
+#include "src/watchlist.h"
+#include "src/nl80211util.h"
+#include "src/netdev.h"
+#include "src/frame-xchg.h"
+
+struct watch_group {
+	/*
+	 * Group IDs, except 0, are per wdev for user's convenience.
+	 * I.e. group 1 can be used for P2P discovery and be removed as
+	 * soon as the scan is over on a given device without interfering
+	 * with scans on other devices.  This means a module can name
+	 * all the groups it's going to need in a static enum.
+	 * Group 0 is the default group and uses the iwd_get_genl() netlink
+	 * socket shared with all its other users, meaning that it can not
+	 * be closed through the watch API.  It is to be used for watches
+	 * that don't need to be unregistered before the virtual interface
+	 * type change or destruction, which are the two events that
+	 * implicitly unregister all existing watches.
+	 */
+	uint32_t id;
+	uint64_t wdev_id;
+	uint32_t unicast_watch_id;
+	struct l_genl *genl;
+	struct l_genl_family *nl80211;
+	struct watchlist watches;
+};
+
+struct frame_watch {
+	uint64_t wdev_id;
+	uint16_t frame_type;
+	uint8_t *prefix;
+	size_t prefix_len;
+	struct watch_group *group;
+	struct watchlist_item super;
+};
+
+static struct l_queue *watch_groups;
+
+struct wdev_info {
+	uint64_t id;
+	uint32_t iftype;
+};
+
+static struct l_queue *wdevs;
+
+struct frame_prefix_info {
+	uint16_t frame_type;
+	const uint8_t *body;
+	size_t body_len;
+	uint64_t wdev_id;
+};
+
+static bool frame_watch_match_prefix(const void *a, const void *b)
+{
+	const struct watchlist_item *item = a;
+	const struct frame_watch *watch =
+		l_container_of(item, struct frame_watch, super);
+	const struct frame_prefix_info *info = b;
+
+	return watch->frame_type == info->frame_type &&
+		watch->prefix_len <= info->body_len &&
+		(watch->prefix_len == 0 ||
+		 !memcmp(watch->prefix, info->body, watch->prefix_len)) &&
+		info->wdev_id == watch->wdev_id;
+}
+
+static void frame_watch_unicast_notify(struct l_genl_msg *msg, void *user_data)
+{
+	struct watch_group *group = user_data;
+	const uint64_t *wdev_id = NULL;
+	const uint32_t *ifindex = NULL;
+	struct l_genl_attr attr;
+	uint16_t type, len, frame_len;
+	const void *data;
+	const struct mmpdu_header *mpdu = NULL;
+	const uint8_t *body;
+	struct frame_prefix_info info;
+	int rssi = 0;	/* No-RSSI flag value */
+
+	if (l_genl_msg_get_command(msg) != NL80211_CMD_FRAME)
+		return;
+
+	if (!l_genl_attr_init(&attr, msg))
+		return;
+
+	while (l_genl_attr_next(&attr, &type, &len, &data)) {
+		switch (type) {
+		case NL80211_ATTR_WDEV:
+			if (len != 8)
+				break;
+
+			wdev_id = data;
+			break;
+
+		case NL80211_ATTR_IFINDEX:
+			if (len != 4)
+				break;
+
+			ifindex = data;
+			break;
+
+		case NL80211_ATTR_FRAME:
+			mpdu = mpdu_validate(data, len);
+			if (!mpdu) {
+				l_warn("Frame didn't validate as MMPDU");
+				return;
+			}
+
+			frame_len = len;
+			break;
+
+		case NL80211_ATTR_RX_SIGNAL_DBM:
+			if (len != 4)
+				break;
+
+			rssi = *(const int32_t *) data;
+		}
+	}
+
+	if (!wdev_id || (group->wdev_id && group->wdev_id != *wdev_id)) {
+		l_warn("Bad wdev attribute");
+		return;
+	}
+
+	if (!mpdu) {
+		l_warn("Missing frame data");
+		return;
+	}
+
+	body = mmpdu_body(mpdu);
+
+	if (ifindex) {
+		struct netdev *netdev = netdev_find(*ifindex);
+
+		if (netdev && memcmp(mpdu->address_1,
+					netdev_get_address(netdev), 6) &&
+				!util_is_broadcast_address(mpdu->address_1))
+			return;
+	}
+
+	/* Only match the frame type and subtype like the kernel does */
+#define FC_FTYPE_STYPE_MASK 0x00fc
+	info.frame_type = l_get_le16(mpdu) & FC_FTYPE_STYPE_MASK;
+	info.body = (const uint8_t *) body;
+	info.body_len = (const uint8_t *) mpdu + frame_len - body;
+	info.wdev_id = *wdev_id;
+
+	WATCHLIST_NOTIFY_MATCHES(&group->watches, frame_watch_match_prefix,
+					&info, frame_watch_cb_t, mpdu,
+					info.body, info.body_len, rssi);
+}
+
+static void frame_watch_group_destroy(void *data)
+{
+	struct watch_group *group = data;
+
+	if (group->unicast_watch_id)
+		l_genl_remove_unicast_watch(group->genl,
+						group->unicast_watch_id);
+
+	if (group->genl)
+		l_genl_unref(group->genl);
+
+	if (group->nl80211)
+		l_genl_family_free(group->nl80211);
+
+	watchlist_destroy(&group->watches);
+	l_free(group);
+}
+
+static void frame_watch_free(struct watchlist_item *item)
+{
+	struct frame_watch *watch =
+		l_container_of(item, struct frame_watch, super);
+
+	l_free(watch->prefix);
+	l_free(watch);
+}
+
+static const struct watchlist_ops frame_watch_ops = {
+	.item_free = frame_watch_free,
+};
+
+static struct watch_group *frame_watch_group_new(uint64_t wdev_id, uint32_t id)
+{
+	struct watch_group *group = l_new(struct watch_group, 1);
+
+	group->id = id;
+	group->wdev_id = wdev_id;
+	watchlist_init(&group->watches, &frame_watch_ops);
+
+	if (id == 0)
+		group->genl = l_genl_ref(iwd_get_genl());
+	else {
+		group->genl = l_genl_new();
+		if (!group->genl)
+			goto err;
+	}
+
+	group->unicast_watch_id = l_genl_add_unicast_watch(group->genl,
+						NL80211_GENL_NAME,
+						frame_watch_unicast_notify,
+						group, NULL);
+	if (!group->unicast_watch_id) {
+		l_error("Registering for unicast notification failed");
+		goto err;
+	}
+
+	group->nl80211 = l_genl_family_new(group->genl, NL80211_GENL_NAME);
+	if (!group->nl80211) {
+		l_error("Failed to obtain nl80211");
+		goto err;
+	}
+
+	return group;
+
+err:
+	frame_watch_group_destroy(group);
+	return NULL;
+}
+
+static struct watch_group *frame_watch_group_get(uint64_t wdev_id, uint32_t id)
+{
+	const struct l_queue_entry *entry;
+
+	for (entry = l_queue_get_entries(watch_groups); entry;
+			entry = entry->next) {
+		struct watch_group *group = entry->data;
+
+		if (group->id == id && (id == 0 || group->wdev_id == wdev_id))
+			return group;
+	}
+
+	return frame_watch_group_new(wdev_id, id);
+}
+
+static void frame_watch_register_cb(struct l_genl_msg *msg, void *user_data)
+{
+	if (l_genl_msg_get_error(msg) < 0)
+		l_error("Could not register frame watch type %04x: %i",
+			L_PTR_TO_UINT(user_data), l_genl_msg_get_error(msg));
+}
+
+bool frame_watch_add(uint64_t wdev_id, uint32_t group_id, uint16_t frame_type,
+			const uint8_t *prefix, size_t prefix_len,
+			frame_watch_cb_t handler, void *user_data,
+			frame_xchg_destroy_func_t destroy)
+{
+	struct watch_group *group = frame_watch_group_get(wdev_id, group_id);
+	struct frame_watch *watch;
+	struct l_genl_msg *msg;
+	struct frame_prefix_info info = { frame_type, prefix, prefix_len, wdev_id };
+	bool registered;
+
+	if (!group)
+		return false;
+
+	registered = l_queue_find(group->watches.items,
+					frame_watch_match_prefix,
+					&info);
+
+	watch = l_new(struct frame_watch, 1);
+	watch->frame_type = frame_type;
+	watch->prefix = prefix_len ? l_memdup(prefix, prefix_len) : NULL;
+	watch->prefix_len = prefix_len;
+	watch->wdev_id = wdev_id;
+	watch->group = group;
+	watchlist_link(&group->watches, &watch->super, handler, user_data,
+			destroy);
+
+	if (registered)
+		return true;
+
+	msg = l_genl_msg_new_sized(NL80211_CMD_REGISTER_FRAME, 32 + prefix_len);
+
+	l_genl_msg_append_attr(msg, NL80211_ATTR_WDEV, 8, &wdev_id);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_FRAME_TYPE, 2, &frame_type);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_FRAME_MATCH,
+				prefix_len, prefix);
+
+	l_genl_family_send(group->nl80211, msg, frame_watch_register_cb,
+				L_UINT_TO_PTR(frame_type), NULL);
+
+	return true;
+}
+
+static bool frame_watch_group_match(const void *a, const void *b)
+{
+	const struct watch_group *group = a;
+	uint32_t id = L_PTR_TO_UINT(b);
+
+	return group->id == id;
+}
+
+bool frame_watch_group_remove(uint64_t wdev_id, uint32_t group_id)
+{
+	struct watch_group *group = l_queue_remove_if(watch_groups,
+						frame_watch_group_match,
+						L_UINT_TO_PTR(group_id));
+
+	if (!group)
+		return false;
+
+	frame_watch_group_destroy(group);
+	return true;
+}
+
+static bool frame_watch_item_remove_wdev(void *data, void *user_data)
+{
+	struct frame_watch *watch =
+		l_container_of(data, struct frame_watch, super);
+	const uint64_t *wdev_id = user_data;
+
+	if (watch->wdev_id != *wdev_id)
+		return false;
+
+	if (watch->super.destroy)
+		watch->super.destroy(watch->super.notify_data);
+
+	frame_watch_free(&watch->super);
+	return true;
+}
+
+static bool frame_watch_group_remove_wdev(void *data, void *user_data)
+{
+	struct watch_group *group = data;
+	const uint64_t *wdev_id = user_data;
+
+	if (group->wdev_id == *wdev_id)
+		return true;
+
+	if (group->id != 0)
+		return false;
+
+	/*
+	 * Have to be careful here because we're messing with watchlist
+	 * internals.
+	 */
+	l_queue_foreach_remove(group->watches.items,
+				frame_watch_item_remove_wdev,
+				&wdev_id);
+	return false;
+}
+
+bool frame_watch_wdev_remove(uint64_t wdev_id)
+{
+	return l_queue_foreach_remove(watch_groups, frame_watch_group_remove_wdev,
+					&wdev_id) > 0;
+}
+
+static bool frame_xchg_wdev_match(const void *a, const void *b)
+{
+	const struct wdev_info *wdev = a;
+	const uint64_t *id = b;
+
+	return wdev->id == *id;
+}
+
+static void frame_xchg_config_notify(struct l_genl_msg *msg, void *user_data)
+{
+	uint64_t wdev_id;
+	uint32_t iftype;
+	struct wdev_info *wdev;
+
+	switch (l_genl_msg_get_command(msg)) {
+	case NL80211_CMD_NEW_INTERFACE:
+	case NL80211_CMD_SET_INTERFACE:
+		if (nl80211_parse_attrs(msg, NL80211_ATTR_WDEV, &wdev_id,
+					NL80211_ATTR_IFTYPE, &iftype,
+					NL80211_ATTR_UNSPEC) < 0)
+			break;
+
+		wdev = l_queue_find(wdevs, frame_xchg_wdev_match, &wdev_id);
+
+		if (!wdev) {
+			wdev = l_new(struct wdev_info, 1);
+			wdev->id = wdev_id;
+			wdev->iftype = iftype;
+
+			if (!wdevs)
+				wdevs = l_queue_new();
+
+			l_queue_push_tail(wdevs, wdev);
+			break;
+		}
+
+		if (wdev->iftype != iftype) {
+			wdev->iftype = iftype;
+			frame_watch_wdev_remove(wdev_id);
+		}
+
+		break;
+
+	case NL80211_CMD_DEL_INTERFACE:
+		if (nl80211_parse_attrs(msg, NL80211_ATTR_WDEV, &wdev_id,
+					NL80211_ATTR_UNSPEC) < 0)
+			break;
+
+		wdev = l_queue_remove_if(wdevs, frame_xchg_wdev_match, &wdev_id);
+		if (!wdev)
+			break;
+
+		l_free(wdev);
+		frame_watch_wdev_remove(wdev_id);
+		break;
+	}
+}
+
+static int frame_xchg_init(void)
+{
+	struct watch_group *default_group = frame_watch_group_new(0, 0);
+
+	if (!default_group)
+		return -EIO;
+
+	if (!l_genl_family_register(default_group->nl80211, "config",
+					frame_xchg_config_notify,
+					NULL, NULL)) {
+		l_error("Registering for config notifications failed");
+		frame_watch_group_destroy(default_group);
+		default_group = NULL;
+		return -EIO;
+	}
+
+	watch_groups = l_queue_new();
+	l_queue_push_tail(watch_groups, default_group);
+
+	return 0;
+}
+
+static void frame_xchg_exit(void)
+{
+	l_queue_destroy(watch_groups, frame_watch_group_destroy);
+	watch_groups = NULL;
+
+	l_queue_destroy(wdevs, l_free);
+	wdevs = NULL;
+}
+
+IWD_MODULE(frame_xchg, frame_xchg_init, frame_xchg_exit);
diff --git a/src/frame-xchg.h b/src/frame-xchg.h
new file mode 100644
index 00000000..1875bd22
--- /dev/null
+++ b/src/frame-xchg.h
@@ -0,0 +1,35 @@
+/*
+ *
+ *  Wireless daemon for Linux
+ *
+ *  Copyright (C) 2020  Intel Corporation. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+struct mmpdu_header;
+
+typedef void (*frame_watch_cb_t)(const struct mmpdu_header *frame,
+					const void *body, size_t body_len,
+					int rssi, void *user_data);
+typedef void (*frame_xchg_destroy_func_t)(void *user_data);
+
+bool frame_watch_add(uint64_t wdev_id, uint32_t group, uint16_t frame_type,
+			const uint8_t *prefix, size_t prefix_len,
+			frame_watch_cb_t handler, void *user_data,
+			frame_xchg_destroy_func_t destroy);
+bool frame_watch_group_remove(uint64_t wdev_id, uint32_t group);
+bool frame_watch_wdev_remove(uint64_t wdev_id);
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] ap: Switch to new frame watch API
  2020-01-06 12:39 [PATCH 1/2] Add a new frame watch API Andrew Zaborowski
@ 2020-01-06 12:39 ` Andrew Zaborowski
  2020-01-13 17:51 ` [PATCH 1/2] Add a " Denis Kenzior
  1 sibling, 0 replies; 3+ messages in thread
From: Andrew Zaborowski @ 2020-01-06 12:39 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 7017 bytes --]

---
 src/ap.c | 92 ++++++++++++++++++++------------------------------------
 1 file changed, 33 insertions(+), 59 deletions(-)

diff --git a/src/ap.c b/src/ap.c
index f8698e9a..569f8572 100644
--- a/src/ap.c
+++ b/src/ap.c
@@ -44,6 +44,7 @@
 #include "src/handshake.h"
 #include "src/dbus.h"
 #include "src/nl80211util.h"
+#include "src/frame-xchg.h"
 
 struct ap_state {
 	struct netdev *netdev;
@@ -55,7 +56,6 @@ struct ap_state {
 	uint32_t beacon_interval;
 	struct l_uintset *rates;
 	uint8_t pmk[32];
-	struct l_queue *frame_watch_ids;
 	uint32_t start_stop_cmd_id;
 	uint8_t gtk[CRYPTO_MAX_GTK_LEN];
 	uint8_t gtk_index;
@@ -109,14 +109,6 @@ static void ap_sta_free(void *data)
 	l_free(sta);
 }
 
-static void ap_frame_watch_remove(void *data, void *user_data)
-{
-	struct netdev *netdev = user_data;
-
-	if (L_PTR_TO_UINT(data))
-		netdev_frame_watch_remove(netdev, L_PTR_TO_UINT(data));
-}
-
 static void ap_reset(struct ap_state *ap)
 {
 	struct netdev *netdev = ap->netdev;
@@ -132,8 +124,7 @@ static void ap_reset(struct ap_state *ap)
 
 	memset(ap->pmk, 0, sizeof(ap->pmk));
 
-	l_queue_foreach(ap->frame_watch_ids, ap_frame_watch_remove, netdev);
-	l_queue_destroy(ap->frame_watch_ids, NULL);
+	frame_watch_wdev_remove(netdev_get_wdev_id(netdev));
 
 	if (ap->start_stop_cmd_id)
 		l_genl_family_cancel(ap->nl80211, ap->start_stop_cmd_id);
@@ -968,10 +959,8 @@ bad_frame:
 }
 
 /* 802.11-2016 9.3.3.6 */
-static void ap_assoc_req_cb(struct netdev *netdev,
-				const struct mmpdu_header *hdr,
-				const void *body, size_t body_len,
-				void *user_data)
+static void ap_assoc_req_cb(const struct mmpdu_header *hdr, const void *body,
+				size_t body_len, int rssi, void *user_data)
 {
 	struct ap_state *ap = user_data;
 	struct sta_state *sta;
@@ -1002,10 +991,8 @@ static void ap_assoc_req_cb(struct netdev *netdev,
 }
 
 /* 802.11-2016 9.3.3.8 */
-static void ap_reassoc_req_cb(struct netdev *netdev,
-				const struct mmpdu_header *hdr,
-				const void *body, size_t body_len,
-				void *user_data)
+static void ap_reassoc_req_cb(const struct mmpdu_header *hdr, const void *body,
+				size_t body_len, int rssi, void *user_data)
 {
 	struct ap_state *ap = user_data;
 	struct sta_state *sta;
@@ -1056,10 +1043,8 @@ static void ap_probe_resp_cb(struct l_genl_msg *msg, void *user_data)
  * Parse Probe Request according to 802.11-2016 9.3.3.10 and act according
  * to 802.11-2016 11.1.4.3
  */
-static void ap_probe_req_cb(struct netdev *netdev,
-				const struct mmpdu_header *hdr,
-				const void *body, size_t body_len,
-				void *user_data)
+static void ap_probe_req_cb(const struct mmpdu_header *hdr, const void *body,
+				size_t body_len, int rssi, void *user_data)
 {
 	struct ap_state *ap = user_data;
 	const struct mmpdu_probe_request *req = body;
@@ -1149,10 +1134,8 @@ static void ap_probe_req_cb(struct netdev *netdev,
 }
 
 /* 802.11-2016 9.3.3.5 (frame format), 802.11-2016 11.3.5.9 (MLME/SME) */
-static void ap_disassoc_cb(struct netdev *netdev,
-				const struct mmpdu_header *hdr,
-				const void *body, size_t body_len,
-				void *user_data)
+static void ap_disassoc_cb(const struct mmpdu_header *hdr, const void *body,
+				size_t body_len, int rssi, void *user_data)
 {
 	struct ap_state *ap = user_data;
 	struct sta_state *sta;
@@ -1221,8 +1204,8 @@ static void ap_auth_reply(struct ap_state *ap, const uint8_t *dest,
  * 802.11-2016 9.3.3.12 (frame format), 802.11-2016 11.3.4.3 and
  * 802.11-2016 12.3.3.2 (MLME/SME)
  */
-static void ap_auth_cb(struct netdev *netdev, const struct mmpdu_header *hdr,
-			const void *body, size_t body_len, void *user_data)
+static void ap_auth_cb(const struct mmpdu_header *hdr, const void *body,
+			size_t body_len, int rssi, void *user_data)
 {
 	struct ap_state *ap = user_data;
 	const struct mmpdu_authentication *auth = body;
@@ -1289,9 +1272,8 @@ done:
 }
 
 /* 802.11-2016 9.3.3.13 (frame format), 802.11-2016 11.3.4.5 (MLME/SME) */
-static void ap_deauth_cb(struct netdev *netdev, const struct mmpdu_header *hdr,
-				const void *body, size_t body_len,
-				void *user_data)
+static void ap_deauth_cb(const struct mmpdu_header *hdr, const void *body,
+				size_t body_len, int rssi, void *user_data)
 {
 	struct ap_state *ap = user_data;
 	struct sta_state *sta;
@@ -1417,8 +1399,7 @@ static int ap_start(struct ap_state *ap, const char *ssid, const char *psk,
 	struct netdev *netdev = ap->netdev;
 	struct wiphy *wiphy = netdev_get_wiphy(netdev);
 	struct l_genl_msg *cmd;
-	const struct l_queue_entry *entry;
-	uint32_t id;
+	uint64_t wdev_id = netdev_get_wdev_id(netdev);
 
 	ap->ssid = l_strdup(ssid);
 	/* TODO: Start a Get Survey to decide the channel */
@@ -1437,42 +1418,35 @@ static int ap_start(struct ap_state *ap, const char *ssid, const char *psk,
 					ap->pmk) < 0)
 		goto error;
 
-	ap->frame_watch_ids = l_queue_new();
-
-	id = netdev_frame_watch_add(netdev, 0x0000 |
+	if (!frame_watch_add(wdev_id, 0, 0x0000 |
 			(MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_REQUEST << 4),
-			NULL, 0, ap_assoc_req_cb, ap);
-	l_queue_push_tail(ap->frame_watch_ids, L_UINT_TO_PTR(id));
+			NULL, 0, ap_assoc_req_cb, ap, NULL))
+		goto error;
 
-	id = netdev_frame_watch_add(netdev, 0x0000 |
+	if (!frame_watch_add(wdev_id, 0, 0x0000 |
 			(MPDU_MANAGEMENT_SUBTYPE_REASSOCIATION_REQUEST << 4),
-			NULL, 0, ap_reassoc_req_cb, ap);
-	l_queue_push_tail(ap->frame_watch_ids, L_UINT_TO_PTR(id));
+			NULL, 0, ap_reassoc_req_cb, ap, NULL))
+		goto error;
 
-	id = netdev_frame_watch_add(netdev, 0x0000 |
+	if (!frame_watch_add(wdev_id, 0, 0x0000 |
 				(MPDU_MANAGEMENT_SUBTYPE_PROBE_REQUEST << 4),
-				NULL, 0, ap_probe_req_cb, ap);
-	l_queue_push_tail(ap->frame_watch_ids, L_UINT_TO_PTR(id));
+				NULL, 0, ap_probe_req_cb, ap, NULL))
+		goto error;
 
-	id = netdev_frame_watch_add(netdev, 0x0000 |
+	if (!frame_watch_add(wdev_id, 0, 0x0000 |
 				(MPDU_MANAGEMENT_SUBTYPE_DISASSOCIATION << 4),
-				NULL, 0, ap_disassoc_cb, ap);
-	l_queue_push_tail(ap->frame_watch_ids, L_UINT_TO_PTR(id));
+				NULL, 0, ap_disassoc_cb, ap, NULL))
+		goto error;
 
-	id = netdev_frame_watch_add(netdev, 0x0000 |
+	if (!frame_watch_add(wdev_id, 0, 0x0000 |
 				(MPDU_MANAGEMENT_SUBTYPE_AUTHENTICATION << 4),
-				NULL, 0, ap_auth_cb, ap);
-	l_queue_push_tail(ap->frame_watch_ids, L_UINT_TO_PTR(id));
+				NULL, 0, ap_auth_cb, ap, NULL))
+		goto error;
 
-	id = netdev_frame_watch_add(netdev, 0x0000 |
+	if (!frame_watch_add(wdev_id, 0, 0x0000 |
 				(MPDU_MANAGEMENT_SUBTYPE_DEAUTHENTICATION << 4),
-				NULL, 0, ap_deauth_cb, ap);
-	l_queue_push_tail(ap->frame_watch_ids, L_UINT_TO_PTR(id));
-
-	for (entry = l_queue_get_entries(ap->frame_watch_ids); entry;
-			entry = entry->next)
-		if (!L_PTR_TO_UINT(entry->data))
-			goto error;
+				NULL, 0, ap_deauth_cb, ap, NULL))
+		goto error;
 
 	cmd = ap_build_cmd_start_ap(ap);
 	if (!cmd)
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 1/2] Add a new frame watch API
  2020-01-06 12:39 [PATCH 1/2] Add a new frame watch API Andrew Zaborowski
  2020-01-06 12:39 ` [PATCH 2/2] ap: Switch to " Andrew Zaborowski
@ 2020-01-13 17:51 ` Denis Kenzior
  1 sibling, 0 replies; 3+ messages in thread
From: Denis Kenzior @ 2020-01-13 17:51 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 1301 bytes --]

Hi Andrew,

On 1/6/20 6:39 AM, Andrew Zaborowski wrote:
> This new API is independent of netdev.c and allows actually
> unregistering from receiving notifications of frames, although with some
> quirks.  The current API only allowed the callback for a registration to
> be forgotten but our process and/or the kernel would still be woken up
> when matching frames were received because the kernel had no frame
> unregister call.  In the new API you can supply a group-id paramter when
> registering frames.  If it is non-zero the frame_watch_group_remove() call
> can be used to remove all frame registrations that had a given group-id
> by closing the netlink socket on which the notifications would be
> received.  This means though that it's a slightly costly operation.
> 
> The file is named frame-xchg.c because I'm thinking of also adding
> utilities for sending frames and waiting for one of a number of replies
> and handling the acked/un-acked information.
> ---
>   Makefile.am      |   1 +
>   src/frame-xchg.c | 476 +++++++++++++++++++++++++++++++++++++++++++++++
>   src/frame-xchg.h |  35 ++++
>   3 files changed, 512 insertions(+)
>   create mode 100644 src/frame-xchg.c
>   create mode 100644 src/frame-xchg.h
> 

Both applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-01-13 17:51 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-06 12:39 [PATCH 1/2] Add a new frame watch API Andrew Zaborowski
2020-01-06 12:39 ` [PATCH 2/2] ap: Switch to " Andrew Zaborowski
2020-01-13 17:51 ` [PATCH 1/2] Add a " Denis Kenzior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.