diff mbox series

[wpa_suppplicant,1/2] netlink: add netlink_process_one_event()

Message ID 20231201114952.c278cb7ac0c4.If32fddf88f23f3939bb73bc6926aad7f88804079@changeid
State New
Headers show
Series wpa_supplicant: wait for carrier race | expand

Commit Message

Johannes Berg Dec. 1, 2023, 10:49 a.m. UTC
From: Johannes Berg <johannes.berg@intel.com>

Add a new function to read and process a single netlink event
with a timeout, to be used in driver_nl80211.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 src/drivers/netlink.c | 43 +++++++++++++++++++++++++++++++++++++++----
 src/drivers/netlink.h |  2 ++
 2 files changed, 41 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/src/drivers/netlink.c b/src/drivers/netlink.c
index 7780479c3e91..bbfe86eee7a0 100644
--- a/src/drivers/netlink.c
+++ b/src/drivers/netlink.c
@@ -33,19 +33,20 @@  static void netlink_receive_link(struct netlink_data *netlink,
 }
 
 
-static void netlink_receive(int sock, void *eloop_ctx, void *sock_ctx)
+static void _netlink_process_one_event(struct netlink_data *netlink,
+				       int wait_single)
 {
-	struct netlink_data *netlink = eloop_ctx;
 	char buf[8192];
 	int left;
 	struct sockaddr_nl from;
 	socklen_t fromlen;
 	struct nlmsghdr *h;
-	int max_events = 10;
+	int max_events = wait_single ? 1 : 10;
 
 try_again:
 	fromlen = sizeof(from);
-	left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
+	left = recvfrom(netlink->sock, buf, sizeof(buf),
+			wait_single ? 0 : MSG_DONTWAIT,
 			(struct sockaddr *) &from, &fromlen);
 	if (left < 0) {
 		if (errno != EINTR && errno != EAGAIN)
@@ -88,6 +89,40 @@  try_again:
 }
 
 
+void netlink_process_one_event(struct netlink_data *netlink,
+			       unsigned int timeout_ms)
+{
+	if (timeout_ms) {
+		struct timeval timeout = {
+			.tv_sec = timeout_ms / 1000,
+			.tv_usec = 1000 * (timeout_ms % 1000),
+		};
+		fd_set read_set;
+		int ret;
+
+		FD_ZERO(&read_set);
+		FD_SET(netlink->sock, &read_set);
+
+		ret = select(netlink->sock + 1, &read_set, NULL, NULL,
+			     &timeout);
+		if (ret < 0) {
+			perror("select on netlink socket");
+			return;
+		}
+		if (ret == 0)
+			return;
+	}
+
+	_netlink_process_one_event(netlink, 1);
+}
+
+
+static void netlink_receive(int sock, void *eloop_ctx, void *sock_ctx)
+{
+	_netlink_process_one_event(eloop_ctx, 0);
+}
+
+
 struct netlink_data * netlink_init(struct netlink_config *cfg)
 {
 	struct netlink_data *netlink;
diff --git a/src/drivers/netlink.h b/src/drivers/netlink.h
index 3a7340e51534..faee28b722ea 100644
--- a/src/drivers/netlink.h
+++ b/src/drivers/netlink.h
@@ -21,6 +21,8 @@  struct netlink_config {
 };
 
 struct netlink_data * netlink_init(struct netlink_config *cfg);
+void netlink_process_one_event(struct netlink_data *netlink,
+			       unsigned int timeout_ms);
 void netlink_deinit(struct netlink_data *netlink);
 int netlink_send_oper_ifla(struct netlink_data *netlink, int ifindex,
 			   int linkmode, int operstate);