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

netfilter: conntrack: handle ->destroy hook via nat_ops instead

The nat module already exposes a few functions to the conntrack core.
Move the nat extension destroy hook to it.

After this, no conntrack extension needs a destroy hook.
'struct nf_ct_ext_type' and the register/unregister api can be removed
in a followup patch.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Florian Westphal and committed by
Pablo Neira Ayuso
1bc91a5d 5f31edc0

+16 -36
+1
include/linux/netfilter.h
··· 379 379 unsigned int (*manip_pkt)(struct sk_buff *skb, struct nf_conn *ct, 380 380 enum nf_nat_manip_type mtype, 381 381 enum ip_conntrack_dir dir); 382 + void (*remove_nat_bysrc)(struct nf_conn *ct); 382 383 }; 383 384 384 385 extern const struct nf_nat_hook __rcu *nf_nat_hook;
-3
include/net/netfilter/nf_conntrack_extend.h
··· 79 79 void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp); 80 80 81 81 struct nf_ct_ext_type { 82 - /* Destroys relationships (can be NULL). */ 83 - void (*destroy)(struct nf_conn *ct); 84 - 85 82 enum nf_ct_ext_id id; 86 83 }; 87 84
+12 -2
net/netfilter/nf_conntrack_core.c
··· 594 594 595 595 void nf_ct_tmpl_free(struct nf_conn *tmpl) 596 596 { 597 - nf_ct_ext_destroy(tmpl); 597 + kfree(tmpl->ext); 598 598 599 599 if (ARCH_KMALLOC_MINALIGN <= NFCT_INFOMASK) 600 600 kfree((char *)tmpl - tmpl->proto.tmpl_padto); ··· 1597 1597 */ 1598 1598 WARN_ON(refcount_read(&ct->ct_general.use) != 0); 1599 1599 1600 - nf_ct_ext_destroy(ct); 1600 + if (ct->status & IPS_SRC_NAT_DONE) { 1601 + const struct nf_nat_hook *nat_hook; 1602 + 1603 + rcu_read_lock(); 1604 + nat_hook = rcu_dereference(nf_nat_hook); 1605 + if (nat_hook) 1606 + nat_hook->remove_nat_bysrc(ct); 1607 + rcu_read_unlock(); 1608 + } 1609 + 1610 + kfree(ct->ext); 1601 1611 kmem_cache_free(nf_conntrack_cachep, ct); 1602 1612 cnet = nf_ct_pernet(net); 1603 1613
-21
net/netfilter/nf_conntrack_extend.c
··· 89 89 ; 90 90 } 91 91 92 - void nf_ct_ext_destroy(struct nf_conn *ct) 93 - { 94 - unsigned int i; 95 - struct nf_ct_ext_type *t; 96 - 97 - for (i = 0; i < NF_CT_EXT_NUM; i++) { 98 - rcu_read_lock(); 99 - t = rcu_dereference(nf_ct_ext_types[i]); 100 - 101 - /* Here the nf_ct_ext_type might have been unregisterd. 102 - * I.e., it has responsible to cleanup private 103 - * area in all conntracks when it is unregisterd. 104 - */ 105 - if (t && t->destroy) 106 - t->destroy(ct); 107 - rcu_read_unlock(); 108 - } 109 - 110 - kfree(ct->ext); 111 - } 112 - 113 92 void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) 114 93 { 115 94 unsigned int newlen, newoff, oldlen, alloc;
+3 -10
net/netfilter/nf_nat_core.c
··· 838 838 return i->status & IPS_NAT_MASK ? 1 : 0; 839 839 } 840 840 841 - static void __nf_nat_cleanup_conntrack(struct nf_conn *ct) 841 + static void nf_nat_cleanup_conntrack(struct nf_conn *ct) 842 842 { 843 843 unsigned int h; 844 844 ··· 860 860 * will delete entry from already-freed table. 861 861 */ 862 862 if (test_and_clear_bit(IPS_SRC_NAT_DONE_BIT, &ct->status)) 863 - __nf_nat_cleanup_conntrack(ct); 863 + nf_nat_cleanup_conntrack(ct); 864 864 865 865 /* don't delete conntrack. Although that would make things a lot 866 866 * simpler, we'd end up flushing all conntracks on nat rmmod. ··· 868 868 return 0; 869 869 } 870 870 871 - /* No one using conntrack by the time this called. */ 872 - static void nf_nat_cleanup_conntrack(struct nf_conn *ct) 873 - { 874 - if (ct->status & IPS_SRC_NAT_DONE) 875 - __nf_nat_cleanup_conntrack(ct); 876 - } 877 - 878 871 static struct nf_ct_ext_type nat_extend __read_mostly = { 879 - .destroy = nf_nat_cleanup_conntrack, 880 872 .id = NF_CT_EXT_NAT, 881 873 }; 882 874 ··· 1163 1171 .decode_session = __nf_nat_decode_session, 1164 1172 #endif 1165 1173 .manip_pkt = nf_nat_manip_pkt, 1174 + .remove_nat_bysrc = nf_nat_cleanup_conntrack, 1166 1175 }; 1167 1176 1168 1177 static int __init nf_nat_init(void)