All of lore.kernel.org
 help / color / mirror / Atom feed
* [wpan-tools v2 0/7] IEEE 802.15.4 scan support
@ 2022-01-12 17:35 Miquel Raynal
  2022-01-12 17:35 ` [wpan-tools v2 1/7] iwpan: Fix the channels printing Miquel Raynal
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Miquel Raynal @ 2022-01-12 17:35 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
	Jakub Kicinski, netdev
  Cc: David Girault, Romuald Despres, Frederic Blain, Nicolas Schodet,
	Thomas Petazzoni, linux-wireless, Miquel Raynal

Hello,

This series follows the work done in the Linux kernel stack: now that
the core knows about the different netlink commands and attributes in
order to support passive scan requests from end-to-end, here are the
userspace changes to be able to use it.

Here is a list of the new available features.

* Sending (or stopping) beacons. Intervals ranging from 0 to 14 are
  valid for passively sending beacons at regular intervals. An interval
  of 15 would request the core to answer to received BEACON_REQ.
  # iwpan dev wpan0 beacons send interval 2 # send BEACON at a fixed rate
  # iwpan dev wpan0 beacons send interval 15 # answer BEACON_REQ only
  # iwpan dev wpan0 beacons stop # apply to both cases

* Scanning all the channels or only a subset:
  # iwpan dev wpan1 scan type passive duration 3 # will not trigger BEACON_REQ
  # iwpan dev wpan1 scan type active duration 3 # will trigger BEACON_REQ

* If a beacon is received during this operation the internal PAN list is
  updated and can be dumped or flushed with:
  # iwpan dev wpan1 pans dump
  PAN 0xffff (on wpan1)
	coordinator 0x2efefdd4cdbf9330
	page 0
	channel 13
	superframe spec. 0xcf22
	LQI 0
	seen 7156ms ago
  # iwpan dev wpan1 pans flush
  # iwpan dev wpan1 set max_pan_entries 100
  # iwpan dev wpan1 set pans_expiration 3600

* It is also possible to monitor the events with:
  # iwpan event

* As well as triggering a non blocking scan:
  # iwpan dev wpan1 scan trigger type passive duration 3
  # iwpan dev wpan1 scan done
  # iwpan dev wpan1 scan abort

Cheers,
Miquèl

Changes in v2:
* Dropped the binaries added by accident.
* New sync of the headers with Linux.
* Added two new commands to configure the stack regarding the number of
  PANs listed and their delay before expiration.

David Girault (4):
  iwpan: Export iwpan_debug
  iwpan: Remove duplicated SECTION
  iwpan: Add full scan support
  iwpan: Add events support

Miquel Raynal (2):
  iwpan: Fix a comment
  iwpan: Synchronize nl802154 header with the Linux kernel

Romuald Despres (1):
  iwpan: Fix the channels printing

 src/Makefile.am |   2 +
 src/event.c     | 221 +++++++++++++++++++++++
 src/info.c      |   4 +-
 src/iwpan.c     |   2 +-
 src/iwpan.h     |  13 +-
 src/mac.c       |  56 ++++++
 src/nl802154.h  |  99 ++++++++++
 src/scan.c      | 471 ++++++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 859 insertions(+), 9 deletions(-)
 create mode 100644 src/event.c
 create mode 100644 src/scan.c

-- 
2.27.0


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

* [wpan-tools v2 1/7] iwpan: Fix the channels printing
  2022-01-12 17:35 [wpan-tools v2 0/7] IEEE 802.15.4 scan support Miquel Raynal
@ 2022-01-12 17:35 ` Miquel Raynal
  2022-01-12 17:35 ` [wpan-tools v2 2/7] iwpan: Export iwpan_debug Miquel Raynal
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Miquel Raynal @ 2022-01-12 17:35 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
	Jakub Kicinski, netdev
  Cc: David Girault, Romuald Despres, Frederic Blain, Nicolas Schodet,
	Thomas Petazzoni, linux-wireless, Romuald Despres, Miquel Raynal

From: Romuald Despres <Romuald.Despres@qorvo.com>

The presence of a channel capability is checked against the tb_msg
netlink attributes array which is the root one, while here we are
looking for channel capabilities, themselves being nested and parsed
into tb_caps. Use tb_caps instead of tb_msg here otherwise we are
accessing a random index in the upper attributes list.

Signed-off-by: Romuald Despres <Romuald.Despres@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 src/info.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/info.c b/src/info.c
index f85690c..8ed5e4f 100644
--- a/src/info.c
+++ b/src/info.c
@@ -342,7 +342,7 @@ static int print_phy_handler(struct nl_msg *msg, void *arg)
 			printf("\b \n");
 		}
 
-		if (tb_msg[NL802154_CAP_ATTR_CHANNELS]) {
+		if (tb_caps[NL802154_CAP_ATTR_CHANNELS]) {
 			int counter = 0;
 			int rem_pages;
 			struct nlattr *nl_pages;
-- 
2.27.0


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

* [wpan-tools v2 2/7] iwpan: Export iwpan_debug
  2022-01-12 17:35 [wpan-tools v2 0/7] IEEE 802.15.4 scan support Miquel Raynal
  2022-01-12 17:35 ` [wpan-tools v2 1/7] iwpan: Fix the channels printing Miquel Raynal
@ 2022-01-12 17:35 ` Miquel Raynal
  2022-01-12 17:35 ` [wpan-tools v2 3/7] iwpan: Fix a comment Miquel Raynal
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Miquel Raynal @ 2022-01-12 17:35 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
	Jakub Kicinski, netdev
  Cc: David Girault, Romuald Despres, Frederic Blain, Nicolas Schodet,
	Thomas Petazzoni, linux-wireless, Miquel Raynal

From: David Girault <david.girault@qorvo.com>

This debug flag will be used later on in different files.

Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 src/iwpan.c | 2 +-
 src/iwpan.h | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/iwpan.c b/src/iwpan.c
index fb7bef1..3cf5fe2 100644
--- a/src/iwpan.c
+++ b/src/iwpan.c
@@ -21,7 +21,7 @@
 
 /* TODO libnl 1.x compatibility code */
 
-static int iwpan_debug = 0;
+int iwpan_debug = 0;
 
 static int nl802154_init(struct nl802154_state *state)
 {
diff --git a/src/iwpan.h b/src/iwpan.h
index 48c4f03..860dd37 100644
--- a/src/iwpan.h
+++ b/src/iwpan.h
@@ -120,4 +120,6 @@ DECLARE_SECTION(get);
 
 const char *iftype_name(enum nl802154_iftype iftype);
 
+extern int iwpan_debug;
+
 #endif /* __IWPAN_H */
-- 
2.27.0


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

* [wpan-tools v2 3/7] iwpan: Fix a comment
  2022-01-12 17:35 [wpan-tools v2 0/7] IEEE 802.15.4 scan support Miquel Raynal
  2022-01-12 17:35 ` [wpan-tools v2 1/7] iwpan: Fix the channels printing Miquel Raynal
  2022-01-12 17:35 ` [wpan-tools v2 2/7] iwpan: Export iwpan_debug Miquel Raynal
@ 2022-01-12 17:35 ` Miquel Raynal
  2022-01-12 17:35 ` [wpan-tools v2 4/7] iwpan: Remove duplicated SECTION Miquel Raynal
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Miquel Raynal @ 2022-01-12 17:35 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
	Jakub Kicinski, netdev
  Cc: David Girault, Romuald Despres, Frederic Blain, Nicolas Schodet,
	Thomas Petazzoni, linux-wireless, Miquel Raynal

There are a couple of words missing, add them to clarify the comment.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 src/iwpan.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/iwpan.h b/src/iwpan.h
index 860dd37..9d265c6 100644
--- a/src/iwpan.h
+++ b/src/iwpan.h
@@ -43,7 +43,7 @@ struct cmd {
 	const enum command_identify_by idby;
 	/* The handler should return a negative error code,
 	 * zero on success, 1 if the arguments were wrong
-	 * and the usage message should and 2 otherwise.
+	 * and the usage message should be displayed, 2 otherwise.
 	 */
 	int (*handler)(struct nl802154_state *state,
 		       struct nl_cb *cb,
-- 
2.27.0


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

* [wpan-tools v2 4/7] iwpan: Remove duplicated SECTION
  2022-01-12 17:35 [wpan-tools v2 0/7] IEEE 802.15.4 scan support Miquel Raynal
                   ` (2 preceding siblings ...)
  2022-01-12 17:35 ` [wpan-tools v2 3/7] iwpan: Fix a comment Miquel Raynal
@ 2022-01-12 17:35 ` Miquel Raynal
  2022-01-12 17:35 ` [wpan-tools v2 5/7] iwpan: Synchronize nl802154 header with the Linux kernel Miquel Raynal
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Miquel Raynal @ 2022-01-12 17:35 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
	Jakub Kicinski, netdev
  Cc: David Girault, Romuald Despres, Frederic Blain, Nicolas Schodet,
	Thomas Petazzoni, linux-wireless, Miquel Raynal

From: David Girault <david.girault@qorvo.com>

This section has been duplicated, drop one.

Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 src/iwpan.h | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/src/iwpan.h b/src/iwpan.h
index 9d265c6..406940a 100644
--- a/src/iwpan.h
+++ b/src/iwpan.h
@@ -90,12 +90,6 @@ struct cmd {
 		.handler = (_handler),					\
 		.help = (_help),					\
 	 }
-#define SECTION(_name)							\
-	struct cmd __section ## _ ## _name				\
-	__attribute__((used)) __attribute__((section("__cmd"))) = {	\
-		.name = (#_name),					\
-		.hidden = 1,						\
-	}
 
 #define SECTION(_name)							\
 	struct cmd __section ## _ ## _name				\
-- 
2.27.0


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

* [wpan-tools v2 5/7] iwpan: Synchronize nl802154 header with the Linux kernel
  2022-01-12 17:35 [wpan-tools v2 0/7] IEEE 802.15.4 scan support Miquel Raynal
                   ` (3 preceding siblings ...)
  2022-01-12 17:35 ` [wpan-tools v2 4/7] iwpan: Remove duplicated SECTION Miquel Raynal
@ 2022-01-12 17:35 ` Miquel Raynal
  2022-01-12 17:35 ` [wpan-tools v2 6/7] iwpan: Add full scan support Miquel Raynal
  2022-01-12 17:35 ` [wpan-tools v2 7/7] iwpan: Add events support Miquel Raynal
  6 siblings, 0 replies; 8+ messages in thread
From: Miquel Raynal @ 2022-01-12 17:35 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
	Jakub Kicinski, netdev
  Cc: David Girault, Romuald Despres, Frederic Blain, Nicolas Schodet,
	Thomas Petazzoni, linux-wireless, Miquel Raynal

The content of this file as evolved, reflect the changes accepted in the
mainline Linux kernel here.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 src/nl802154.h | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 99 insertions(+)

diff --git a/src/nl802154.h b/src/nl802154.h
index ddcee12..9bb136a 100644
--- a/src/nl802154.h
+++ b/src/nl802154.h
@@ -56,6 +56,16 @@ enum nl802154_commands {
 
 	NL802154_CMD_SET_WPAN_PHY_NETNS,
 
+	NL802154_CMD_TRIGGER_SCAN,
+	NL802154_CMD_ABORT_SCAN,
+	NL802154_CMD_SCAN_DONE,
+	NL802154_CMD_DUMP_PANS,
+	NL802154_CMD_FLUSH_PANS,
+	NL802154_CMD_SET_MAX_PAN_ENTRIES,
+	NL802154_CMD_SET_PANS_EXPIRATION,
+	NL802154_CMD_SEND_BEACONS,
+	NL802154_CMD_STOP_BEACONS,
+
 	/* add new commands above here */
 
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
@@ -131,6 +141,15 @@ enum nl802154_attrs {
 	NL802154_ATTR_PID,
 	NL802154_ATTR_NETNS_FD,
 
+	NL802154_ATTR_SCAN_TYPE,
+	NL802154_ATTR_SCAN_FLAGS,
+	NL802154_ATTR_SCAN_CHANNELS,
+	NL802154_ATTR_SCAN_DURATION,
+	NL802154_ATTR_PAN,
+	NL802154_ATTR_MAX_PAN_ENTRIES,
+	NL802154_ATTR_PANS_EXPIRATION,
+	NL802154_ATTR_BEACON_INTERVAL,
+
 	/* add attributes here, update the policy in nl802154.c */
 
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
@@ -217,6 +236,86 @@ enum nl802154_wpan_phy_capability_attr {
 	NL802154_CAP_ATTR_MAX = __NL802154_CAP_ATTR_AFTER_LAST - 1
 };
 
+/**
+ * enum nl802154_scan_types - Scan types
+ *
+ * @__NL802154_SCAN_INVALID: scan type number 0 is reserved
+ * @NL802154_SCAN_ED: An ED scan allows a device to obtain a measure of the peak
+ *	energy in each requested channel
+ * @NL802154_SCAN_ACTIVE: Locate any coordinator transmitting Beacon frames using
+ *	a Beacon Request command
+ * @NL802154_SCAN_PASSIVE: Locate any coordinator transmitting Beacon frames
+ * @NL802154_SCAN_ORPHAN: Relocate coordinator following a loss of synchronisation
+ * @NL802154_SCAN_ENHANCED_ACTIVE: Same as Active using Enhanced Beacon Request
+ *	command instead of Beacon Request command
+ * @NL802154_SCAN_RIT_PASSIVE: Passive scan for RIT Data Request command frames
+ *	instead of Beacon frames
+ * @NL802154_SCAN_ATTR_MAX: Maximum SCAN attribute number
+ */
+enum nl802154_scan_types {
+	__NL802154_SCAN_INVALID,
+	NL802154_SCAN_ED,
+	NL802154_SCAN_ACTIVE,
+	NL802154_SCAN_PASSIVE,
+	NL802154_SCAN_ORPHAN,
+	NL802154_SCAN_ENHANCED_ACTIVE,
+	NL802154_SCAN_RIT_PASSIVE,
+
+	/* keep last */
+	NL802154_SCAN_ATTR_MAX,
+};
+
+/**
+ * enum nl802154_scan_flags - Scan request control flags
+ *
+ * @NL802154_SCAN_FLAG_RANDOM_ADDR: use a random MAC address for this scan (ie.
+ *	a different one for every scan iteration). When the flag is set, full
+ *	randomisation is assumed.
+ */
+enum nl802154_scan_flags {
+	NL802154_SCAN_FLAG_RANDOM_ADDR = 1 << 0,
+};
+
+/**
+ * enum nl802154_pan - Netlink attributes for a PAN
+ *
+ * @__NL802154_PAN_INVALID: invalid
+ * @NL802154_PAN_PANID: PANID of the PAN (2 bytes)
+ * @NL802154_PAN_COORD_ADDR: Coordinator address, (8 bytes or 2 bytes)
+ * @NL802154_PAN_CHANNEL: channel number, related to @NL802154_PAN_PAGE (u8)
+ * @NL802154_PAN_PAGE: channel page, related to @NL802154_PAN_CHANNEL (u8)
+ * @NL802154_PAN_PREAMBLE_CODE: Preamble code while the beacon was received,
+ *	this is PHY dependent and optional (4 bytes)
+ * @NL802154_PAN_SUPERFRAME_SPEC: superframe specification of the PAN (u16)
+ * @NL802154_PAN_LINK_QUALITY: signal quality of beacon in unspecified units,
+ *	scaled to 0..255 (u8)
+ * @NL802154_PAN_GTS_PERMIT: set to true if GTS is permitted on this PAN
+ * @NL802154_PAN_PAYLOAD_DATA: binary data containing the raw data from the
+ *	frame payload, (only if beacon or probe response had data)
+ * @NL802154_PAN_STATUS: status, if this PAN is "used"
+ * @NL802154_PAN_SEEN_MS_AGO: age of this PAN entry in ms
+ * @NL802154_PAN_PAD: attribute used for padding for 64-bit alignment
+ * @NL802154_PAN_MAX: highest PAN attribute
+ */
+enum nl802154_pan {
+	__NL802154_PAN_INVALID,
+	NL802154_PAN_PANID,
+	NL802154_PAN_COORD_ADDR,
+	NL802154_PAN_CHANNEL,
+	NL802154_PAN_PAGE,
+	NL802154_PAN_PREAMBLE_CODE,
+	NL802154_PAN_SUPERFRAME_SPEC,
+	NL802154_PAN_LINK_QUALITY,
+	NL802154_PAN_GTS_PERMIT,
+	NL802154_PAN_PAYLOAD_DATA,
+	NL802154_PAN_STATUS,
+	NL802154_PAN_SEEN_MS_AGO,
+	NL802154_PAN_PAD,
+
+	/* keep last */
+	NL802154_PAN_MAX,
+};
+
 /**
  * enum nl802154_cca_modes - cca modes
  *
-- 
2.27.0


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

* [wpan-tools v2 6/7] iwpan: Add full scan support
  2022-01-12 17:35 [wpan-tools v2 0/7] IEEE 802.15.4 scan support Miquel Raynal
                   ` (4 preceding siblings ...)
  2022-01-12 17:35 ` [wpan-tools v2 5/7] iwpan: Synchronize nl802154 header with the Linux kernel Miquel Raynal
@ 2022-01-12 17:35 ` Miquel Raynal
  2022-01-12 17:35 ` [wpan-tools v2 7/7] iwpan: Add events support Miquel Raynal
  6 siblings, 0 replies; 8+ messages in thread
From: Miquel Raynal @ 2022-01-12 17:35 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
	Jakub Kicinski, netdev
  Cc: David Girault, Romuald Despres, Frederic Blain, Nicolas Schodet,
	Thomas Petazzoni, linux-wireless, Miquel Raynal

From: David Girault <david.girault@qorvo.com>

Bring support for different scanning operations, such as starting or
aborting a scan operation with a given configuration, dumping the list
of discovered PANs, and flushing the list.

It also brings support for a couple of semi-debug features, such as a
manual beacon request to ask sending or stopping beacons out of a
particular interface. This is particularly useful when trying to
validate the scanning support without proper hardware.

Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 src/Makefile.am |   1 +
 src/info.c      |   2 +
 src/mac.c       |  56 ++++++
 src/scan.c      | 471 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 530 insertions(+)
 create mode 100644 src/scan.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 2d54576..18b3569 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,6 +9,7 @@ iwpan_SOURCES = \
 	interface.c \
 	phy.c \
 	mac.c \
+	scan.c \
 	nl_extras.h \
 	nl802154.h
 
diff --git a/src/info.c b/src/info.c
index 8ed5e4f..a0a1556 100644
--- a/src/info.c
+++ b/src/info.c
@@ -213,6 +213,8 @@ static const char *commands[NL802154_CMD_MAX + 1] = {
 	[NL802154_CMD_SET_MAX_CSMA_BACKOFFS] = "set_max_csma_backoffs",
 	[NL802154_CMD_SET_LBT_MODE] = "set_lbt_mode",
 	[NL802154_CMD_SET_ACKREQ_DEFAULT] = "set_ackreq_default",
+	[NL802154_CMD_SET_MAX_PAN_ENTRIES] = "set_max_pan_entries",
+	[NL802154_CMD_SET_PANS_EXPIRATION] = "set_pans_expiration",
 };
 
 static char cmdbuf[100];
diff --git a/src/mac.c b/src/mac.c
index 286802c..6ebfa3b 100644
--- a/src/mac.c
+++ b/src/mac.c
@@ -234,3 +234,59 @@ nla_put_failure:
 COMMAND(set, ackreq_default, "<1|0>",
 	NL802154_CMD_SET_ACKREQ_DEFAULT, 0, CIB_NETDEV, handle_ackreq_default,
 	NULL);
+
+static int handle_set_max_pan_entries(struct nl802154_state *state,
+				      struct nl_cb *cb,
+				      struct nl_msg *msg,
+				      int argc, char **argv,
+				      enum id_input id)
+{
+	unsigned long max_pan_entries;
+	char *end;
+
+	if (argc < 1)
+		return 1;
+
+	/* Maximum number of PAN entries */
+	max_pan_entries = strtoul(argv[0], &end, 0);
+	if (*end != '\0')
+		return 1;
+
+	NLA_PUT_U32(msg, NL802154_ATTR_MAX_PAN_ENTRIES, max_pan_entries);
+
+	return 0;
+
+nla_put_failure:
+	return -ENOBUFS;
+}
+COMMAND(set, max_pan_entries, "<max_pan_entries>",
+	NL802154_CMD_SET_MAX_PAN_ENTRIES, 0, CIB_NETDEV,
+	handle_set_max_pan_entries, NULL);
+
+static int handle_set_pans_expiration(struct nl802154_state *state,
+				      struct nl_cb *cb,
+				      struct nl_msg *msg,
+				      int argc, char **argv,
+				      enum id_input id)
+{
+	unsigned long expiration;
+	char *end;
+
+	if (argc < 1)
+		return 1;
+
+	/* Maximum number of PAN entries */
+	expiration = strtoul(argv[0], &end, 0);
+	if (*end != '\0')
+		return 1;
+
+	NLA_PUT_U32(msg, NL802154_ATTR_PANS_EXPIRATION, expiration);
+
+	return 0;
+
+nla_put_failure:
+	return -ENOBUFS;
+}
+COMMAND(set, pans_expiration, "<delay_in_seconds>",
+	NL802154_CMD_SET_PANS_EXPIRATION, 0, CIB_NETDEV,
+	handle_set_pans_expiration, NULL);
diff --git a/src/scan.c b/src/scan.c
new file mode 100644
index 0000000..ec91c7c
--- /dev/null
+++ b/src/scan.c
@@ -0,0 +1,471 @@
+#include <net/if.h>
+#include <errno.h>
+#include <string.h>
+#include <stdbool.h>
+#include <inttypes.h>
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+#include "nl802154.h"
+#include "nl_extras.h"
+#include "iwpan.h"
+
+static char scantypebuf[100];
+
+static const char *scantype_name(enum nl802154_scan_types scantype)
+{
+	switch (scantype) {
+	case NL802154_SCAN_ED:
+		return "ed";
+	case NL802154_SCAN_ACTIVE:
+		return "active";
+	case NL802154_SCAN_PASSIVE:
+		return "passive";
+	case NL802154_SCAN_ENHANCED_ACTIVE:
+		return "enhanced";
+	case NL802154_SCAN_RIT_PASSIVE:
+		return "rit";
+	default:
+		sprintf(scantypebuf, "Invalid scantype (%d)", scantype);
+		return scantypebuf;
+	}
+}
+
+/* for help */
+#define SCAN_TYPES "Valid scanning types are: ed, active, passive, enhanced, rit."
+
+/* return 0 if ok, internal error otherwise */
+static int get_scan_type(int *argc, char ***argv, enum nl802154_scan_types *type)
+{
+	char *tpstr;
+
+	if (*argc < 2)
+		return 1;
+
+	if (strcmp((*argv)[0], "type"))
+		return 1;
+
+	tpstr = (*argv)[1];
+	*argc -= 2;
+	*argv += 2;
+
+	if (strcmp(tpstr, "ed") == 0) {
+		*type = NL802154_SCAN_ED;
+		return 0;
+	} else if (strcmp(tpstr, "active") == 0) {
+		*type = NL802154_SCAN_ACTIVE;
+		return 0;
+	} else if (strcmp(tpstr, "passive") == 0) {
+		*type = NL802154_SCAN_PASSIVE;
+		return 0;
+	} else if (strcmp(tpstr, "enhanced") == 0) {
+		*type = NL802154_SCAN_ENHANCED_ACTIVE;
+		return 0;
+	} else if (strcmp(tpstr, "rit") == 0) {
+		*type = NL802154_SCAN_RIT_PASSIVE;
+		return 0;
+	}
+
+	fprintf(stderr, "invalid interface type %s\n", tpstr);
+	return 2;
+}
+
+static int get_option_value(int *argc, char ***argv, const char *marker, unsigned long *result, bool *valid)
+{
+	unsigned long value;
+	char *tpstr, *end;
+
+	*valid = false;
+
+	if (*argc < 2)
+		return 0;
+
+	if (strcmp((*argv)[0], marker))
+		return 0;
+
+	tpstr = (*argv)[1];
+	*argc -= 2;
+	*argv += 2;
+
+	value = strtoul(tpstr, &end, 10);
+	if (*end != '\0')
+		return 1;
+
+	*result = value;
+	*valid = true;
+
+	return 0;
+}
+
+static int scan_trigger_handler(struct nl802154_state *state,
+				struct nl_cb *cb,
+				struct nl_msg *msg,
+				int argc, char **argv,
+				enum id_input id)
+{
+	enum nl802154_scan_types type;
+	unsigned long page, channels, duration;
+	int tpset;
+	bool valid_page, valid_channels, valid_duration;
+
+	if (argc < 2)
+		return 1;
+
+	tpset = get_scan_type(&argc, &argv, &type);
+	if (tpset)
+		return tpset;
+
+	tpset = get_option_value(&argc, &argv, "page", &page, &valid_page);
+	if (tpset)
+		return tpset;
+	if (valid_page && page > UINT8_MAX)
+		return 1;
+
+	tpset = get_option_value(&argc, &argv, "channels", &channels, &valid_channels);
+	if (tpset)
+		return tpset;
+	if (valid_channels && channels > UINT32_MAX)
+		return 1;
+
+	tpset = get_option_value(&argc, &argv, "duration", &duration, &valid_duration);
+	if (tpset)
+		return tpset;
+	if (valid_duration && duration > UINT8_MAX)
+		return 1;
+
+	if (argc)
+		return 1;
+
+	/* Mandatory argument */
+	NLA_PUT_U8(msg, NL802154_ATTR_SCAN_TYPE, type);
+	/* Optional arguments */
+	if (valid_duration)
+		NLA_PUT_U8(msg, NL802154_ATTR_SCAN_DURATION, duration);
+	if (valid_page)
+		NLA_PUT_U8(msg, NL802154_ATTR_PAGE, page);
+	if (valid_channels)
+		NLA_PUT_U32(msg, NL802154_ATTR_SCAN_CHANNELS, channels);
+
+	/* TODO: support IES parameters for active scans */
+
+	return 0;
+
+nla_put_failure:
+	return -ENOBUFS;
+}
+
+static int scan_abort_handler(struct nl802154_state *state,
+			      struct nl_cb *cb,
+			      struct nl_msg *msg,
+			      int argc, char **argv,
+			      enum id_input id)
+{
+	return 0;
+}
+
+
+static int parse_scan_result_pan(struct nlattr *nestedpan, struct nlattr *ifattr)
+{
+	struct nlattr *pan[NL802154_PAN_MAX + 1];
+	static struct nla_policy pan_policy[NL802154_PAN_MAX + 1] = {
+		[NL802154_PAN_PANID] = { .type = NLA_U16, },
+		[NL802154_PAN_COORD_ADDR] = { .minlen = 2, .maxlen = 8, }, /* 2 or 8 */
+		[NL802154_PAN_CHANNEL] = { .type = NLA_U8, },
+		[NL802154_PAN_PAGE] = { .type = NLA_U8, },
+		[NL802154_PAN_SUPERFRAME_SPEC] = { .type = NLA_U16, },
+		[NL802154_PAN_LINK_QUALITY] = { .type = NLA_U8, },
+		[NL802154_PAN_GTS_PERMIT] = { .type = NLA_FLAG, },
+		[NL802154_PAN_STATUS] = { .type = NLA_U32, },
+		[NL802154_PAN_SEEN_MS_AGO] = { .type = NLA_U32, },
+	};
+	char dev[20];
+	int ret;
+
+	ret = nla_parse_nested(pan, NL802154_PAN_MAX, nestedpan, pan_policy);
+	if (ret < 0) {
+		fprintf(stderr, "failed to parse nested attributes! (ret = %d)\n",
+			ret);
+		return NL_SKIP;
+	}
+	if (!pan[NL802154_PAN_PANID])
+		return NL_SKIP;
+
+	printf("PAN 0x%04x", le16toh(nla_get_u16(pan[NL802154_PAN_PANID])));
+	if (ifattr) {
+		if_indextoname(nla_get_u32(ifattr), dev);
+		printf(" (on %s)", dev);
+	}
+	printf("\n");
+	if (pan[NL802154_PAN_COORD_ADDR]) {
+		struct nlattr *coord = pan[NL802154_PAN_COORD_ADDR];
+		if (nla_len(coord) == 2) {
+			uint16_t addr = nla_get_u16(coord);
+			printf("\tcoordinator 0x%04x\n", le16toh(addr));
+		} else {
+			uint64_t addr = nla_get_u64(coord);
+			printf("\tcoordinator 0x%016" PRIx64 "\n", le64toh(addr));
+		}
+	}
+	if (pan[NL802154_PAN_PAGE]) {
+		printf("\tpage %u\n", nla_get_u8(pan[NL802154_PAN_PAGE]));
+	}
+	if (pan[NL802154_PAN_CHANNEL]) {
+		printf("\tchannel %u\n", nla_get_u8(pan[NL802154_PAN_CHANNEL]));
+	}
+	if (pan[NL802154_PAN_SUPERFRAME_SPEC]) {
+		printf("\tsuperframe spec. 0x%x\n", nla_get_u16(
+				pan[NL802154_PAN_SUPERFRAME_SPEC]));
+	}
+	if (pan[NL802154_PAN_LINK_QUALITY]) {
+		printf("\tLQI %x\n", nla_get_u8(
+				pan[NL802154_PAN_LINK_QUALITY]));
+	}
+	if (pan[NL802154_PAN_GTS_PERMIT]) {
+		printf("\tGTS permitted\n");
+	}
+	if (pan[NL802154_PAN_STATUS]) {
+		printf("\tstatus 0x%x\n", nla_get_u32(
+				pan[NL802154_PAN_STATUS]));
+	}
+	if (pan[NL802154_PAN_SEEN_MS_AGO]) {
+		printf("\tseen %ums ago\n", nla_get_u32(
+				pan[NL802154_PAN_SEEN_MS_AGO]));
+	}
+
+	/* TODO: Beacon IES display/decoding */
+
+	return NL_OK;
+}
+
+static int print_scan_dump_handler(struct nl_msg *msg, void *arg)
+{
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct nlattr *tb[NL802154_ATTR_MAX + 1];
+	struct nlattr *nestedpan;
+
+	nla_parse(tb, NL802154_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+	nestedpan = tb[NL802154_ATTR_PAN];
+	if (!nestedpan) {
+		fprintf(stderr, "pan info missing!\n");
+		return NL_SKIP;
+	}
+	return parse_scan_result_pan(nestedpan, tb[NL802154_ATTR_IFINDEX]);
+}
+
+struct scan_done
+{
+	volatile int done;
+	int devidx;
+};
+
+static int wait_scan_done_handler(struct nl_msg *msg, void *arg)
+{
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct scan_done *sd = (struct scan_done *)arg;
+	if (gnlh->cmd != NL802154_CMD_SCAN_DONE)
+		return 0;
+	else if (sd->devidx != -1) {
+		struct nlattr *tb[NL802154_ATTR_MAX + 1];
+		nla_parse(tb, NL802154_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+			genlmsg_attrlen(gnlh, 0), NULL);
+		if (!tb[NL802154_ATTR_IFINDEX] ||
+			nla_get_u32(tb[NL802154_ATTR_IFINDEX]) != sd->devidx)
+			return 0;
+	}
+	sd->done = 1;
+	return 0;
+}
+
+static int no_seq_check(struct nl_msg *msg, void *arg)
+{
+	return NL_OK;
+}
+
+static int scan_done_handler(struct nl802154_state *state,
+			     struct nl_cb *cb,
+			     struct nl_msg *msg,
+			     int argc, char **argv,
+			     enum id_input id)
+{
+	struct nl_cb *s_cb;
+	struct scan_done sd;
+	int ret, group;
+
+	/* Configure socket to receive messages in Scan multicast group */
+	group = genl_ctrl_resolve_grp(state->nl_sock, "nl802154", "scan");
+	if (group < 0)
+		return group;
+	ret = nl_socket_add_membership(state->nl_sock, group);
+	if (ret)
+		return ret;
+	/* Init netlink callbacks as if we run a command */
+	cb = nl_cb_alloc(iwpan_debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
+	if (!cb) {
+		fprintf(stderr, "failed to allocate netlink callbacks\n");
+		return 2;
+	}
+	nl_socket_set_cb(state->nl_sock, cb);
+	/* no sequence checking for multicast messages */
+	nl_socket_disable_seq_check(state->nl_sock);
+	/* install scan done message handler */
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, wait_scan_done_handler, &sd);
+	/* set net device filter */
+	sd.devidx = if_nametoindex(*argv);
+	if (sd.devidx == 0)
+		sd.devidx = -1;
+	sd.done = 0;
+	/* loop waiting */
+	while (sd.done == 0)
+		nl_recvmsgs(state->nl_sock, cb);
+	/* restore seq & leave multicast group */
+	ret = nl_socket_drop_membership(state->nl_sock, group);
+	nl_cb_put(cb);
+	return ret;
+}
+
+static int scan_combined_handler(struct nl802154_state *state,
+				 struct nl_cb *cb,
+				 struct nl_msg *msg,
+				 int argc, char **argv,
+				 enum id_input id)
+{
+	char **trig_argv;
+	static char *done_argv[] = {
+		NULL,
+		"scan",
+		"done",
+	};
+	static char *dump_argv[] = {
+		NULL,
+		"pans",
+		"dump",
+	};
+	int trig_argc, err;
+	int i;
+
+	/* dev wpan0 scan trigger ... */
+	trig_argc = 3 + (argc - 2);
+	trig_argv = calloc(trig_argc, sizeof(*trig_argv));
+	if (!trig_argv)
+		return -ENOMEM;
+	trig_argv[0] = argv[0];
+	trig_argv[1] = "scan";
+	trig_argv[2] = "trigger";
+	for (i = 0; i < argc - 2; i++)
+		trig_argv[i + 3] = argv[i + 2];
+	err = handle_cmd(state, id, trig_argc, trig_argv);
+	free(trig_argv);
+	if (err)
+		return err;
+
+	/* dev wpan0 scan done */
+	done_argv[0] = argv[0];
+	err = handle_cmd(state, id, 3, done_argv);
+	if (err)
+		return err;
+
+	/* dev wpan0 scan dump */
+	dump_argv[0] = argv[0];
+	return handle_cmd(state, id, 3, dump_argv);
+}
+TOPLEVEL(scan, "type <type> [page <page>] [channels <bitfield>] [duration <duration-order>]",
+	0, 0, CIB_NETDEV, scan_combined_handler,
+	"Scan on this virtual interface with the given configuration.\n"
+	SCAN_TYPES);
+COMMAND(scan, abort, NULL, NL802154_CMD_ABORT_SCAN, 0, CIB_NETDEV, scan_abort_handler,
+	"Abort ongoing scanning on this virtual interface");
+COMMAND(scan, done, NULL, 0, 0, CIB_NETDEV, scan_done_handler,
+	"Wait scan terminated on this virtual interface");
+COMMAND(scan, trigger,
+	"type <type> [page <page>] [channels <bitfield>] [duration <duration-order>]",
+	NL802154_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, scan_trigger_handler,
+	"Launch scanning on this virtual interface with the given configuration.\n"
+	SCAN_TYPES);
+
+SECTION(pans);
+
+static unsigned int scan_dump_offset;
+
+static int pans_dump_handler(struct nl802154_state *state,
+			     struct nl_cb *cb,
+			     struct nl_msg *msg,
+			     int argc, char **argv,
+			     enum id_input id)
+{
+	int ret;
+	scan_dump_offset = 0;
+	/* Configure socket to receive messages in scan multicast group */
+	ret = genl_ctrl_resolve_grp(state->nl_sock, "nl802154", "scan");
+	if (ret < 0)
+		return ret;
+	ret = nl_socket_add_membership(state->nl_sock, ret);
+	if (ret)
+		return ret;
+	/* Set custom callback to decode received message on scan group */
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_scan_dump_handler, &scan_dump_offset);
+	return 0;
+}
+
+static int pans_flush_handler(struct nl802154_state *state,
+			      struct nl_cb *cb,
+			      struct nl_msg *msg,
+			      int argc, char **argv,
+			      enum id_input id)
+{
+	return 0;
+}
+
+COMMAND(pans, flush, NULL, NL802154_CMD_FLUSH_PANS, 0, CIB_NETDEV,
+	pans_flush_handler,
+	"Flush list of known PANs on this virtual interface");
+COMMAND(pans, dump, NULL, NL802154_CMD_DUMP_PANS, NLM_F_DUMP, CIB_NETDEV,
+	pans_dump_handler,
+	"Dump list of known PANs on this virtual interface");
+
+SECTION(beacons);
+
+static int send_beacons_handler(struct nl802154_state *state, struct nl_cb *cb,
+				struct nl_msg *msg, int argc, char **argv,
+				enum id_input id)
+{
+	unsigned long interval;
+	bool valid_interval;
+	int tpset;
+
+	tpset = get_option_value(&argc, &argv, "interval", &interval, &valid_interval);
+	if (tpset)
+		return tpset;
+	if (valid_interval && interval > UINT8_MAX)
+		return 1;
+
+	if (argc)
+		return 1;
+
+	/* Optional arguments */
+	if (valid_interval)
+		NLA_PUT_U8(msg, NL802154_ATTR_BEACON_INTERVAL, interval);
+
+	return 0;
+
+nla_put_failure:
+	return -ENOBUFS;
+}
+
+static int stop_beacons_handler(struct nl802154_state *state, struct nl_cb *cb,
+				struct nl_msg *msg, int argc, char **argv,
+				enum id_input id)
+{
+	return 0;
+}
+
+COMMAND(beacons, stop, NULL,
+	NL802154_CMD_STOP_BEACONS, 0, CIB_NETDEV, stop_beacons_handler,
+	"Stop sending beacons on this interface.");
+COMMAND(beacons, send, "[interval <interval-order>]",
+	NL802154_CMD_SEND_BEACONS, 0, CIB_NETDEV, send_beacons_handler,
+	"Send beacons on this virtual interface at a regular pace.");
-- 
2.27.0


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

* [wpan-tools v2 7/7] iwpan: Add events support
  2022-01-12 17:35 [wpan-tools v2 0/7] IEEE 802.15.4 scan support Miquel Raynal
                   ` (5 preceding siblings ...)
  2022-01-12 17:35 ` [wpan-tools v2 6/7] iwpan: Add full scan support Miquel Raynal
@ 2022-01-12 17:35 ` Miquel Raynal
  6 siblings, 0 replies; 8+ messages in thread
From: Miquel Raynal @ 2022-01-12 17:35 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
	Jakub Kicinski, netdev
  Cc: David Girault, Romuald Despres, Frederic Blain, Nicolas Schodet,
	Thomas Petazzoni, linux-wireless, Miquel Raynal

From: David Girault <david.girault@qorvo.com>

Add the possibility to listen to the scan multicast netlink family in
order to print all the events happening in the 802.15.4 stack.

Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 src/Makefile.am |   1 +
 src/event.c     | 221 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/iwpan.h     |   3 +
 src/scan.c      |   4 +-
 4 files changed, 227 insertions(+), 2 deletions(-)
 create mode 100644 src/event.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 18b3569..7933daf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,6 +10,7 @@ iwpan_SOURCES = \
 	phy.c \
 	mac.c \
 	scan.c \
+	event.c \
 	nl_extras.h \
 	nl802154.h
 
diff --git a/src/event.c b/src/event.c
new file mode 100644
index 0000000..0c5450b
--- /dev/null
+++ b/src/event.c
@@ -0,0 +1,221 @@
+#include <net/if.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <inttypes.h>
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+#include "nl802154.h"
+#include "nl_extras.h"
+#include "iwpan.h"
+
+struct print_event_args {
+	struct timeval ts; /* internal */
+	bool have_ts; /* must be set false */
+	bool frame, time, reltime;
+};
+
+static void parse_scan_terminated(struct nlattr **tb)
+{
+	struct nlattr *a;
+	if ((a = tb[NL802154_ATTR_SCAN_TYPE])) {
+		enum nl802154_scan_types st =
+			(enum nl802154_scan_types)nla_get_u8(a);
+		const char *stn = scantype_name(st);
+		printf(" type %s,", stn);
+	}
+	if ((a = tb[NL802154_ATTR_SCAN_FLAGS])) {
+		printf(" flags 0x%x,", nla_get_u32(a));
+	}
+	if ((a = tb[NL802154_ATTR_PAGE])) {
+		printf(" page %u,", nla_get_u8(a));
+	}
+	if ((a = tb[NL802154_ATTR_SCAN_CHANNELS])) {
+		printf(" channels mask 0x%x,", nla_get_u32(a));
+	}
+	/* TODO: show requested IEs */
+	if ((a = tb[NL802154_ATTR_PAN])) {
+		parse_scan_result_pan(a, tb[NL802154_ATTR_IFINDEX]);
+	}
+}
+
+static int print_event(struct nl_msg *msg, void *arg)
+{
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct nlattr *tb[NL802154_ATTR_MAX + 1], *nst;
+	struct print_event_args *args = arg;
+	char ifname[100];
+
+	uint8_t reg_type;
+	uint32_t wpan_phy_idx = 0;
+	int rem_nst;
+	uint16_t status;
+
+	if (args->time || args->reltime) {
+		unsigned long long usecs, previous;
+
+		previous = 1000000ULL * args->ts.tv_sec + args->ts.tv_usec;
+		gettimeofday(&args->ts, NULL);
+		usecs = 1000000ULL * args->ts.tv_sec + args->ts.tv_usec;
+		if (args->reltime) {
+			if (!args->have_ts) {
+				usecs = 0;
+				args->have_ts = true;
+			} else
+				usecs -= previous;
+		}
+		printf("%llu.%06llu: ", usecs/1000000, usecs % 1000000);
+	}
+
+	nla_parse(tb, NL802154_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+	if (tb[NL802154_ATTR_IFINDEX] && tb[NL802154_ATTR_WPAN_PHY]) {
+		if_indextoname(nla_get_u32(tb[NL802154_ATTR_IFINDEX]), ifname);
+		printf("%s (phy #%d): ", ifname, nla_get_u32(tb[NL802154_ATTR_WPAN_PHY]));
+	} else if (tb[NL802154_ATTR_WPAN_DEV] && tb[NL802154_ATTR_WPAN_PHY]) {
+		printf("wdev 0x%llx (phy #%d): ",
+			(unsigned long long)nla_get_u64(tb[NL802154_ATTR_WPAN_DEV]),
+			nla_get_u32(tb[NL802154_ATTR_WPAN_PHY]));
+	} else if (tb[NL802154_ATTR_IFINDEX]) {
+		if_indextoname(nla_get_u32(tb[NL802154_ATTR_IFINDEX]), ifname);
+		printf("%s: ", ifname);
+	} else if (tb[NL802154_ATTR_WPAN_DEV]) {
+		printf("wdev 0x%llx: ", (unsigned long long)nla_get_u64(tb[NL802154_ATTR_WPAN_DEV]));
+	} else if (tb[NL802154_ATTR_WPAN_PHY]) {
+		printf("phy #%d: ", nla_get_u32(tb[NL802154_ATTR_WPAN_PHY]));
+	}
+
+	switch (gnlh->cmd) {
+	case NL802154_CMD_NEW_WPAN_PHY:
+		printf("renamed to %s\n", nla_get_string(tb[NL802154_ATTR_WPAN_PHY_NAME]));
+		break;
+	case NL802154_CMD_DEL_WPAN_PHY:
+		printf("delete wpan_phy\n");
+		break;
+	case NL802154_CMD_TRIGGER_SCAN:
+		printf("scan started\n");
+		break;
+	case NL802154_CMD_SCAN_DONE:
+		printf("scan finished:");
+		parse_scan_terminated(tb);
+		printf("\n");
+		break;
+	default:
+		printf("unknown event %d\n", gnlh->cmd);
+		break;
+	}
+	fflush(stdout);
+	return NL_SKIP;
+}
+
+static int __prepare_listen_events(struct nl802154_state *state)
+{
+	int mcid, ret;
+
+	/* Configuration multicast group */
+	mcid = genl_ctrl_resolve_grp(state->nl_sock, NL802154_GENL_NAME,
+				     "config");
+	if (mcid < 0)
+		return mcid;
+	ret = nl_socket_add_membership(state->nl_sock, mcid);
+	if (ret)
+		return ret;
+
+	/* Scan multicast group */
+	mcid = genl_ctrl_resolve_grp(state->nl_sock, NL802154_GENL_NAME,
+				     "scan");
+	if (mcid >= 0) {
+		ret = nl_socket_add_membership(state->nl_sock, mcid);
+		if (ret)
+			return ret;
+	}
+
+	/* MLME multicast group */
+	mcid = genl_ctrl_resolve_grp(state->nl_sock, NL802154_GENL_NAME,
+				     "mlme");
+	if (mcid >= 0) {
+		ret = nl_socket_add_membership(state->nl_sock, mcid);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int __do_listen_events(struct nl802154_state *state,
+			      struct print_event_args *args)
+{
+	struct nl_cb *cb = nl_cb_alloc(iwpan_debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
+	if (!cb) {
+		fprintf(stderr, "failed to allocate netlink callbacks\n");
+		return -ENOMEM;
+	}
+	nl_socket_set_cb(state->nl_sock, cb);
+	/* No sequence checking for multicast messages */
+	nl_socket_disable_seq_check(state->nl_sock);
+	/* Install print_event message handler */
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_event, args);
+
+	/* Loop waiting until interrupted by signal */
+	while (1) {
+		int ret = nl_recvmsgs(state->nl_sock, cb);
+		if (ret) {
+			fprintf(stderr, "nl_recvmsgs return error %d\n", ret);
+			break;
+		}
+	}
+	/* Free allocated nl_cb structure */
+	nl_cb_put(cb);
+	return 0;
+}
+
+static int print_events(struct nl802154_state *state,
+			struct nl_cb *cb,
+			struct nl_msg *msg,
+			int argc, char **argv,
+			enum id_input id)
+{
+	struct print_event_args args;
+	int ret;
+
+	memset(&args, 0, sizeof(args));
+
+	argc--;
+	argv++;
+
+	while (argc > 0) {
+		if (strcmp(argv[0], "-f") == 0)
+			args.frame = true;
+		else if (strcmp(argv[0], "-t") == 0)
+			args.time = true;
+		else if (strcmp(argv[0], "-r") == 0)
+			args.reltime = true;
+		else
+			return 1;
+		argc--;
+		argv++;
+	}
+	if (args.time && args.reltime)
+		return 1;
+	if (argc)
+		return 1;
+
+	/* Prepare reception of all multicast messages */
+	ret = __prepare_listen_events(state);
+	if (ret)
+		return ret;
+
+	/* Read message loop */
+	return __do_listen_events(state, &args);
+}
+TOPLEVEL(event, "[-t|-r] [-f]", 0, 0, CIB_NONE, print_events,
+	"Monitor events from the kernel.\n"
+	"-t - print timestamp\n"
+	"-r - print relative timestamp\n"
+	"-f - print full frame for auth/assoc etc.");
diff --git a/src/iwpan.h b/src/iwpan.h
index 406940a..a71b991 100644
--- a/src/iwpan.h
+++ b/src/iwpan.h
@@ -114,6 +114,9 @@ DECLARE_SECTION(get);
 
 const char *iftype_name(enum nl802154_iftype iftype);
 
+const char *scantype_name(enum nl802154_scan_types scantype);
+int parse_scan_result_pan(struct nlattr *nestedpan, struct nlattr *ifattr);
+
 extern int iwpan_debug;
 
 #endif /* __IWPAN_H */
diff --git a/src/scan.c b/src/scan.c
index ec91c7c..a557e09 100644
--- a/src/scan.c
+++ b/src/scan.c
@@ -16,7 +16,7 @@
 
 static char scantypebuf[100];
 
-static const char *scantype_name(enum nl802154_scan_types scantype)
+const char *scantype_name(enum nl802154_scan_types scantype)
 {
 	switch (scantype) {
 	case NL802154_SCAN_ED:
@@ -168,7 +168,7 @@ static int scan_abort_handler(struct nl802154_state *state,
 }
 
 
-static int parse_scan_result_pan(struct nlattr *nestedpan, struct nlattr *ifattr)
+int parse_scan_result_pan(struct nlattr *nestedpan, struct nlattr *ifattr)
 {
 	struct nlattr *pan[NL802154_PAN_MAX + 1];
 	static struct nla_policy pan_policy[NL802154_PAN_MAX + 1] = {
-- 
2.27.0


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

end of thread, other threads:[~2022-01-12 17:36 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-12 17:35 [wpan-tools v2 0/7] IEEE 802.15.4 scan support Miquel Raynal
2022-01-12 17:35 ` [wpan-tools v2 1/7] iwpan: Fix the channels printing Miquel Raynal
2022-01-12 17:35 ` [wpan-tools v2 2/7] iwpan: Export iwpan_debug Miquel Raynal
2022-01-12 17:35 ` [wpan-tools v2 3/7] iwpan: Fix a comment Miquel Raynal
2022-01-12 17:35 ` [wpan-tools v2 4/7] iwpan: Remove duplicated SECTION Miquel Raynal
2022-01-12 17:35 ` [wpan-tools v2 5/7] iwpan: Synchronize nl802154 header with the Linux kernel Miquel Raynal
2022-01-12 17:35 ` [wpan-tools v2 6/7] iwpan: Add full scan support Miquel Raynal
2022-01-12 17:35 ` [wpan-tools v2 7/7] iwpan: Add events support Miquel Raynal

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.