mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-31 02:17:58 +00:00 
			
		
		
		
	ucode: update to the latest version
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
		 Felix Fietkau
					Felix Fietkau
				
			
				
					committed by
					
						 John Crispin
						John Crispin
					
				
			
			
				
	
			
			
			 John Crispin
						John Crispin
					
				
			
						parent
						
							bccdb175b0
						
					
				
				
					commit
					323dc65770
				
			| @@ -12,24 +12,37 @@ PKG_RELEASE:=1 | |||||||
|  |  | ||||||
| PKG_SOURCE_PROTO:=git | PKG_SOURCE_PROTO:=git | ||||||
| PKG_SOURCE_URL=https://github.com/jow-/ucode.git | PKG_SOURCE_URL=https://github.com/jow-/ucode.git | ||||||
| PKG_MIRROR_HASH:=413a08ee63c30c44d6f0a5de14b1c84787f9bd1fe8b125c8e4956aa2884cc933 | PKG_SOURCE_DATE:=2023-06-06 | ||||||
| #PKG_MIRROR_HASH:=98303ef9d5fa7eca04042792abaf8a2e66082237a23a89a7f5e72e4409714a72 | PKG_SOURCE_VERSION:=c7d84aae09691a99ae3db427c0b2463732ef84f4 | ||||||
| PKG_SOURCE_DATE:=2022-04-07 | PKG_MIRROR_HASH:=38826ae70d886d1d7ada3fc6591ac807169aa28107f60f7f2e617520083525fb | ||||||
| PKG_SOURCE_VERSION:=7fa59ce44b9347528b0e4e44ebcfb04a08479f3f |  | ||||||
| PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io> | PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io> | ||||||
| PKG_LICENSE:=ISC | PKG_LICENSE:=ISC | ||||||
|  |  | ||||||
| PKG_ABI_VERSION:=20220322 | PKG_ABI_VERSION:=20220812 | ||||||
|  |  | ||||||
| include $(INCLUDE_DIR)/package.mk | include $(INCLUDE_DIR)/package.mk | ||||||
|  | include $(INCLUDE_DIR)/host-build.mk | ||||||
| include $(INCLUDE_DIR)/cmake.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 | define Package/ucode/default | ||||||
|   SECTION:=utils |   SUBMENU:=ucode | ||||||
|   CATEGORY:=Utilities |   SECTION:=lang | ||||||
|   TITLE:=ucode - Tiny scripting and templating language |   CATEGORY:=Languages | ||||||
|  |   TITLE:=Tiny scripting and templating language | ||||||
| endef | endef | ||||||
|  |  | ||||||
| define Package/ucode | define Package/ucode | ||||||
| @@ -45,7 +58,10 @@ endef | |||||||
|  |  | ||||||
| define Package/libucode | define Package/libucode | ||||||
|   $(Package/ucode/default) |   $(Package/ucode/default) | ||||||
|   TITLE+= - runtime library |   SUBMENU:= | ||||||
|  |   SECTION:=libs | ||||||
|  |   CATEGORY:=Libraries | ||||||
|  |   TITLE+= (library) | ||||||
|   ABI_VERSION:=$(PKG_ABI_VERSION) |   ABI_VERSION:=$(PKG_ABI_VERSION) | ||||||
|   DEPENDS:=+libjson-c |   DEPENDS:=+libjson-c | ||||||
| endef | endef | ||||||
| @@ -80,7 +96,7 @@ endef | |||||||
| define Package/ucode-mod-nl80211 | define Package/ucode-mod-nl80211 | ||||||
|   $(Package/ucode/default) |   $(Package/ucode/default) | ||||||
|   TITLE+= (nl80211 module) |   TITLE+= (nl80211 module) | ||||||
|   DEPENDS:=ucode +libnl-tiny +kmod-mac80211 +libubox |   DEPENDS:=ucode +libnl-tiny +libubox | ||||||
| endef | endef | ||||||
|  |  | ||||||
| define Package/ucode-mod-nl80211/description | define Package/ucode-mod-nl80211/description | ||||||
| @@ -117,7 +133,7 @@ define Package/ucode-mod-struct | |||||||
| endef | endef | ||||||
|  |  | ||||||
| define Package/ucode-mod-struct/description | 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 | endef | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -143,6 +159,7 @@ define Package/ucode-mod-uci/description | |||||||
|  The uci module allows templates to read and modify uci configuration. |  The uci module allows templates to read and modify uci configuration. | ||||||
| endef | endef | ||||||
|  |  | ||||||
|  |  | ||||||
| define Package/ucode-mod-uloop | define Package/ucode-mod-uloop | ||||||
|   $(Package/ucode/default) |   $(Package/ucode/default) | ||||||
|   TITLE+= (uloop module) |   TITLE+= (uloop module) | ||||||
| @@ -150,7 +167,8 @@ define Package/ucode-mod-uloop | |||||||
| endef | endef | ||||||
|  |  | ||||||
| define Package/ucode-mod-uloop/description | 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 | endef | ||||||
|  |  | ||||||
| define Build/Prepare | 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/ | 	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/ucode/uloop.so $(1)/usr/lib/ucode/ | ||||||
| endef | endef | ||||||
|  |  | ||||||
|  |  | ||||||
| $(eval $(call BuildPackage,ucode)) |  | ||||||
| $(eval $(call BuildPackage,libucode)) | $(eval $(call BuildPackage,libucode)) | ||||||
|  | $(eval $(call BuildPackage,ucode)) | ||||||
| $(eval $(call BuildPackage,ucode-mod-fs)) | $(eval $(call BuildPackage,ucode-mod-fs)) | ||||||
| $(eval $(call BuildPackage,ucode-mod-math)) | $(eval $(call BuildPackage,ucode-mod-math)) | ||||||
| $(eval $(call BuildPackage,ucode-mod-nl80211)) | $(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-ubus)) | ||||||
| $(eval $(call BuildPackage,ucode-mod-uci)) | $(eval $(call BuildPackage,ucode-mod-uci)) | ||||||
| $(eval $(call BuildPackage,ucode-mod-uloop)) | $(eval $(call BuildPackage,ucode-mod-uloop)) | ||||||
|  | $(eval $(call HostBuild)) | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c | --- a/lib/nl80211.c | ||||||
| =================================================================== | +++ b/lib/nl80211.c | ||||||
| --- ucode-2022-04-07-33f1e0b0.orig/lib/nl80211.c |  | ||||||
| +++ ucode-2022-04-07-33f1e0b0/lib/nl80211.c |  | ||||||
| @@ -38,7 +38,7 @@ limitations under the License. | @@ -38,7 +38,7 @@ limitations under the License. | ||||||
|  #include <netlink/genl/family.h> |  #include <netlink/genl/family.h> | ||||||
|  #include <netlink/genl/ctrl.h> |  #include <netlink/genl/ctrl.h> | ||||||
| @@ -9,5 +7,5 @@ Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c | |||||||
| -#include <linux/nl80211.h> | -#include <linux/nl80211.h> | ||||||
| +#include "../nl80211_copy.h" | +#include "../nl80211_copy.h" | ||||||
|  #include <linux/ieee80211.h> |  #include <linux/ieee80211.h> | ||||||
|  |  #include <libubox/uloop.h> | ||||||
|   |   | ||||||
|  #include "ucode/module.h" |  | ||||||
|   | |||||||
| @@ -8,20 +8,18 @@ Subject: [PATCH] fixes | |||||||
|  lib/rtnl.c    |  1 + |  lib/rtnl.c    |  1 + | ||||||
|  2 files changed, 87 insertions(+), 6 deletions(-) |  2 files changed, 87 insertions(+), 6 deletions(-) | ||||||
|  |  | ||||||
| Index: ucode-2022-04-07-33f1e0b0/lib/nl80211.c | --- a/lib/nl80211.c | ||||||
| =================================================================== | +++ b/lib/nl80211.c | ||||||
| --- ucode-2022-04-07-33f1e0b0.orig/lib/nl80211.c | @@ -56,6 +56,8 @@ limitations under the License. | ||||||
| +++ ucode-2022-04-07-33f1e0b0/lib/nl80211.c |  | ||||||
| @@ -51,6 +51,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 | +#define NL80211_ATTR_NOT_IMPLEMENTED 0x10000 | ||||||
| + | + | ||||||
|  static struct { |  static struct { | ||||||
|  	int code; |  	int code; | ||||||
|  	char *msg; |  	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 = { |  static const uc_nl_nested_spec_t nl80211_mesh_params_nla = { | ||||||
|  	.headsize = 0, |  	.headsize = 0, | ||||||
|  	.nattrs = 29, |  	.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 = { |  static const uc_nl_nested_spec_t nl80211_peer_measurements_peers_req_data_ftm_nla = { | ||||||
|  	.headsize = 0, |  	.headsize = 0, | ||||||
|  	.nattrs = 13, |  	.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 = { |  static const uc_nl_nested_spec_t nl80211_wiphy_bands_freqs_nla = { | ||||||
|  	.headsize = 0, |  	.headsize = 0, | ||||||
|  	.nattrs = 25, |  	.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 = { |  static const uc_nl_nested_spec_t nl80211_wiphy_bands_iftype_data_nla = { | ||||||
|  	.headsize = 0, |  	.headsize = 0, | ||||||
|  	.nattrs = 7, |  	.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 = { |  static const uc_nl_nested_spec_t nl80211_sta_info_nla = { | ||||||
|  	.headsize = 0, |  	.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