aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2014-04-03 19:38:51 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2014-05-19 06:06:10 -0400
commitb380e5c733b9f18a6a3ebb97963b6dd037339bc0 (patch)
tree3ca18c36eb7acae13894029ceb350eaee1e90d26 /net/netfilter
parent37082f930bb59ef6fd45e7bae6c45858af2cd972 (diff)
netfilter: nf_tables: add message type to transactions
The patch adds message type to the transaction to simplify the commit the and abort routines. Yet another step forward in the generalisation of the transaction infrastructure. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/nf_tables_api.c74
1 files changed, 43 insertions, 31 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 17df4b807f84..34aa3d507542 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -105,7 +105,8 @@ static void nft_ctx_init(struct nft_ctx *ctx,
105 ctx->nla = nla; 105 ctx->nla = nla;
106} 106}
107 107
108static struct nft_trans *nft_trans_alloc(struct nft_ctx *ctx, u32 size) 108static struct nft_trans *nft_trans_alloc(struct nft_ctx *ctx, int msg_type,
109 u32 size)
109{ 110{
110 struct nft_trans *trans; 111 struct nft_trans *trans;
111 112
@@ -113,6 +114,7 @@ static struct nft_trans *nft_trans_alloc(struct nft_ctx *ctx, u32 size)
113 if (trans == NULL) 114 if (trans == NULL)
114 return NULL; 115 return NULL;
115 116
117 trans->msg_type = msg_type;
116 trans->ctx = *ctx; 118 trans->ctx = *ctx;
117 119
118 return trans; 120 return trans;
@@ -1576,12 +1578,12 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
1576 kfree(rule); 1578 kfree(rule);
1577} 1579}
1578 1580
1579static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx, 1581static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx, int msg_type,
1580 struct nft_rule *rule) 1582 struct nft_rule *rule)
1581{ 1583{
1582 struct nft_trans *trans; 1584 struct nft_trans *trans;
1583 1585
1584 trans = nft_trans_alloc(ctx, sizeof(struct nft_trans_rule)); 1586 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_rule));
1585 if (trans == NULL) 1587 if (trans == NULL)
1586 return NULL; 1588 return NULL;
1587 1589
@@ -1703,7 +1705,8 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
1703 1705
1704 if (nlh->nlmsg_flags & NLM_F_REPLACE) { 1706 if (nlh->nlmsg_flags & NLM_F_REPLACE) {
1705 if (nft_rule_is_active_next(net, old_rule)) { 1707 if (nft_rule_is_active_next(net, old_rule)) {
1706 trans = nft_trans_rule_add(&ctx, old_rule); 1708 trans = nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE,
1709 old_rule);
1707 if (trans == NULL) { 1710 if (trans == NULL) {
1708 err = -ENOMEM; 1711 err = -ENOMEM;
1709 goto err2; 1712 goto err2;
@@ -1726,7 +1729,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
1726 list_add_rcu(&rule->list, &chain->rules); 1729 list_add_rcu(&rule->list, &chain->rules);
1727 } 1730 }
1728 1731
1729 if (nft_trans_rule_add(&ctx, rule) == NULL) { 1732 if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
1730 err = -ENOMEM; 1733 err = -ENOMEM;
1731 goto err3; 1734 goto err3;
1732 } 1735 }
@@ -1754,7 +1757,7 @@ nf_tables_delrule_one(struct nft_ctx *ctx, struct nft_rule *rule)
1754{ 1757{
1755 /* You cannot delete the same rule twice */ 1758 /* You cannot delete the same rule twice */
1756 if (nft_rule_is_active_next(ctx->net, rule)) { 1759 if (nft_rule_is_active_next(ctx->net, rule)) {
1757 if (nft_trans_rule_add(ctx, rule) == NULL) 1760 if (nft_trans_rule_add(ctx, NFT_MSG_DELRULE, rule) == NULL)
1758 return -ENOMEM; 1761 return -ENOMEM;
1759 nft_rule_disactivate_next(ctx->net, rule); 1762 nft_rule_disactivate_next(ctx->net, rule);
1760 return 0; 1763 return 0;
@@ -3114,28 +3117,26 @@ static int nf_tables_commit(struct sk_buff *skb)
3114 synchronize_rcu(); 3117 synchronize_rcu();
3115 3118
3116 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { 3119 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
3117 /* This rule was inactive in the past and just became active. 3120 switch (trans->msg_type) {
3118 * Clear the next bit of the genmask since its meaning has 3121 case NFT_MSG_NEWRULE:
3119 * changed, now it is the future. 3122 nft_rule_clear(trans->ctx.net, nft_trans_rule(trans));
3120 */ 3123 nf_tables_rule_notify(trans->ctx.skb, trans->ctx.nlh,
3121 if (nft_rule_is_active(net, nft_trans_rule(trans))) {
3122 nft_rule_clear(net, nft_trans_rule(trans));
3123 nf_tables_rule_notify(skb, trans->ctx.nlh,
3124 trans->ctx.table, 3124 trans->ctx.table,
3125 trans->ctx.chain, 3125 trans->ctx.chain,
3126 nft_trans_rule(trans), 3126 nft_trans_rule(trans),
3127 NFT_MSG_NEWRULE, 0, 3127 NFT_MSG_NEWRULE, 0,
3128 trans->ctx.afi->family); 3128 trans->ctx.afi->family);
3129 nft_trans_destroy(trans); 3129 nft_trans_destroy(trans);
3130 continue; 3130 break;
3131 case NFT_MSG_DELRULE:
3132 list_del_rcu(&nft_trans_rule(trans)->list);
3133 nf_tables_rule_notify(trans->ctx.skb, trans->ctx.nlh,
3134 trans->ctx.table,
3135 trans->ctx.chain,
3136 nft_trans_rule(trans), NFT_MSG_DELRULE, 0,
3137 trans->ctx.afi->family);
3138 break;
3131 } 3139 }
3132
3133 /* This rule is in the past, get rid of it */
3134 list_del_rcu(&nft_trans_rule(trans)->list);
3135 nf_tables_rule_notify(skb, trans->ctx.nlh,
3136 trans->ctx.table, trans->ctx.chain,
3137 nft_trans_rule(trans), NFT_MSG_DELRULE,
3138 0, trans->ctx.afi->family);
3139 } 3140 }
3140 3141
3141 /* Make sure we don't see any packet traversing old rules */ 3142 /* Make sure we don't see any packet traversing old rules */
@@ -3143,8 +3144,13 @@ static int nf_tables_commit(struct sk_buff *skb)
3143 3144
3144 /* Now we can safely release unused old rules */ 3145 /* Now we can safely release unused old rules */
3145 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { 3146 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
3146 nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans)); 3147 switch (trans->msg_type) {
3147 nft_trans_destroy(trans); 3148 case NFT_MSG_DELRULE:
3149 nf_tables_rule_destroy(&trans->ctx,
3150 nft_trans_rule(trans));
3151 nft_trans_destroy(trans);
3152 break;
3153 }
3148 } 3154 }
3149 3155
3150 return 0; 3156 return 0;
@@ -3156,22 +3162,28 @@ static int nf_tables_abort(struct sk_buff *skb)
3156 struct nft_trans *trans, *next; 3162 struct nft_trans *trans, *next;
3157 3163
3158 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { 3164 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
3159 if (!nft_rule_is_active_next(net, nft_trans_rule(trans))) { 3165 switch (trans->msg_type) {
3160 nft_rule_clear(net, nft_trans_rule(trans)); 3166 case NFT_MSG_NEWRULE:
3167 list_del_rcu(&nft_trans_rule(trans)->list);
3168 break;
3169 case NFT_MSG_DELRULE:
3170 nft_rule_clear(trans->ctx.net, nft_trans_rule(trans));
3161 nft_trans_destroy(trans); 3171 nft_trans_destroy(trans);
3162 continue; 3172 break;
3163 } 3173 }
3164
3165 /* This rule is inactive, get rid of it */
3166 list_del_rcu(&nft_trans_rule(trans)->list);
3167 } 3174 }
3168 3175
3169 /* Make sure we don't see any packet accessing aborted rules */ 3176 /* Make sure we don't see any packet accessing aborted rules */
3170 synchronize_rcu(); 3177 synchronize_rcu();
3171 3178
3172 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { 3179 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
3173 nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans)); 3180 switch (trans->msg_type) {
3174 nft_trans_destroy(trans); 3181 case NFT_MSG_NEWRULE:
3182 nf_tables_rule_destroy(&trans->ctx,
3183 nft_trans_rule(trans));
3184 nft_trans_destroy(trans);
3185 break;
3186 }
3175 } 3187 }
3176 3188
3177 return 0; 3189 return 0;