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.
Unified · Split
| @@ -379,6 +379,7 @@ struct nf_nat_hook { · 378 unmodified lines | ||
| 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; |
| @@ -79,9 +79,6 @@ void nf_ct_ext_destroy(struct nf_conn *ct); · 78 unmodified lines | ||
| 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 | |
| @@ -594,7 +594,7 @@ EXPORT_SYMBOL_GPL(nf_ct_tmpl_alloc); · 593 unmodified lines | ||
| 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,7 +1597,17 @@ void nf_conntrack_free(struct nf_conn *ct) · 996 unmodified lines | ||
| 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 | |
| @@ -89,27 +89,6 @@ static __always_inline unsigned int total_extension_size(void) · 88 unmodified lines | ||
| 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; |
| @@ -838,7 +838,7 @@ static int nf_nat_proto_remove(struct nf_conn *i, void *data) · 837 unmodified lines | ||
| 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,7 +860,7 @@ static int nf_nat_proto_clean(struct nf_conn *ct, void *data) · 15 unmodified lines | ||
| 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,15 +868,7 @@ static int nf_nat_proto_clean(struct nf_conn *ct, void *data) · 1 unmodified line | ||
| 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 | |
| @@ -1171,6 +1163,7 @@ static const struct nf_nat_hook nat_hook = { · 288 unmodified lines | ||
| 1171 | 1163 | .decode_session = __nf_nat_decode_session, |
| 1172 | 1164 | #endif |
| 1173 | 1165 | .manip_pkt = nf_nat_manip_pkt, |
| 1166 | + .remove_nat_bysrc = nf_nat_cleanup_conntrack, | |
| 1174 | 1167 | }; |
| 1175 | 1168 | |
| 1176 | 1169 | static int __init nf_nat_init(void) |