Linux-Wireless Archive mirror
 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).