mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 01:22:25 +00:00
ucode: update to the latest version
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
committed by
John Crispin
parent
bccdb175b0
commit
323dc65770
@@ -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))
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) ||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user