Search code examples
clinux-kernelnetfilter

Error "assignment from incompatible pointer type" when creating a Netfilter kernel module


I'm implementing a "mini firewall" and use the filter function with the signature shown below:

unsigned int minifw_inbound_filter(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in,
                                const struct net_device *out, int (*okfn)(struct sk_buff *));

When I added the netfilter kernel module:

static struct           nf_hook_ops nfho_in;

nt init_rule_match_module(void) {
nfho_in.hook        = minifw_inbound_filter;        // filter for inbound packets
nfho_in.hooknum     = NF_INET_LOCAL_IN;             // netfilter hook for local machine bounded ipv4 packets
nfho_in.pf          = PF_INET;
nfho_in.priority    = NF_IP_PRI_FIRST;              // we set its priority higher than other hooks
nf_register_hook(&nfho_in);

I tried to compile my module and got a compilation error:

error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
     nfho_in.hook  = minifw_inbound_filter;  // filter for inbound packets

What I'm doing wrong?


Solution

  • The hook function's type declaration changes depending on what kernel you're compiling against. That pattern looks to be from the 2.6 kernel.

    The current function signature looks like:

    unsigned int nf_hookfn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state); 
    

    It's likely you're referencing old sample code for this - you should try to find a newer example more aligned with the kernel you are compiling against.

    However, as Paul R mentions in the comments to the question, if you want to harden the code so that it can compile against multiple releases of the linux kernel, you can use the solution suggested in this answer, which wraps it based on the kernel/RHEL environment you're building against.

    The problem is that the netfilter hook function signature changed at least three times since 2.6 - in the 3.13 kernel timeframe, in the 4.1 kernel timeframe and again in the 4.4 kernel timeframe, all changing the signature.