Skip to content

Conversation

@hauke
Copy link

@hauke hauke commented Aug 15, 2022

The _init() function collides with a _init() function in crti.o.
This results in the following error in OpenWrt:
arc-openwrt-linux-gnu/bin/ld: libxt_coova.o: in function `_init':
/lib/gcc/arc-openwrt-linux-gnu/11.3.0/crti.o:(.init+0x4): first defined here
collect2: error: ld returned 1 exit status
make[7]: *** [Makefile:22: libxt_coova.so] Error 1

Fix this by suing a constructor attribute instead. This function will
still be called after the shared library was loaded.

Fixes: #553
Signed-off-by: Hauke Mehrtens hauke@hauke-m.de

The _init() function collides with a _init() function in crti.o.
This results in the following error in OpenWrt:
arc-openwrt-linux-gnu/bin/ld: libxt_coova.o: in function `_init':
/lib/gcc/arc-openwrt-linux-gnu/11.3.0/crti.o:(.init+0x4): first defined here
collect2: error: ld returned 1 exit status
make[7]: *** [Makefile:22: libxt_coova.so] Error 1

Fix this by suing a constructor attribute instead. This function will
still be called after the shared library was loaded.

Fixes: coova#553
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
@sevan
Copy link
Member

sevan commented Aug 19, 2025

I was wondering if the correct fix for this is actually to change the function signature from void _init(void) to static void _init(void). The Writing Netfilter modules book has the following to say:

"Each library must register to the running ip6tables (or iptables) program by calling xtables_register_match. The _init function is called when the module is loaded by iptables. For more information about it, see dlopen(3). As a tiny implementation detail, note that _init is actually defined as a macro for iptables, and the keyword will be replaced by appropriate logic to wire it up with iptables, as we cannot strictly use _init, because the Glibc CRT (common runtime) stubs that will be linked into shared libraries, already do.
void _init(void) { xtables_register_match(&ipaddr_mt_reg); }
When iptables is built, this will expand to:
void __attribute__((constructor)) libxt_ipaddr_init(void)
so you may not use the name libxt_ipaddr_init for other functions, or you will get an unfortunate compile error.
In case you use the Xtables-addons framework, just directly write
static void _init(void)
i. e. with the static keyword and without the extra prototype above it, because modules are always compiled as shared library objects (.so) in Xtables-addons, so no symbols need to be globally visible."

Unfortunately, I don't have OpenWRT setup to test, can you try making the following change and report back?

--- a/src/linux/libxt_coova.c
+++ b/src/linux/libxt_coova.c
@@ -126,7 +126,7 @@ static struct xtables_match coova_mt6_reg = {
        .extra_opts    = coova_opts,
 };
 
-void _init(void)
+static void _init(void)
 {
        xtables_register_match(&coova_mt_reg);
        xtables_register_match(&coova_mt6_reg);

@sevan
Copy link
Member

sevan commented Aug 20, 2025

@hauke @teslamint @neheb ^^

@neheb
Copy link
Contributor

neheb commented Aug 20, 2025

I see

json/json_object.c:static void json_object_init(void) __attribute__ ((constructor));

No idea if both are desired to be honest.

Having it static would probably result in an unused function warning.

edit: ah disregard that.

edit2: I tried the static version. No unused function warning.

@neheb
Copy link
Contributor

neheb commented Aug 20, 2025

I was wrong

  3 libxt_coova.c:129:13: warning: '_init' defined but not used [-Wunused-function]
  2   129 | static void _init(void)
  1       |             ^~~~~

edit: xtables.h has all the logic hidden behind a define. Which is probably why it doesn't work:

#ifdef XTABLES_INTERNAL

#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
#       ifdef _INIT
#               undef _init
#               define _init _INIT
#       endif
        extern void init_extensions(void);
        extern void init_extensions4(void);
        extern void init_extensions6(void);
        extern void init_extensionsa(void);
        extern void init_extensionsb(void);
#else
#       define _init __attribute__((constructor)) _INIT
#       define EMPTY_FUNC_DEF(x) static inline void x(void) {}
        EMPTY_FUNC_DEF(init_extensions)
        EMPTY_FUNC_DEF(init_extensions4)
        EMPTY_FUNC_DEF(init_extensions6)
        EMPTY_FUNC_DEF(init_extensionsa)
        EMPTY_FUNC_DEF(init_extensionsb)
#       undef EMPTY_FUNC_DEF
#endif

extern void _init(void);

#endif /* XTABLES_INTERNAL */

@Neustradamus
Copy link

Dear @coova team, @sevan, @jobezic,

Have you progressed on this PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Coova-chilli compile error using the latest OpenWrt Master branch (July 31 2022)

4 participants