From kartik.mgit at gmail.com Fri Jul 3 15:57:36 2026 From: kartik.mgit at gmail.com (Kartik Rajput) Date: Fri, 3 Jul 2026 22:57:36 +0000 Subject: [RFC] wpa_supplicant: Added Support for Varlink folder structure Message-ID: <20260703225736.579-1-kartik.mgit@gmail.com> 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 --- 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_=y) or dynamically (CONFIG_EAP_=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 + * + * 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 + * + * 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 + +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 + * + * 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 + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. +*/ + +#include "utils/includes.h" +#include + +#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 + * + * 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 + +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 + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. +*/ + +#include "utils/includes.h" +#include + +#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 +#include + +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