ucode: update to the latest version

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau
2023-07-05 12:19:19 +00:00
committed by John Crispin
parent bccdb175b0
commit 323dc65770
11 changed files with 46 additions and 1203 deletions

View File

@@ -12,24 +12,37 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=https://github.com/jow-/ucode.git
PKG_MIRROR_HASH:=413a08ee63c30c44d6f0a5de14b1c84787f9bd1fe8b125c8e4956aa2884cc933
#PKG_MIRROR_HASH:=98303ef9d5fa7eca04042792abaf8a2e66082237a23a89a7f5e72e4409714a72
PKG_SOURCE_DATE:=2022-04-07
PKG_SOURCE_VERSION:=7fa59ce44b9347528b0e4e44ebcfb04a08479f3f
PKG_SOURCE_DATE:=2023-06-06
PKG_SOURCE_VERSION:=c7d84aae09691a99ae3db427c0b2463732ef84f4
PKG_MIRROR_HASH:=38826ae70d886d1d7ada3fc6591ac807169aa28107f60f7f2e617520083525fb
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
PKG_LICENSE:=ISC
PKG_ABI_VERSION:=20220322
PKG_ABI_VERSION:=20220812
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/host-build.mk
include $(INCLUDE_DIR)/cmake.mk
CMAKE_OPTIONS += -DSOVERSION=$(PKG_ABI_VERSION)
CMAKE_OPTIONS += -DSOVERSION=$(PKG_ABI_VERSION) -DLINUX=ON
CMAKE_HOST_OPTIONS += \
-DSOVERSION=$(PKG_ABI_VERSION) \
-DFS_SUPPORT=ON \
-DMATH_SUPPORT=ON \
-DNL80211_SUPPORT=OFF \
-DRESOLV_SUPPORT=OFF \
-DRTNL_SUPPORT=OFF \
-DSTRUCT_SUPPORT=ON \
-DUBUS_SUPPORT=OFF \
-DUCI_SUPPORT=OFF \
-DULOOP_SUPPORT=OFF
define Package/ucode/default
SECTION:=utils
CATEGORY:=Utilities
TITLE:=ucode - Tiny scripting and templating language
SUBMENU:=ucode
SECTION:=lang
CATEGORY:=Languages
TITLE:=Tiny scripting and templating language
endef
define Package/ucode
@@ -45,7 +58,10 @@ endef
define Package/libucode
$(Package/ucode/default)
TITLE+= - runtime library
SUBMENU:=
SECTION:=libs
CATEGORY:=Libraries
TITLE+= (library)
ABI_VERSION:=$(PKG_ABI_VERSION)
DEPENDS:=+libjson-c
endef
@@ -80,7 +96,7 @@ endef
define Package/ucode-mod-nl80211
$(Package/ucode/default)
TITLE+= (nl80211 module)
DEPENDS:=ucode +libnl-tiny +kmod-mac80211 +libubox
DEPENDS:=ucode +libnl-tiny +libubox
endef
define Package/ucode-mod-nl80211/description
@@ -117,7 +133,7 @@ define Package/ucode-mod-struct
endef
define Package/ucode-mod-struct/description
The struct plugin implemnts Python 3 compatible struct.pack/unpack functionality.
The struct plugin implements Python 3 compatible struct.pack/unpack functionality.
endef
@@ -143,6 +159,7 @@ define Package/ucode-mod-uci/description
The uci module allows templates to read and modify uci configuration.
endef
define Package/ucode-mod-uloop
$(Package/ucode/default)
TITLE+= (uloop module)
@@ -150,7 +167,8 @@ define Package/ucode-mod-uloop
endef
define Package/ucode-mod-uloop/description
The uloop module allows templates to run a main loop.
The uloop module allows ucode scripts to interact with OpenWrt uloop event
loop implementation.
endef
define Build/Prepare
@@ -220,9 +238,8 @@ define Package/ucode-mod-uloop/install
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/uloop.so $(1)/usr/lib/ucode/
endef
$(eval $(call BuildPackage,ucode))
$(eval $(call BuildPackage,libucode))
$(eval $(call BuildPackage,ucode))
$(eval $(call BuildPackage,ucode-mod-fs))
$(eval $(call BuildPackage,ucode-mod-math))
$(eval $(call BuildPackage,ucode-mod-nl80211))
@@ -232,3 +249,4 @@ $(eval $(call BuildPackage,ucode-mod-struct))
$(eval $(call BuildPackage,ucode-mod-ubus))
$(eval $(call BuildPackage,ucode-mod-uci))
$(eval $(call BuildPackage,ucode-mod-uloop))
$(eval $(call HostBuild))

View File

@@ -1,7 +1,5 @@
Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c
===================================================================
--- ucode-2022-04-07-33f1e0b0.orig/lib/nl80211.c
+++ ucode-2022-04-07-33f1e0b0/lib/nl80211.c
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -38,7 +38,7 @@ limitations under the License.
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
@@ -9,5 +7,5 @@ Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c
-#include <linux/nl80211.h>
+#include "../nl80211_copy.h"
#include <linux/ieee80211.h>
#include <libubox/uloop.h>
#include "ucode/module.h"

View File

@@ -8,20 +8,18 @@ Subject: [PATCH] fixes
lib/rtnl.c | 1 +
2 files changed, 87 insertions(+), 6 deletions(-)
Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c
===================================================================
--- ucode-2022-04-07-33f1e0b0.orig/lib/nl80211.c
+++ ucode-2022-04-07-33f1e0b0/lib/nl80211.c
@@ -51,6 +51,8 @@ limitations under the License.
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -56,6 +56,8 @@ limitations under the License.
#define NL80211_ATTR_NOT_IMPLEMENTED 0x10000
#define NL80211_CMDS_BITMAP_SIZE DIV_ROUND_UP(NL80211_CMD_MAX + 1, 32)
+#define NL80211_ATTR_NOT_IMPLEMENTED 0x10000
+
static struct {
int code;
char *msg;
@@ -263,6 +265,14 @@ static const uc_nl_nested_spec_t nl80211
@@ -277,6 +279,14 @@ static const uc_nl_nested_spec_t nl80211
}
};
@@ -36,7 +34,7 @@ Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c
static const uc_nl_nested_spec_t nl80211_mesh_params_nla = {
.headsize = 0,
.nattrs = 29,
@@ -354,6 +364,14 @@ static const uc_nl_nested_spec_t nl80211
@@ -368,6 +378,14 @@ static const uc_nl_nested_spec_t nl80211
}
};
@@ -51,7 +49,7 @@ Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c
static const uc_nl_nested_spec_t nl80211_peer_measurements_peers_req_data_ftm_nla = {
.headsize = 0,
.nattrs = 13,
@@ -503,6 +521,26 @@ static const uc_nl_nested_spec_t nl80211
@@ -517,6 +535,26 @@ static const uc_nl_nested_spec_t nl80211
}
};
@@ -78,7 +76,7 @@ Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c
static const uc_nl_nested_spec_t nl80211_wiphy_bands_freqs_nla = {
.headsize = 0,
.nattrs = 25,
@@ -544,6 +582,10 @@ static const uc_nl_nested_spec_t nl80211
@@ -558,6 +596,10 @@ static const uc_nl_nested_spec_t nl80211
}
};
@@ -89,7 +87,7 @@ Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c
static const uc_nl_nested_spec_t nl80211_wiphy_bands_iftype_data_nla = {
.headsize = 0,
.nattrs = 7,
@@ -714,6 +756,10 @@ static const uc_nl_nested_spec_t nl80211
@@ -728,6 +770,10 @@ static const uc_nl_nested_spec_t nl80211
}
};
@@ -99,4 +97,4 @@ Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c
+
static const uc_nl_nested_spec_t nl80211_sta_info_nla = {
.headsize = 0,
.nattrs = 35,
.nattrs = 40,

View File

@@ -1,13 +0,0 @@
Index: ucode-2022-04-07-7fa59ce4/lib/uloop.c
===================================================================
--- ucode-2022-04-07-7fa59ce4.orig/lib/uloop.c
+++ ucode-2022-04-07-7fa59ce4/lib/uloop.c
@@ -971,6 +971,8 @@ uc_uloop_task(uc_vm_t *vm, size_t nargs)
err_return(errno);
if (pid == 0) {
+ uloop_done();
+
patch_devnull(0, false);
patch_devnull(1, true);
patch_devnull(2, true);

View File

@@ -1,47 +0,0 @@
From 1f515b67c706a2cafae46e06b488212bbe842a2d Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Mon, 9 Jan 2023 10:31:32 +0100
Subject: [PATCH] nl80211: add support for NL80211_ATTR_MPATH_INFO
Signed-off-by: John Crispin <john@phrozen.org>
---
lib/nl80211.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/lib/nl80211.c b/lib/nl80211.c
index aa84848..0ab5c13 100644
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -776,6 +776,21 @@ static const uc_nl_nested_spec_t nl80211_survey_info_nla = {
}
};
+static const uc_nl_nested_spec_t nl80211_mpath_info_nla = {
+ .headsize = 0,
+ .nattrs = 8,
+ .attrs = {
+ { NL80211_MPATH_INFO_SN, "sn", DT_U32, 0, NULL },
+ { NL80211_MPATH_INFO_METRIC, "metric", DT_U32, 0, NULL },
+ { NL80211_MPATH_INFO_EXPTIME, "expire", DT_U32, 0, NULL },
+ { NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, "discovery_timeout", DT_U32, 0, NULL },
+ { NL80211_MPATH_INFO_DISCOVERY_RETRIES, "discovery_retries", DT_U8, 0, NULL },
+ { NL80211_MPATH_INFO_FLAGS, "flags", DT_U8, 0, NULL },
+ { NL80211_MPATH_INFO_HOP_COUNT, "hop_count", DT_U8, 0, NULL },
+ { NL80211_MPATH_INFO_PATH_CHANGE, "path_change", DT_U32, 0, NULL },
+ }
+};
+
static const uc_nl_nested_spec_t nl80211_msg = {
.headsize = 0,
.nattrs = 126,
@@ -834,6 +849,7 @@ static const uc_nl_nested_spec_t nl80211_msg = {
{ NL80211_ATTR_MGMT_SUBTYPE, "mgmt_subtype", DT_U8, 0, NULL },
{ NL80211_ATTR_MNTR_FLAGS, "mntr_flags", DT_NESTED, 0, &nl80211_mntr_flags_nla },
{ NL80211_ATTR_MPATH_NEXT_HOP, "mpath_next_hop", DT_LLADDR, 0, NULL },
+ { NL80211_ATTR_MPATH_INFO, "mpath_info", DT_NESTED, 0, &nl80211_mpath_info_nla },
{ NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR, "mu_mimo_follow_mac_addr", DT_LLADDR, 0, NULL },
{ NL80211_ATTR_NAN_FUNC, "nan_func", DT_NESTED, 0, &nl80211_nan_func_nla },
{ NL80211_ATTR_NAN_MASTER_PREF, "nan_master_pref", DT_U8, 0, NULL },
--
2.34.1

View File

@@ -1,102 +0,0 @@
From c0e413c21f7b114a70282041a0049196869dd15f Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Wed, 4 Jan 2023 14:12:43 +0100
Subject: [PATCH] include: add uc_fn_thisval()
Can be used to get rid of a layer of pointer indirection in resource type
handlers.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/ucode/lib.h | 14 +++++++++++++-
include/ucode/types.h | 1 +
types.c | 22 +++++++++++++++++++---
3 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/include/ucode/lib.h b/include/ucode/lib.h
index 0709702..74d8866 100644
--- a/include/ucode/lib.h
+++ b/include/ucode/lib.h
@@ -38,14 +38,26 @@ __hidden void uc_error_message_indent(char **msg);
__hidden uc_value_t *uc_require_library(uc_vm_t *vm, uc_value_t *nameval, bool so_only);
/* vm helper */
+static inline uc_value_t *
+_uc_fn_this_res(uc_vm_t *vm)
+{
+ return vm->callframes.entries[vm->callframes.count - 1].ctx;
+}
static inline void *
_uc_fn_this(uc_vm_t *vm, const char *expected_type)
{
- return ucv_resource_dataptr(vm->callframes.entries[vm->callframes.count - 1].ctx, expected_type);
+ return ucv_resource_dataptr(_uc_fn_this_res(vm), expected_type);
+}
+
+static inline void *
+_uc_fn_thisval(uc_vm_t *vm, const char *expected_type)
+{
+ return ucv_resource_data(_uc_fn_this_res(vm), expected_type);
}
#define uc_fn_this(...) _uc_fn_this(vm, __VA_ARGS__)
+#define uc_fn_thisval(...) _uc_fn_thisval(vm, __VA_ARGS__)
static inline uc_value_t *
_uc_fn_arg(uc_vm_t *vm, size_t nargs, size_t n)
diff --git a/include/ucode/types.h b/include/ucode/types.h
index bae2dd5..22fe9a9 100644
--- a/include/ucode/types.h
+++ b/include/ucode/types.h
@@ -392,6 +392,7 @@ uc_resource_type_t *ucv_resource_type_add(uc_vm_t *, const char *, uc_value_t *,
uc_resource_type_t *ucv_resource_type_lookup(uc_vm_t *, const char *);
uc_value_t *ucv_resource_new(uc_resource_type_t *, void *);
+void *ucv_resource_data(uc_value_t *uv, const char *);
void **ucv_resource_dataptr(uc_value_t *, const char *);
uc_value_t *ucv_regexp_new(const char *, bool, bool, bool, char **);
diff --git a/types.c b/types.c
index 8a7986b..cde2221 100644
--- a/types.c
+++ b/types.c
@@ -1096,8 +1096,8 @@ ucv_resource_new(uc_resource_type_t *type, void *data)
return &res->header;
}
-void **
-ucv_resource_dataptr(uc_value_t *uv, const char *name)
+static uc_resource_t *
+ucv_resource_check(uc_value_t *uv, const char *name)
{
uc_resource_t *res = (uc_resource_t *)uv;
@@ -1109,7 +1109,23 @@ ucv_resource_dataptr(uc_value_t *uv, const char *name)
return NULL;
}
- return &res->data;
+ return res;
+}
+
+void *
+ucv_resource_data(uc_value_t *uv, const char *name)
+{
+ uc_resource_t *res = ucv_resource_check(uv, name);
+
+ return res ? res->data : NULL;
+}
+
+void **
+ucv_resource_dataptr(uc_value_t *uv, const char *name)
+{
+ uc_resource_t *res = ucv_resource_check(uv, name);
+
+ return res ? &res->data : NULL;
}
--
2.34.1

View File

@@ -1,164 +0,0 @@
From ec167d39b803df4ebdfba0741be8d620e51cd2a7 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Tue, 17 Jan 2023 11:44:26 +0100
Subject: [PATCH] nl80211: refactor command bitmask handling
- add missing overflow check
- make array size dynamic
- set all bits if command id is not specified
- add helper function for filling command bits
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
lib/nl80211.c | 88 +++++++++++++++++++++++++++++----------------------
1 file changed, 50 insertions(+), 38 deletions(-)
diff --git a/lib/nl80211.c b/lib/nl80211.c
index d182d7a..58e49bb 100644
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -43,6 +43,8 @@ limitations under the License.
#include "ucode/module.h"
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
#define err_return(code, ...) do { set_error(code, __VA_ARGS__); return NULL; } while(0)
/* Modified downstream nl80211.h headers may disable certain unsupported
@@ -51,6 +53,8 @@ limitations under the License.
#define NL80211_ATTR_NOT_IMPLEMENTED 0x10000
+#define NL80211_CMDS_BITMAP_SIZE DIV_ROUND_UP(NL80211_CMD_MAX + 1, 32)
+
static struct {
int code;
char *msg;
@@ -2149,7 +2153,7 @@ struct waitfor_ctx {
uint8_t cmd;
uc_vm_t *vm;
uc_value_t *res;
- uint32_t cmds[8];
+ uint32_t cmds[NL80211_CMDS_BITMAP_SIZE];
};
static int
@@ -2158,28 +2162,25 @@ cb_event(struct nl_msg *msg, void *arg)
struct nlmsghdr *hdr = nlmsg_hdr(msg);
struct genlmsghdr *gnlh = nlmsg_data(hdr);
struct waitfor_ctx *s = arg;
- bool rv, match = true;
+ bool rv;
uc_value_t *o;
- if (s->cmds[0] || s->cmds[1] || s->cmds[2] || s->cmds[3] ||
- s->cmds[4] || s->cmds[5] || s->cmds[6] || s->cmds[7]) {
- match = (s->cmds[gnlh->cmd / 32] & (1 << (gnlh->cmd % 32)));
- }
+ if (gnlh->cmd > NL80211_CMD_MAX ||
+ !(s->cmds[gnlh->cmd / 32] & (1 << (gnlh->cmd % 32))))
+ return NL_SKIP;
- if (match) {
- o = ucv_object_new(s->vm);
+ o = ucv_object_new(s->vm);
- rv = uc_nl_convert_attrs(msg,
- genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0),
- 0, nl80211_msg.attrs, nl80211_msg.nattrs, s->vm, o);
+ rv = uc_nl_convert_attrs(msg,
+ genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0),
+ 0, nl80211_msg.attrs, nl80211_msg.nattrs, s->vm, o);
- if (rv)
- s->res = o;
- else
- ucv_put(o);
+ if (rv)
+ s->res = o;
+ else
+ ucv_put(o);
- s->cmd = gnlh->cmd;
- }
+ s->cmd = gnlh->cmd;
return NL_SKIP;
}
@@ -2190,6 +2191,35 @@ cb_seq(struct nl_msg *msg, void *arg)
return NL_OK;
}
+static bool
+uc_nl_fill_cmds(uint32_t *cmd_bits, uc_value_t *cmds)
+{
+ if (ucv_type(cmds) == UC_ARRAY) {
+ for (size_t i = 0; i < ucv_array_length(cmds); i++) {
+ int64_t n = ucv_int64_get(ucv_array_get(cmds, i));
+
+ if (errno || n < 0 || n > NL80211_CMD_MAX)
+ return false;
+
+ cmd_bits[n / 32] |= (1 << (n % 32));
+ }
+ }
+ else if (ucv_type(cmds) == UC_INTEGER) {
+ int64_t n = ucv_int64_get(cmds);
+
+ if (errno || n < 0 || n > 255)
+ return false;
+
+ cmd_bits[n / 32] |= (1 << (n % 32));
+ }
+ else if (!cmds)
+ memset(cmd_bits, 0xff, NL80211_CMDS_BITMAP_SIZE * sizeof(*cmd_bits));
+ else
+ return false;
+
+ return true;
+}
+
static uc_value_t *
uc_nl_waitfor(uc_vm_t *vm, size_t nargs)
{
@@ -2200,11 +2230,9 @@ uc_nl_waitfor(uc_vm_t *vm, size_t nargs)
struct waitfor_ctx ctx = { .vm = vm };
struct nl_cb *cb;
int ms = -1, err;
- int64_t n;
- size_t i;
if (timeout) {
- n = ucv_int64_get(timeout);
+ int64_t n = ucv_int64_get(timeout);
if (ucv_type(timeout) != UC_INTEGER || n < INT32_MIN || n > INT32_MAX)
err_return(NLE_INVAL, "Invalid timeout specified");
@@ -2212,24 +2240,8 @@ uc_nl_waitfor(uc_vm_t *vm, size_t nargs)
ms = (int)n;
}
- if (ucv_type(cmds) == UC_ARRAY) {
- for (i = 0; i < ucv_array_length(cmds); i++) {
- n = ucv_int64_get(ucv_array_get(cmds, i));
-
- if (n < 0 || n > 255)
- err_return(NLE_INVAL, "Invalid command ID specified");
-
- ctx.cmds[n / 32] |= (1 << (n % 32));
- }
- }
- else if (ucv_type(cmds) == UC_INTEGER) {
- n = ucv_int64_get(cmds);
-
- if (n < 0 || n > 255)
- err_return(NLE_INVAL, "Invalid command ID specified");
-
- ctx.cmds[n / 32] |= (1 << (n % 32));
- }
+ if (!uc_nl_fill_cmds(ctx.cmds, cmds))
+ err_return(NLE_INVAL, "Invalid command ID specified");
if (!nl80211_conn.evsock) {
if (!uc_nl_connect_sock(&nl80211_conn.evsock, true) ||

View File

@@ -1,358 +0,0 @@
From 6704ec0d5b2923100fda9e2cb7efead7b9836da2 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Thu, 19 Jan 2023 11:01:20 +0100
Subject: [PATCH] nl80211: add support for registering an uloop based listener
Can be used to capture nl80211 messages in an event driven program
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
CMakeLists.txt | 3 +-
lib/nl80211.c | 246 +++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 228 insertions(+), 21 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6506b1a..6d76f3a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -154,13 +154,14 @@ ENDIF()
IF(NL80211_SUPPORT)
FIND_LIBRARY(nl NAMES nl-tiny)
+ FIND_LIBRARY(ubox NAMES ubox)
FIND_PATH(nl_include_dir NAMES netlink/msg.h PATH_SUFFIXES libnl-tiny)
INCLUDE_DIRECTORIES(${nl_include_dir})
SET(LIBRARIES ${LIBRARIES} nl80211_lib)
ADD_LIBRARY(nl80211_lib MODULE lib/nl80211.c)
SET_TARGET_PROPERTIES(nl80211_lib PROPERTIES OUTPUT_NAME nl80211 PREFIX "")
TARGET_LINK_OPTIONS(nl80211_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
- TARGET_LINK_LIBRARIES(nl80211_lib ${nl})
+ TARGET_LINK_LIBRARIES(nl80211_lib ${nl} ${ubox})
ENDIF()
IF(RESOLV_SUPPORT)
diff --git a/lib/nl80211.c b/lib/nl80211.c
index 58e49bb..f3e63bb 100644
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -40,6 +40,7 @@ limitations under the License.
#include <linux/nl80211.h>
#include <linux/ieee80211.h>
+#include <libubox/uloop.h>
#include "ucode/module.h"
@@ -76,6 +77,15 @@ set_error(int errcode, const char *fmt, ...) {
}
}
+static uc_resource_type_t *listener_type;
+static uc_value_t *listener_registry;
+static uc_vm_t *listener_vm;
+
+typedef struct {
+ uint32_t cmds[NL80211_CMDS_BITMAP_SIZE];
+ size_t index;
+} uc_nl_listener_t;
+
static bool
uc_nl_parse_u32(uc_value_t *val, uint32_t *n)
{
@@ -1817,6 +1827,8 @@ static struct {
struct nl_cache *cache;
struct genl_family *nl80211;
struct genl_family *nlctrl;
+ struct uloop_fd evsock_fd;
+ struct nl_cb *evsock_cb;
} nl80211_conn;
typedef enum {
@@ -2156,29 +2168,90 @@ struct waitfor_ctx {
uint32_t cmds[NL80211_CMDS_BITMAP_SIZE];
};
+static uc_value_t *
+uc_nl_prepare_event(uc_vm_t *vm, struct nl_msg *msg)
+{
+ struct nlmsghdr *hdr = nlmsg_hdr(msg);
+ struct genlmsghdr *gnlh = nlmsg_data(hdr);
+ uc_value_t *o = ucv_object_new(vm);
+
+ if (!uc_nl_convert_attrs(msg, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), 0,
+ nl80211_msg.attrs, nl80211_msg.nattrs, vm, o)) {
+ ucv_put(o);
+ return NULL;
+ }
+
+ return o;
+}
+
+static int
+cb_listener_event(struct nl_msg *msg, void *arg)
+{
+ struct nlmsghdr *hdr = nlmsg_hdr(msg);
+ struct genlmsghdr *gnlh = nlmsg_data(hdr);
+ uc_vm_t *vm = listener_vm;
+
+ if (!nl80211_conn.evsock_fd.registered || !vm)
+ return NL_SKIP;
+
+ for (size_t i = 0; i < ucv_array_length(listener_registry); i += 2) {
+ uc_value_t *this = ucv_array_get(listener_registry, i);
+ uc_value_t *func = ucv_array_get(listener_registry, i + 1);
+ uc_nl_listener_t *l;
+ uc_value_t *o, *data;
+
+ l = ucv_resource_data(this, "nl80211.listener");
+ if (!l)
+ continue;
+
+ if (gnlh->cmd > NL80211_CMD_MAX ||
+ !(l->cmds[gnlh->cmd / 32] & (1 << (gnlh->cmd % 32))))
+ continue;
+
+ if (!ucv_is_callable(func))
+ continue;
+
+ data = uc_nl_prepare_event(vm, msg);
+ if (!data)
+ return NL_SKIP;
+
+ o = ucv_object_new(vm);
+ ucv_object_add(o, "cmd", ucv_int64_new(gnlh->cmd));
+ ucv_object_add(o, "msg", data);
+
+ uc_vm_stack_push(vm, ucv_get(this));
+ uc_vm_stack_push(vm, ucv_get(func));
+ uc_vm_stack_push(vm, o);
+
+ if (uc_vm_call(vm, true, 1) != EXCEPTION_NONE) {
+ uloop_end();
+ return NL_STOP;
+ }
+
+ ucv_put(uc_vm_stack_pop(vm));
+ }
+
+ return NL_SKIP;
+}
+
static int
cb_event(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *hdr = nlmsg_hdr(msg);
struct genlmsghdr *gnlh = nlmsg_data(hdr);
struct waitfor_ctx *s = arg;
- bool rv;
uc_value_t *o;
+ cb_listener_event(msg, arg);
+
if (gnlh->cmd > NL80211_CMD_MAX ||
!(s->cmds[gnlh->cmd / 32] & (1 << (gnlh->cmd % 32))))
return NL_SKIP;
- o = ucv_object_new(s->vm);
-
- rv = uc_nl_convert_attrs(msg,
- genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0),
- 0, nl80211_msg.attrs, nl80211_msg.nattrs, s->vm, o);
-
- if (rv)
+ o = uc_nl_prepare_event(s->vm, msg);
+ if (o)
s->res = o;
- else
- ucv_put(o);
s->cmd = gnlh->cmd;
@@ -2220,6 +2293,29 @@ uc_nl_fill_cmds(uint32_t *cmd_bits, uc_value_t *cmds)
return true;
}
+static bool
+uc_nl_evsock_init(void)
+{
+ if (nl80211_conn.evsock)
+ return true;
+
+ if (!uc_nl_connect_sock(&nl80211_conn.evsock, true))
+ return false;
+
+ if (!uc_nl_subscribe(nl80211_conn.evsock, "nl80211", "config") ||
+ !uc_nl_subscribe(nl80211_conn.evsock, "nl80211", "scan") ||
+ !uc_nl_subscribe(nl80211_conn.evsock, "nl80211", "regulatory") ||
+ !uc_nl_subscribe(nl80211_conn.evsock, "nl80211", "mlme") ||
+ !uc_nl_subscribe(nl80211_conn.evsock, "nl80211", "vendor") ||
+ !uc_nl_subscribe(nl80211_conn.evsock, "nl80211", "nan")) {
+ nl_socket_free(nl80211_conn.evsock);
+ nl80211_conn.evsock = NULL;
+ return false;
+ }
+
+ return true;
+}
+
static uc_value_t *
uc_nl_waitfor(uc_vm_t *vm, size_t nargs)
{
@@ -2243,16 +2339,8 @@ uc_nl_waitfor(uc_vm_t *vm, size_t nargs)
if (!uc_nl_fill_cmds(ctx.cmds, cmds))
err_return(NLE_INVAL, "Invalid command ID specified");
- if (!nl80211_conn.evsock) {
- if (!uc_nl_connect_sock(&nl80211_conn.evsock, true) ||
- !uc_nl_subscribe(nl80211_conn.evsock, "nl80211", "config") ||
- !uc_nl_subscribe(nl80211_conn.evsock, "nl80211", "scan") ||
- !uc_nl_subscribe(nl80211_conn.evsock, "nl80211", "regulatory") ||
- !uc_nl_subscribe(nl80211_conn.evsock, "nl80211", "mlme") ||
- !uc_nl_subscribe(nl80211_conn.evsock, "nl80211", "vendor") ||
- !uc_nl_subscribe(nl80211_conn.evsock, "nl80211", "nan"))
- return NULL;
- }
+ if (!uc_nl_evsock_init())
+ return NULL;
cb = nl_cb_alloc(NL_CB_DEFAULT);
@@ -2380,6 +2468,113 @@ uc_nl_request(uc_vm_t *vm, size_t nargs)
}
}
+static void
+uc_nl_listener_cb(struct uloop_fd *fd, unsigned int events)
+{
+ nl_recvmsgs(nl80211_conn.evsock, nl80211_conn.evsock_cb);
+}
+
+static uc_value_t *
+uc_nl_listener(uc_vm_t *vm, size_t nargs)
+{
+ struct uloop_fd *fd = &nl80211_conn.evsock_fd;
+ uc_nl_listener_t *l;
+ uc_value_t *cb_func = uc_fn_arg(0);
+ uc_value_t *cmds = uc_fn_arg(1);
+ uc_value_t *rv;
+ size_t i;
+
+ if (!ucv_is_callable(cb_func)) {
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Invalid callback");
+ return NULL;
+ }
+
+ if (!uc_nl_evsock_init())
+ return NULL;
+
+ if (!fd->registered) {
+ fd->fd = nl_socket_get_fd(nl80211_conn.evsock);
+ fd->cb = uc_nl_listener_cb;
+ uloop_fd_add(fd, ULOOP_READ);
+ }
+
+ if (!nl80211_conn.evsock_cb) {
+ struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
+
+ if (!cb)
+ err_return(NLE_NOMEM, NULL);
+
+ nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, cb_seq, NULL);
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_listener_event, NULL);
+ nl80211_conn.evsock_cb = cb;
+ }
+
+ for (i = 0; i < ucv_array_length(listener_registry); i += 2) {
+ if (!ucv_array_get(listener_registry, i))
+ break;
+ }
+
+ ucv_array_set(listener_registry, i + 1, cb_func);
+ l = xalloc(sizeof(*l));
+ l->index = i;
+ if (!uc_nl_fill_cmds(l->cmds, cmds)) {
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Invalid command ID");
+ free(l);
+ return NULL;
+ }
+
+ rv = uc_resource_new(listener_type, l);
+ ucv_array_set(listener_registry, i, rv);
+ listener_vm = vm;
+
+ return rv;
+}
+
+static void
+uc_nl_listener_free(void *arg)
+{
+ uc_nl_listener_t *l = arg;
+
+ ucv_array_set(listener_registry, l->index, NULL);
+ ucv_array_set(listener_registry, l->index + 1, NULL);
+ free(l);
+}
+
+static uc_value_t *
+uc_nl_listener_set_commands(uc_vm_t *vm, size_t nargs)
+{
+ uc_nl_listener_t *l = uc_fn_thisval("nl80211.listener");
+ uc_value_t *cmds = uc_fn_arg(0);
+
+ if (!l)
+ return NULL;
+
+ memset(l->cmds, 0, sizeof(l->cmds));
+ if (!uc_nl_fill_cmds(l->cmds, cmds))
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Invalid command ID");
+
+ return NULL;
+}
+
+static uc_value_t *
+uc_nl_listener_close(uc_vm_t *vm, size_t nargs)
+{
+ uc_nl_listener_t **lptr = uc_fn_this("nl80211.listener");
+ uc_nl_listener_t *l;
+
+ if (!lptr)
+ return NULL;
+
+ l = *lptr;
+ if (!l)
+ return NULL;
+
+ *lptr = NULL;
+ uc_nl_listener_free(l);
+
+ return NULL;
+}
+
static void
register_constants(uc_vm_t *vm, uc_value_t *scope)
@@ -2530,12 +2725,23 @@ static const uc_function_list_t global_fns[] = {
{ "error", uc_nl_error },
{ "request", uc_nl_request },
{ "waitfor", uc_nl_waitfor },
+ { "listener", uc_nl_listener },
};
+static const uc_function_list_t listener_fns[] = {
+ { "set_commands", uc_nl_listener_set_commands },
+ { "close", uc_nl_listener_close },
+};
+
void uc_module_init(uc_vm_t *vm, uc_value_t *scope)
{
uc_function_list_register(scope, global_fns);
+ listener_type = uc_type_declare(vm, "nl80211.listener", listener_fns, uc_nl_listener_free);
+ listener_registry = ucv_array_new(vm);
+
+ uc_vm_registry_set(vm, "nl80211.registry", listener_registry);
+
register_constants(vm, scope);
}

View File

@@ -1,381 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6d76f3a1b9df..3fb1f7aed964 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -143,13 +143,14 @@ ENDIF()
IF(RTNL_SUPPORT)
FIND_LIBRARY(nl NAMES nl-tiny)
+ FIND_LIBRARY(ubox NAMES ubox)
FIND_PATH(nl_include_dir NAMES netlink/msg.h PATH_SUFFIXES libnl-tiny)
INCLUDE_DIRECTORIES(${nl_include_dir})
SET(LIBRARIES ${LIBRARIES} rtnl_lib)
ADD_LIBRARY(rtnl_lib MODULE lib/rtnl.c)
SET_TARGET_PROPERTIES(rtnl_lib PROPERTIES OUTPUT_NAME rtnl PREFIX "")
TARGET_LINK_OPTIONS(rtnl_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
- TARGET_LINK_LIBRARIES(rtnl_lib ${nl})
+ TARGET_LINK_LIBRARIES(rtnl_lib ${nl} ${ubox})
ENDIF()
IF(NL80211_SUPPORT)
diff --git a/lib/rtnl.c b/lib/rtnl.c
index c72b9fdc816c..6a9144e21734 100644
--- a/lib/rtnl.c
+++ b/lib/rtnl.c
@@ -49,12 +49,19 @@ limitations under the License.
#include <linux/netconf.h>
#include <linux/ipv6.h>
+#include <libubox/uloop.h>
+
#include "ucode/module.h"
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
#define err_return(code, ...) do { set_error(code, __VA_ARGS__); return NULL; } while(0)
#define NLM_F_STRICT_CHK (1 << 15)
+#define RTNL_CMDS_BITMAP_SIZE DIV_ROUND_UP(__RTM_MAX, 32)
+#define RTNL_GRPS_BITMAP_SIZE DIV_ROUND_UP(__RTNLGRP_MAX, 32)
+
/* Can't use net/if.h for declarations as it clashes with linux/if.h
* on certain musl versions.
* Ref: https://www.openwall.com/lists/musl/2017/04/16/1 */
@@ -82,6 +89,15 @@ set_error(int errcode, const char *fmt, ...) {
}
}
+static uc_resource_type_t *listener_type;
+static uc_value_t *listener_registry;
+static uc_vm_t *listener_vm;
+
+typedef struct {
+ uint32_t cmds[RTNL_CMDS_BITMAP_SIZE];
+ size_t index;
+} uc_nl_listener_t;
+
typedef struct {
uint8_t family;
uint8_t mask;
@@ -3202,6 +3218,11 @@ uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base
static struct nl_sock *sock = NULL;
+static struct {
+ struct nl_sock *evsock;
+ struct uloop_fd evsock_fd;
+ uint32_t groups[RTNL_GRPS_BITMAP_SIZE];
+} nl_conn;
typedef enum {
STATE_UNREPLIED,
@@ -3463,6 +3484,287 @@ uc_nl_request(uc_vm_t *vm, size_t nargs)
}
}
+static const uc_nl_nested_spec_t *
+uc_nl_msg_spec(int type)
+{
+ switch (type) {
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ return &link_msg;
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ return &route_msg;
+ case RTM_NEWNEIGH:
+ case RTM_DELNEIGH:
+ return &neigh_msg;
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ return &addr_msg;
+ case RTM_NEWRULE:
+ case RTM_DELRULE:
+ return &rule_msg;
+ case RTM_NEWADDRLABEL:
+ case RTM_DELADDRLABEL:
+ return &addrlabel_msg;
+ case RTM_NEWNEIGHTBL:
+ return &neightbl_msg;
+ case RTM_NEWNETCONF:
+ case RTM_DELNETCONF:
+ return &netconf_msg;
+ default:
+ return NULL;
+ }
+}
+
+static void
+uc_nl_prepare_event(uc_vm_t *vm, uc_value_t *dest, struct nl_msg *msg)
+{
+ struct nlmsghdr *hdr = nlmsg_hdr(msg);
+ const uc_nl_nested_spec_t *spec;
+ const uc_nl_attr_spec_t *attrs = NULL;
+ size_t nattrs = 0, headsize = 0;
+ uc_value_t *o;
+
+ spec = uc_nl_msg_spec(hdr->nlmsg_type);
+ if (spec) {
+ attrs = spec->attrs;
+ nattrs = spec->nattrs;
+ headsize = spec->headsize;
+ }
+
+ o = ucv_object_new(vm);
+ if (!uc_nl_convert_attrs(msg, nlmsg_attrdata(hdr, 0),
+ nlmsg_attrlen(hdr, 0), headsize, attrs, nattrs, vm, o)) {
+ ucv_put(o);
+ return;
+ }
+
+ ucv_object_add(dest, "msg", o);
+ if (headsize)
+ ucv_object_add(dest, "head", ucv_string_new_length(NLMSG_DATA(hdr), headsize));
+}
+
+static bool
+uc_nl_fill_cmds(uint32_t *cmd_bits, uc_value_t *cmds)
+{
+ if (ucv_type(cmds) == UC_ARRAY) {
+ for (size_t i = 0; i < ucv_array_length(cmds); i++) {
+ int64_t n = ucv_int64_get(ucv_array_get(cmds, i));
+
+ if (errno || n < 0 || n >= __RTM_MAX)
+ return false;
+
+ cmd_bits[n / 32] |= (1 << (n % 32));
+ }
+ }
+ else if (ucv_type(cmds) == UC_INTEGER) {
+ int64_t n = ucv_int64_get(cmds);
+
+ if (errno || n < 0 || n > 255)
+ return false;
+
+ cmd_bits[n / 32] |= (1 << (n % 32));
+ }
+ else if (!cmds)
+ memset(cmd_bits, 0xff, RTNL_CMDS_BITMAP_SIZE * sizeof(*cmd_bits));
+ else
+ return false;
+
+ return true;
+}
+
+static int
+cb_listener_event(struct nl_msg *msg, void *arg)
+{
+ struct nlmsghdr *hdr = nlmsg_hdr(msg);
+ uc_vm_t *vm = listener_vm;
+ int cmd = hdr->nlmsg_type;
+
+ if (!nl_conn.evsock_fd.registered || !vm)
+ return NL_SKIP;
+
+ for (size_t i = 0; i < ucv_array_length(listener_registry); i += 2) {
+ uc_value_t *this = ucv_array_get(listener_registry, i);
+ uc_value_t *func = ucv_array_get(listener_registry, i + 1);
+ uc_nl_listener_t *l;
+ uc_value_t *o;
+
+ l = ucv_resource_data(this, "rtnl.listener");
+ if (!l)
+ continue;
+
+ if (cmd > __RTM_MAX || !(l->cmds[cmd / 32] & (1 << (cmd % 32))))
+ continue;
+
+ if (!ucv_is_callable(func))
+ continue;
+
+ o = ucv_object_new(vm);
+ uc_nl_prepare_event(vm, o, msg);
+ ucv_object_add(o, "cmd", ucv_int64_new(cmd));
+
+ uc_vm_stack_push(vm, ucv_get(this));
+ uc_vm_stack_push(vm, ucv_get(func));
+ uc_vm_stack_push(vm, o);
+
+ if (uc_vm_call(vm, true, 1) != EXCEPTION_NONE) {
+ uloop_end();
+ return NL_STOP;
+ }
+
+ ucv_put(uc_vm_stack_pop(vm));
+ }
+
+ return NL_SKIP;
+}
+
+static void
+uc_nl_listener_cb(struct uloop_fd *fd, unsigned int events)
+{
+ nl_recvmsgs_default(nl_conn.evsock);
+}
+
+static void
+uc_nl_add_group(unsigned int idx)
+{
+ if (idx >= __RTNLGRP_MAX)
+ return;
+
+ if (nl_conn.groups[idx / 32] & (1 << (idx % 32)))
+ return;
+
+ nl_conn.groups[idx / 32] |= (1 << (idx % 32));
+ nl_socket_add_membership(nl_conn.evsock, idx);
+}
+
+static bool
+uc_nl_evsock_init(void)
+{
+ struct uloop_fd *fd = &nl_conn.evsock_fd;
+ struct nl_sock *sock;
+
+ if (nl_conn.evsock)
+ return true;
+
+ sock = nl_socket_alloc();
+
+ if (nl_connect(sock, NETLINK_ROUTE))
+ goto free;
+
+ fd->fd = nl_socket_get_fd(sock);
+ fd->cb = uc_nl_listener_cb;
+ uloop_fd_add(fd, ULOOP_READ);
+
+ nl_socket_set_buffer_size(sock, 65535, 0);
+ nl_socket_disable_seq_check(sock);
+ nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, cb_listener_event, NULL);
+
+ nl_conn.evsock = sock;
+
+ return true;
+
+free:
+ nl_socket_free(sock);
+ return false;
+}
+
+static uc_value_t *
+uc_nl_listener(uc_vm_t *vm, size_t nargs)
+{
+ uc_nl_listener_t *l;
+ uc_value_t *cb_func = uc_fn_arg(0);
+ uc_value_t *cmds = uc_fn_arg(1);
+ uc_value_t *groups = uc_fn_arg(2);
+ uc_value_t *rv;
+ size_t i;
+
+ if (!ucv_is_callable(cb_func)) {
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Invalid callback");
+ return NULL;
+ }
+
+ if (!uc_nl_evsock_init())
+ return NULL;
+
+ if (ucv_type(groups) == UC_ARRAY) {
+ for (i = 0; i < ucv_array_length(groups); i++) {
+ int64_t n = ucv_int64_get(ucv_array_get(groups, i));
+
+ if (errno || n < 0 || n >= __RTNLGRP_MAX)
+ err_return(NLE_INVAL, NULL);
+
+ uc_nl_add_group(n);
+ }
+ } else {
+ uc_nl_add_group(RTNLGRP_LINK);
+ }
+
+ for (i = 0; i < ucv_array_length(listener_registry); i += 2) {
+ if (!ucv_array_get(listener_registry, i))
+ break;
+ }
+
+ ucv_array_set(listener_registry, i + 1, cb_func);
+ l = xalloc(sizeof(*l));
+ l->index = i;
+ if (!uc_nl_fill_cmds(l->cmds, cmds)) {
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Invalid command ID");
+ free(l);
+ return NULL;
+ }
+
+ rv = uc_resource_new(listener_type, l);
+ ucv_array_set(listener_registry, i, rv);
+ listener_vm = vm;
+
+ return rv;
+}
+
+static void
+uc_nl_listener_free(void *arg)
+{
+ uc_nl_listener_t *l = arg;
+
+ ucv_array_set(listener_registry, l->index, NULL);
+ ucv_array_set(listener_registry, l->index + 1, NULL);
+ free(l);
+}
+
+static uc_value_t *
+uc_nl_listener_set_commands(uc_vm_t *vm, size_t nargs)
+{
+ uc_nl_listener_t *l = uc_fn_thisval("rtnl.listener");
+ uc_value_t *cmds = uc_fn_arg(0);
+
+ if (!l)
+ return NULL;
+
+ memset(l->cmds, 0, sizeof(l->cmds));
+ if (!uc_nl_fill_cmds(l->cmds, cmds))
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Invalid command ID");
+
+ return NULL;
+}
+
+static uc_value_t *
+uc_nl_listener_close(uc_vm_t *vm, size_t nargs)
+{
+ uc_nl_listener_t **lptr = uc_fn_this("rtnl.listener");
+ uc_nl_listener_t *l;
+
+ if (!lptr)
+ return NULL;
+
+ l = *lptr;
+ if (!l)
+ return NULL;
+
+ *lptr = NULL;
+ uc_nl_listener_free(l);
+
+ return NULL;
+}
+
static void
register_constants(uc_vm_t *vm, uc_value_t *scope)
@@ -3833,12 +4135,20 @@ register_constants(uc_vm_t *vm, uc_value_t *scope)
static const uc_function_list_t global_fns[] = {
{ "error", uc_nl_error },
{ "request", uc_nl_request },
+ { "listener", uc_nl_listener },
};
+static const uc_function_list_t listener_fns[] = {
+ { "set_commands", uc_nl_listener_set_commands },
+ { "close", uc_nl_listener_close },
+};
void uc_module_init(uc_vm_t *vm, uc_value_t *scope)
{
uc_function_list_register(scope, global_fns);
+ listener_type = uc_type_declare(vm, "rtnl.listener", listener_fns, uc_nl_listener_free);
+ listener_registry = ucv_array_new(vm);
+
register_constants(vm, scope);
}

View File

@@ -1,48 +0,0 @@
--- a/lib/rtnl.c
+++ b/lib/rtnl.c
@@ -3704,7 +3704,7 @@ uc_nl_listener(uc_vm_t *vm, size_t nargs
break;
}
- ucv_array_set(listener_registry, i + 1, cb_func);
+ ucv_array_set(listener_registry, i + 1, ucv_get(cb_func));
l = xalloc(sizeof(*l));
l->index = i;
if (!uc_nl_fill_cmds(l->cmds, cmds)) {
@@ -3714,7 +3714,7 @@ uc_nl_listener(uc_vm_t *vm, size_t nargs
}
rv = uc_resource_new(listener_type, l);
- ucv_array_set(listener_registry, i, rv);
+ ucv_array_set(listener_registry, i, ucv_get(rv));
listener_vm = vm;
return rv;
@@ -4150,5 +4150,7 @@ void uc_module_init(uc_vm_t *vm, uc_valu
listener_type = uc_type_declare(vm, "rtnl.listener", listener_fns, uc_nl_listener_free);
listener_registry = ucv_array_new(vm);
+ uc_vm_registry_set(vm, "rtnl.registry", listener_registry);
+
register_constants(vm, scope);
}
--- a/lib/nl80211.c
+++ b/lib/nl80211.c
@@ -2560,7 +2560,7 @@ uc_nl_listener(uc_vm_t *vm, size_t nargs
break;
}
- ucv_array_set(listener_registry, i + 1, cb_func);
+ ucv_array_set(listener_registry, i + 1, ucv_get(cb_func));
l = xalloc(sizeof(*l));
l->index = i;
if (!uc_nl_fill_cmds(l->cmds, cmds)) {
@@ -2570,7 +2570,7 @@ uc_nl_listener(uc_vm_t *vm, size_t nargs
}
rv = uc_resource_new(listener_type, l);
- ucv_array_set(listener_registry, i, rv);
+ ucv_array_set(listener_registry, i, ucv_get(rv));
listener_vm = vm;
return rv;

View File

@@ -1,58 +0,0 @@
From d2cc00310dba05de233ff18d3c830c8638f9bfdf Mon Sep 17 00:00:00 2001
From: Jo-Philipp Wich <jo@mein.io>
Date: Wed, 23 Nov 2022 12:48:07 +0100
Subject: [PATCH] uci: auto-load package in `ctx.foreach()` and
`ctx.get_first()`
Functions that use `uci_lookup_ptr()` internally, such as `ctx.get()`,
`ctx.set()` or `ctx.delete()`, implicitly load the given configuration
name while the higher level functions `ctx.foreach()` or `ctx.get_first()`
do not.
This behaviour violates the principle of least surprise and might lead to
non-deterministic program behavior as the outcome of these functions
depends on prior uci operations performed on the cursor.
Fix this issue by invoking `uci_load()` internally in case the given
uci package name cannot be found in the cursor's package cache.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
---
lib/uci.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/lib/uci.c b/lib/uci.c
index 50cc050e..b88dabd1 100644
--- a/lib/uci.c
+++ b/lib/uci.c
@@ -346,8 +346,8 @@ uc_uci_get_first(uc_vm_t *vm, size_t nargs)
break;
}
- if (!p)
- err_return(UCI_ERR_NOTFOUND);
+ if (!p && uci_load(*c, ucv_string_get(conf), &p))
+ err_return((*c)->err);
uci_foreach_element(&p->sections, e) {
sc = uci_to_section(e);
@@ -917,8 +917,8 @@ uc_uci_foreach(uc_vm_t *vm, size_t nargs)
break;
}
- if (!p)
- err_return(UCI_ERR_NOTFOUND);
+ if (!p && uci_load(*c, ucv_string_get(conf), &p))
+ err_return((*c)->err);
uci_foreach_element_safe(&p->sections, tmp, e) {
sc = uci_to_section(e);
@@ -946,8 +946,6 @@ uc_uci_foreach(uc_vm_t *vm, size_t nargs)
break;
}
- /* XXX: rethrow */
-
return ucv_boolean_new(ret);
}