Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: defrag: Add glue hooks for enabling/disabling defrag

We want to be able to enable/disable IP packet defrag from core
bpf/netfilter code. In other words, execute code from core that could
possibly be built as a module.

To help avoid symbol resolution errors, use glue hooks that the modules
will register callbacks with during module init.

Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
Reviewed-by: Florian Westphal <fw@strlen.de>
Link: https://lore.kernel.org/r/f6a8824052441b72afe5285acedbd634bd3384c1.1689970773.git.dxu@dxuuu.xyz
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Daniel Xu and committed by
Alexei Starovoitov
9abddac5 ee932bf9

+43 -1
+10
include/linux/netfilter.h
··· 11 11 #include <linux/wait.h> 12 12 #include <linux/list.h> 13 13 #include <linux/static_key.h> 14 + #include <linux/module.h> 14 15 #include <linux/netfilter_defs.h> 15 16 #include <linux/netdevice.h> 16 17 #include <linux/sockptr.h> ··· 481 480 enum ip_conntrack_info ctinfo, s32 off); 482 481 }; 483 482 extern const struct nfnl_ct_hook __rcu *nfnl_ct_hook; 483 + 484 + struct nf_defrag_hook { 485 + struct module *owner; 486 + int (*enable)(struct net *net); 487 + void (*disable)(struct net *net); 488 + }; 489 + 490 + extern const struct nf_defrag_hook __rcu *nf_defrag_v4_hook; 491 + extern const struct nf_defrag_hook __rcu *nf_defrag_v6_hook; 484 492 485 493 /* 486 494 * nf_skb_duplicated - TEE target has sent a packet
+16 -1
net/ipv4/netfilter/nf_defrag_ipv4.c
··· 7 7 #include <linux/ip.h> 8 8 #include <linux/netfilter.h> 9 9 #include <linux/module.h> 10 + #include <linux/rcupdate.h> 10 11 #include <linux/skbuff.h> 11 12 #include <net/netns/generic.h> 12 13 #include <net/route.h> ··· 114 113 } 115 114 } 116 115 116 + static const struct nf_defrag_hook defrag_hook = { 117 + .owner = THIS_MODULE, 118 + .enable = nf_defrag_ipv4_enable, 119 + .disable = nf_defrag_ipv4_disable, 120 + }; 121 + 117 122 static struct pernet_operations defrag4_net_ops = { 118 123 .exit = defrag4_net_exit, 119 124 }; 120 125 121 126 static int __init nf_defrag_init(void) 122 127 { 123 - return register_pernet_subsys(&defrag4_net_ops); 128 + int err; 129 + 130 + err = register_pernet_subsys(&defrag4_net_ops); 131 + if (err) 132 + return err; 133 + 134 + rcu_assign_pointer(nf_defrag_v4_hook, &defrag_hook); 135 + return err; 124 136 } 125 137 126 138 static void __exit nf_defrag_fini(void) 127 139 { 140 + rcu_assign_pointer(nf_defrag_v4_hook, NULL); 128 141 unregister_pernet_subsys(&defrag4_net_ops); 129 142 } 130 143
+11
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
··· 10 10 #include <linux/module.h> 11 11 #include <linux/skbuff.h> 12 12 #include <linux/icmp.h> 13 + #include <linux/rcupdate.h> 13 14 #include <linux/sysctl.h> 14 15 #include <net/ipv6_frag.h> 15 16 ··· 97 96 } 98 97 } 99 98 99 + static const struct nf_defrag_hook defrag_hook = { 100 + .owner = THIS_MODULE, 101 + .enable = nf_defrag_ipv6_enable, 102 + .disable = nf_defrag_ipv6_disable, 103 + }; 104 + 100 105 static struct pernet_operations defrag6_net_ops = { 101 106 .exit = defrag6_net_exit, 102 107 }; ··· 121 114 pr_err("nf_defrag_ipv6: can't register pernet ops\n"); 122 115 goto cleanup_frag6; 123 116 } 117 + 118 + rcu_assign_pointer(nf_defrag_v6_hook, &defrag_hook); 119 + 124 120 return ret; 125 121 126 122 cleanup_frag6: ··· 134 124 135 125 static void __exit nf_defrag_fini(void) 136 126 { 127 + rcu_assign_pointer(nf_defrag_v6_hook, NULL); 137 128 unregister_pernet_subsys(&defrag6_net_ops); 138 129 nf_ct_frag6_cleanup(); 139 130 }
+6
net/netfilter/core.c
··· 680 680 const struct nf_ct_hook __rcu *nf_ct_hook __read_mostly; 681 681 EXPORT_SYMBOL_GPL(nf_ct_hook); 682 682 683 + const struct nf_defrag_hook __rcu *nf_defrag_v4_hook __read_mostly; 684 + EXPORT_SYMBOL_GPL(nf_defrag_v4_hook); 685 + 686 + const struct nf_defrag_hook __rcu *nf_defrag_v6_hook __read_mostly; 687 + EXPORT_SYMBOL_GPL(nf_defrag_v6_hook); 688 + 683 689 #if IS_ENABLED(CONFIG_NF_CONNTRACK) 684 690 u8 nf_ctnetlink_has_listener; 685 691 EXPORT_SYMBOL_GPL(nf_ctnetlink_has_listener);