[RFC] wpa_supplicant: Added Support for Varlink folder structure
Kartik Rajput
kartik.mgit at gmail.com
Fri Jul 3 15:57:36 PDT 2026
Added Basic Scalfholding for Varlink Server and socket.
Configured Makefile for linking libvarlink C bindings to wpa_supplicant in the Makefiles. Also appeneded clean instructions for the object/output files.
Added a new flag -V representing varlink enablement, without it off by default.
In defconfig added a simple flag CONFIG_CTRL_IFACE_VARLINK to enable/disable compilation.
Varlink is still disabled via wpa_params, even if compiled with, until -V is supplied through the initial call.
Used dbus Makefile as base for Varlink.
varlink_common_i.h is for internal uses. varlink_common.h, varlink_server.c, and varlink_events.c is for init and public event calls, used by the notify.c
varlink_methods.c and varlink_methods.h is for client side usage.
org.wlan.supplicant.varlink is for varlink structure and maybe (MAYBE) parsing.
Signed-off-by: Kartik Rajput <kartik.mgit at gmail.com>
---
wpa_supplicant/Makefile | 16 +++
wpa_supplicant/defconfig | 3 +
wpa_supplicant/main.c | 11 +-
wpa_supplicant/notify.c | 16 +++
wpa_supplicant/varlink/.gitignore | 1 +
wpa_supplicant/varlink/Makefile | 57 ++++++++++
.../varlink/org.wlan.supplicant.varlink | 4 +
wpa_supplicant/varlink/varlink_common.h | 40 +++++++
wpa_supplicant/varlink/varlink_common_i.h | 20 ++++
wpa_supplicant/varlink/varlink_events.c | 7 ++
wpa_supplicant/varlink/varlink_methods.c | 53 +++++++++
wpa_supplicant/varlink/varlink_methods.h | 20 ++++
wpa_supplicant/varlink/varlink_server.c | 104 ++++++++++++++++++
wpa_supplicant/wpa_supplicant.c | 5 +
wpa_supplicant/wpa_supplicant_i.h | 14 +++
15 files changed, 370 insertions(+), 1 deletion(-)
create mode 100644 wpa_supplicant/varlink/.gitignore
create mode 100644 wpa_supplicant/varlink/Makefile
create mode 100644 wpa_supplicant/varlink/org.wlan.supplicant.varlink
create mode 100644 wpa_supplicant/varlink/varlink_common.h
create mode 100644 wpa_supplicant/varlink/varlink_common_i.h
create mode 100644 wpa_supplicant/varlink/varlink_events.c
create mode 100644 wpa_supplicant/varlink/varlink_methods.c
create mode 100644 wpa_supplicant/varlink/varlink_methods.h
create mode 100644 wpa_supplicant/varlink/varlink_server.c
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 2b82c42c8..58885bcd5 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -1800,6 +1800,21 @@ CFLAGS += $(DBUS_INCLUDE)
LIBS += $(DBUS_LIBS)
endif
+ifdef CONFIG_CTRL_IFACE_VARLINK
+CFLAGS += -DCONFIG_CTRL_IFACE_VARLINK
+OBJS += varlink/varlink_server.o
+OBJS += varlink/varlink_methods.o
+OBJS += varlink/varlink_events.o
+ifndef VARLINK_LIBS
+VARLINK_LIBS := $(shell $(PKG_CONFIG) --libs libvarlink)
+endif
+ifndef VARLINK_INCLUDE
+VARLINK_INCLUDE := $(shell $(PKG_CONFIG) --cflags libvarlink)
+endif
+CFLAGS += $(VARLINK_INCLUDE)
+LIBS += $(VARLINK_LIBS)
+endif
+
ifdef CONFIG_READLINE
OBJS_c += ../src/utils/edit_readline.o
LIBS_c += -lreadline -lncurses
@@ -2399,6 +2414,7 @@ libpasn.so: $(LIBPASNSO)
clean: common-clean
$(MAKE) -C ../src clean
$(MAKE) -C dbus clean
+ $(MAKE) -C varlink clean
rm -f core *~ *.o *.d *.gcno *.gcda *.gcov
rm -f eap_*.so $(WINALL) eapol_test preauth_test
rm -f wpa_priv
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index bc865ce5f..a9cb4c460 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -380,6 +380,9 @@ CONFIG_CTRL_IFACE_DBUS_NEW=y
# Add introspection support for new DBus control interface
CONFIG_CTRL_IFACE_DBUS_INTRO=y
+# Add support for varlink control interface
+CONFIG_CTRL_IFACE_VARLINK=y
+
# Add support for loading EAP methods dynamically as shared libraries.
# When this option is enabled, each EAP method can be either included
# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c
index eeb3606ad..4a787cb0a 100644
--- a/wpa_supplicant/main.c
+++ b/wpa_supplicant/main.c
@@ -213,7 +213,7 @@ int main(int argc, char *argv[])
for (;;) {
c = getopt(argc, argv,
- "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvWyz:");
+ "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuVvWyz:");
if (c < 0)
break;
switch (c) {
@@ -313,6 +313,15 @@ int main(int argc, char *argv[])
params.dbus_ctrl_interface = 1;
break;
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
+#ifdef CONFIG_CTRL_IFACE_VARLINK
+ case 'V':
+ params.varlink_ctrl_interface = 1;
+ break;
+#else
+ case 'V':
+ printf("Varlink is not compiled with wpa_supplicant in this version!\n");
+ break;
+#endif /* CONFIG_CTRL_IFACE_VARLINK */
case 'v':
printf("%s\n", wpa_supplicant_version);
exitcode = 0;
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index af1b4e3da..d56bb173f 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -17,6 +17,9 @@
#include "binder/binder.h"
#include "dbus/dbus_common.h"
#include "dbus/dbus_new.h"
+#ifdef CONFIG_CTRL_IFACE_VARLINK
+#include "varlink/varlink_common.h"
+#endif /* CONFIG_CTRL_IFACE_VARLINK */
#include "rsn_supp/wpa.h"
#include "rsn_supp/pmksa_cache.h"
#include "fst/fst.h"
@@ -38,6 +41,14 @@ int wpas_notify_supplicant_initialized(struct wpa_global *global)
}
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
+#ifdef CONFIG_CTRL_IFACE_VARLINK
+ if (global->params.varlink_ctrl_interface) {
+ global->varlink = wpas_varlink_init(global);
+ if (global->varlink == NULL)
+ return -1;
+ }
+#endif /* CONFIG_CTRL_IFACE_VARLINK */
+
#ifdef CONFIG_BINDER
global->binder = wpas_binder_init(global);
if (!global->binder)
@@ -55,6 +66,11 @@ void wpas_notify_supplicant_deinitialized(struct wpa_global *global)
wpas_dbus_deinit(global->dbus);
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
+#ifdef CONFIG_CTRL_IFACE_VARLINK
+ if (global->varlink)
+ wpas_varlink_deinit(global->varlink);
+#endif /* CONFIG_CTRL_IFACE_VARLINK */
+
#ifdef CONFIG_BINDER
if (global->binder)
wpas_binder_deinit(global->binder);
diff --git a/wpa_supplicant/varlink/.gitignore b/wpa_supplicant/varlink/.gitignore
new file mode 100644
index 000000000..c792507d2
--- /dev/null
+++ b/wpa_supplicant/varlink/.gitignore
@@ -0,0 +1 @@
+libwpavarlink.a
\ No newline at end of file
diff --git a/wpa_supplicant/varlink/Makefile b/wpa_supplicant/varlink/Makefile
new file mode 100644
index 000000000..e49c04506
--- /dev/null
+++ b/wpa_supplicant/varlink/Makefile
@@ -0,0 +1,57 @@
+all: libwpavarlink.a
+
+clean:
+ rm -f *~ *.o *.d *.gcno *.gcda *.gcov
+ rm -f libwpavarlink.a
+
+install:
+ @echo Nothing to be made.
+
+ifndef CC
+CC=gcc
+endif
+
+ifndef CFLAGS
+CFLAGS = -MMD -O2 -Wall -g
+endif
+
+PKG_CONFIG ?= pkg-config
+CFLAGS += -I../../src -I../../src/utils
+
+
+Q=@
+E=echo
+ifeq ($(V), 1)
+Q=
+E=true
+endif
+
+%.o: %.c
+ $(Q)$(CC) -c -o $@ $(CFLAGS) $<
+ @$(E) " CC " $<
+
+
+ifdef CONFIG_WPS
+CFLAGS += -DCONFIG_WPS
+endif
+
+CFLAGS += -DCONFIG_CTRL_IFACE_VARLINK
+
+ifndef VARLINK_LIBS
+VARLINK_LIBS := $(shell $(PKG_CONFIG) --libs libvarlink)
+endif
+ifndef VARLINK_INCLUDE
+VARLINK_INCLUDE := $(shell $(PKG_CONFIG) --cflags libvarlink)
+endif
+
+CFLAGS += $(VARLINK_INCLUDE)
+
+LIB_OBJS= \
+ varlink_server.o \
+ varlink_methods.o \
+ varlink_events.o
+
+libwpavarlink.a: $(LIB_OBJS)
+ $(AR) crT $@ $?
+
+-include $(OBJS:%.o=%.d)
diff --git a/wpa_supplicant/varlink/org.wlan.supplicant.varlink b/wpa_supplicant/varlink/org.wlan.supplicant.varlink
new file mode 100644
index 000000000..05194f3dd
--- /dev/null
+++ b/wpa_supplicant/varlink/org.wlan.supplicant.varlink
@@ -0,0 +1,4 @@
+interface org.wlan.supplicant
+
+# Returns the current state of the daemon
+method GetState() -> (state: string)
diff --git a/wpa_supplicant/varlink/varlink_common.h b/wpa_supplicant/varlink/varlink_common.h
new file mode 100644
index 000000000..f13d8f3de
--- /dev/null
+++ b/wpa_supplicant/varlink/varlink_common.h
@@ -0,0 +1,40 @@
+/*
+ * wpa_supplicant Varlink control interface - common definitions
+ * Copyright (c) 2026, Kartik Rajput <incorrectmail101 at gmail.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+*/
+
+#ifndef HOSTAP_VARLINK_COMMON_H
+#define HOSTAP_VARLINK_COMMON_H
+
+#define WPAS_VARLINK_ADDRESS "unix:/run/wpa_supplicant/varlink"
+#define WPAS_VARLINK_FILE_PATH "/run/wpa_supplicant/varlink"
+#define WPAS_VARLINK_PARENT_FOLDER "/run/wpa_supplicant"
+
+#define WPAS_VARLINK_INTERFACE "fi.w1.wpasupplicant"
+
+#define WPAS_VARLINK_VENDOR "fi.w1"
+#define WPAS_VARLINK_PRODUCT "wpa_supplicant"
+#define WPAS_VARLINK_VERSION "1"
+#define WPAS_VARLINK_VENDOR_URL "https://w1.fi/"
+
+struct wpas_varlink_priv;
+struct wpa_global;
+
+#ifdef CONFIG_CTRL_IFACE_VARLINK
+ struct wpas_varlink_priv * wpas_varlink_init(struct wpa_global * global);
+ void wpas_varlink_deinit(struct wpas_varlink_priv * priv);
+#else
+ static inline struct wpas_varlink_priv * wpas_varlink_init(struct wpa_global *global)
+ {
+ return NULL;
+ }
+
+ static inline void wpas_varlink_deinit(struct wpas_varlink_priv *priv)
+ {
+ }
+#endif
+
+#endif /* HOSTAP_VARLINK_COMMON_H */
diff --git a/wpa_supplicant/varlink/varlink_common_i.h b/wpa_supplicant/varlink/varlink_common_i.h
new file mode 100644
index 000000000..007219783
--- /dev/null
+++ b/wpa_supplicant/varlink/varlink_common_i.h
@@ -0,0 +1,20 @@
+/*
+ * wpa_supplicant Varlink control interface - internal definitions
+ * Copyright (c) 2026, Kartik Rajput <incorrectmail101 at gmail.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+*/
+
+#ifndef HOSTAP_VARLINK_COMMON_I_H
+#define HOSTAP_VARLINK_COMMON_I_H
+
+#include <varlink.h>
+
+struct wpas_varlink_priv {
+ struct wpa_global * global;
+ VarlinkService * service;
+ int varlink_fd;
+};
+
+#endif /* HOSTAP_VARLINK_COMMON_I_H */
diff --git a/wpa_supplicant/varlink/varlink_events.c b/wpa_supplicant/varlink/varlink_events.c
new file mode 100644
index 000000000..855c04d28
--- /dev/null
+++ b/wpa_supplicant/varlink/varlink_events.c
@@ -0,0 +1,7 @@
+/*
+ * wpa_supplicant D-Bus control interface - common definitions
+ * Copyright (c) 2026, Kartik Rajput <incorrectmail101 at gmail.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+*/
\ No newline at end of file
diff --git a/wpa_supplicant/varlink/varlink_methods.c b/wpa_supplicant/varlink/varlink_methods.c
new file mode 100644
index 000000000..b6cbd77f9
--- /dev/null
+++ b/wpa_supplicant/varlink/varlink_methods.c
@@ -0,0 +1,53 @@
+/*
+ * wpa_supplicant D-Bus control interface - common definitions
+ * Copyright (c) 2026, Kartik Rajput <incorrectmail101 at gmail.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+*/
+
+#include "utils/includes.h"
+#include <varlink.h>
+
+#include "utils/common.h"
+#include "utils/wpa_debug.h"
+#include "utils/eloop.h"
+#include "varlink_common_i.h"
+#include "varlink_common.h"
+#include "../wpa_supplicant_i.h"
+
+long wpas_varlink_get_state(VarlinkService *service,
+ VarlinkCall *call,
+ VarlinkObject *parameters,
+ uint64_t flags,
+ void *userdata)
+{
+ struct wpas_varlink_priv *priv = userdata;
+ const char *ifname;
+ struct wpa_supplicant *wpa_s;
+ VarlinkObject *out = NULL;
+
+ if (varlink_object_get_string(parameters, "ifname", &ifname) < 0) {
+ return varlink_call_reply_invalid_parameter(call, "ifname");
+ }
+
+ wpa_s = wpa_supplicant_get_iface(priv->global, ifname);
+ if (wpa_s == NULL) {
+ /* If it doesn't exist, return our custom Varlink error */
+ VarlinkObject *err_params;
+ varlink_object_new(&err_params);
+ varlink_object_set_string(err_params, "ifname", ifname);
+ long ret = varlink_call_reply_error(call, WPAS_VARLINK_INTERFACE ".InterfaceUnknown", err_params);
+ varlink_object_unref(err_params);
+ return ret;
+ }
+
+ varlink_object_new(&out);
+
+ varlink_object_set_string(out, "state", wpa_supplicant_state_txt(wpa_s->wpa_state));
+
+ varlink_call_reply(call, out, 0);
+ varlink_object_unref(out);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/wpa_supplicant/varlink/varlink_methods.h b/wpa_supplicant/varlink/varlink_methods.h
new file mode 100644
index 000000000..f5b80e4eb
--- /dev/null
+++ b/wpa_supplicant/varlink/varlink_methods.h
@@ -0,0 +1,20 @@
+/*
+ * wpa_supplicant Varlink control interface - common definitions
+ * Copyright (c) 2026, Kartik Rajput <incorrectmail101 at gmail.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+*/
+
+#ifndef HOSTAP_VARLINK_METHODS_H
+#define HOSTAP_VARLINK_METHODS_H
+
+#include <varlink.h>
+
+long wpas_varlink_get_state(VarlinkService *service,
+ VarlinkCall *call,
+ VarlinkObject *parameters,
+ uint64_t flags,
+ void *userdata);
+
+#endif /* HOSTAP_VARLINK_METHODS_H */
\ No newline at end of file
diff --git a/wpa_supplicant/varlink/varlink_server.c b/wpa_supplicant/varlink/varlink_server.c
new file mode 100644
index 000000000..a31e632ab
--- /dev/null
+++ b/wpa_supplicant/varlink/varlink_server.c
@@ -0,0 +1,104 @@
+/*
+ * wpa_supplicant D-Bus control interface - common definitions
+ * Copyright (c) 2026, Kartik Rajput <incorrectmail101 at gmail.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+*/
+
+#include "utils/includes.h"
+#include <varlink.h>
+
+#include "utils/common.h"
+#include "utils/wpa_debug.h"
+#include "utils/eloop.h"
+#include "varlink_common_i.h"
+#include "varlink_common.h"
+#include "varlink_methods.h"
+#include "../wpa_supplicant_i.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+void wpas_varlink_receive_handler(int sock, void *eloop_ctx, void *sock_ctx)
+{
+ struct wpas_varlink_priv *priv = eloop_ctx;
+
+ varlink_service_process_events(priv->service);
+}
+
+void wpas_varlink_deinit(struct wpas_varlink_priv * priv){
+ if (priv == NULL)
+ return;
+
+ if (priv->varlink_fd >= 0) {
+ eloop_unregister_read_sock(priv->varlink_fd);
+ }
+
+ if (priv->service) {
+ varlink_service_free(priv->service);
+ }
+
+ wpa_printf(MSG_DEBUG, "varlink: Unlink previous socket '%s'", WPAS_VARLINK_FILE_PATH);
+ unlink("/run/wpa_supplicant/varlink");
+
+ wpa_printf(MSG_DEBUG, "varlink: De-Register varlink object '%s'", WPAS_VARLINK_ADDRESS);
+
+ os_free(priv);
+}
+
+struct wpas_varlink_priv * wpas_varlink_init(struct wpa_global * global){
+ struct wpas_varlink_priv * priv;
+
+ priv = os_zalloc(sizeof(*priv));
+ if (priv == NULL)
+ return NULL;
+ priv->global = global;
+ priv->varlink_fd = -1;
+
+ /* rwxr-xr-x */
+ wpa_printf(MSG_DEBUG, "varlink: Creating varlink folder '%s'", WPAS_VARLINK_PARENT_FOLDER);
+ mkdir(WPAS_VARLINK_PARENT_FOLDER, 0755);
+ /* Clear previous socket if still there */
+ wpa_printf(MSG_DEBUG, "varlink: Unlink previous socket '%s'", WPAS_VARLINK_FILE_PATH);
+ unlink(WPAS_VARLINK_FILE_PATH);
+
+ if(varlink_service_new(&priv->service,
+ WPAS_VARLINK_VENDOR,
+ WPAS_VARLINK_PRODUCT,
+ WPAS_VARLINK_VERSION,
+ WPAS_VARLINK_VENDOR_URL,
+ WPAS_VARLINK_ADDRESS,
+ -1) != 0){
+ wpas_varlink_deinit(priv);
+ return NULL;
+ }
+
+ const char *schema =
+ "interface " WPAS_VARLINK_INTERFACE "\n"
+ "method GetState(ifname: string) -> (state: string)\n"
+ "error InterfaceUnknown(ifname: string)\n";
+
+ if (varlink_service_add_interface(priv->service, schema,
+ "GetState",
+ wpas_varlink_get_state,
+ priv,
+ NULL) != 0) {
+ wpa_printf(MSG_ERROR, "varlink: Failed to add interface");
+ wpas_varlink_deinit(priv);
+ return NULL;
+ }
+
+ priv->varlink_fd = varlink_service_get_fd(priv->service);
+ if(priv->varlink_fd < 0){
+ wpas_varlink_deinit(priv);
+ return NULL;
+ }
+
+ eloop_register_read_sock(priv->varlink_fd, wpas_varlink_receive_handler, priv, NULL);
+
+ wpa_printf(MSG_DEBUG, "varlink: Register varlink object '%s'", WPAS_VARLINK_ADDRESS);
+
+ return priv;
+}
+
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 45f6ea852..9391a8813 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -8639,6 +8639,11 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
global->params.daemonize = params->daemonize;
global->params.wait_for_monitor = params->wait_for_monitor;
global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
+
+#ifdef CONFIG_CTRL_IFACE_VARLINK
+ global->params.varlink_ctrl_interface = params->varlink_ctrl_interface;
+#endif /* CONFIG_CTRL_IFACE_VARLINK */
+
global->params.show_details = params->show_details;
if (params->pid_file) {
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 0d59c31ae..039fc1d79 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -53,6 +53,10 @@ struct ctrl_iface_global_priv;
struct wpas_dbus_priv;
struct wpas_binder_priv;
+#ifdef CONFIG_CTRL_IFACE_VARLINK
+struct wpas_varlink_priv;
+#endif /* CONFIG_CTRL_IFACE_VARLINK */
+
/**
* struct wpa_interface - Parameters for wpa_supplicant_add_iface()
*/
@@ -206,6 +210,13 @@ struct wpa_params {
*/
int dbus_ctrl_interface;
+#ifdef CONFIG_CTRL_IFACE_VARLINK
+ /**
+ * varlink_ctrl_interface - Enable the Varlink control interface
+ */
+ int varlink_ctrl_interface;
+#endif /* CONFIG_CTRL_IFACE_VARLINK */
+
/**
* wpa_debug_file_path - Path of debug file or %NULL to use stdout
*/
@@ -304,6 +315,9 @@ struct wpa_global {
struct wpa_params params;
struct ctrl_iface_global_priv *ctrl_iface;
struct wpas_dbus_priv *dbus;
+#ifdef CONFIG_CTRL_IFACE_VARLINK
+ struct wpas_varlink_priv *varlink;
+#endif /* CONFIG_CTRL_IFACE_VARLINK */
struct wpas_binder_priv *binder;
void **drv_priv;
size_t drv_count;
--
2.47.3
More information about the Hostap
mailing list