blob: bc7fb85d40021e26bfc6c188163971c0ef4c7898 [file] [log] [blame]
Patrick McHardy96518512013-10-14 11:00:02 +02001/*
2 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Development of this code funded by Astaro AG (http://www.astaro.com/)
9 */
10
11#include <linux/module.h>
12#include <linux/init.h>
13#include <linux/list.h>
14#include <linux/rculist.h>
15#include <linux/skbuff.h>
16#include <linux/netlink.h>
17#include <linux/netfilter.h>
18#include <linux/netfilter/nfnetlink.h>
19#include <linux/netfilter/nf_tables.h>
20#include <net/netfilter/nf_tables_core.h>
21#include <net/netfilter/nf_tables.h>
22
23#define NFT_JUMP_STACK_SIZE 16
24
25unsigned int nft_do_chain(const struct nf_hook_ops *ops,
26 struct sk_buff *skb,
27 const struct net_device *in,
28 const struct net_device *out,
29 int (*okfn)(struct sk_buff *))
30{
31 const struct nft_chain *chain = ops->priv;
32 const struct nft_rule *rule;
33 const struct nft_expr *expr, *last;
34 struct nft_data data[NFT_REG_MAX + 1];
35 const struct nft_pktinfo pkt = {
36 .skb = skb,
37 .in = in,
38 .out = out,
39 .hooknum = ops->hooknum,
40 };
41 unsigned int stackptr = 0;
42 struct {
43 const struct nft_chain *chain;
44 const struct nft_rule *rule;
45 } jumpstack[NFT_JUMP_STACK_SIZE];
46
47do_chain:
48 rule = list_entry(&chain->rules, struct nft_rule, list);
49next_rule:
50 data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
51 list_for_each_entry_continue_rcu(rule, &chain->rules, list) {
52 nft_rule_for_each_expr(expr, last, rule) {
53 expr->ops->eval(expr, data, &pkt);
54 if (data[NFT_REG_VERDICT].verdict != NFT_CONTINUE)
55 break;
56 }
57
58 switch (data[NFT_REG_VERDICT].verdict) {
59 case NFT_BREAK:
60 data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
61 /* fall through */
62 case NFT_CONTINUE:
63 continue;
64 }
65 break;
66 }
67
68 switch (data[NFT_REG_VERDICT].verdict) {
69 case NF_ACCEPT:
70 case NF_DROP:
71 case NF_QUEUE:
72 return data[NFT_REG_VERDICT].verdict;
73 case NFT_JUMP:
74 BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE);
75 jumpstack[stackptr].chain = chain;
76 jumpstack[stackptr].rule = rule;
77 stackptr++;
78 /* fall through */
79 case NFT_GOTO:
80 chain = data[NFT_REG_VERDICT].chain;
81 goto do_chain;
82 case NFT_RETURN:
83 case NFT_CONTINUE:
84 break;
85 default:
86 WARN_ON(1);
87 }
88
89 if (stackptr > 0) {
90 stackptr--;
91 chain = jumpstack[stackptr].chain;
92 rule = jumpstack[stackptr].rule;
93 goto next_rule;
94 }
95
96 return NF_ACCEPT;
97}
98EXPORT_SYMBOL_GPL(nft_do_chain);
99
100int __init nf_tables_core_module_init(void)
101{
102 int err;
103
104 err = nft_immediate_module_init();
105 if (err < 0)
106 goto err1;
107
108 err = nft_cmp_module_init();
109 if (err < 0)
110 goto err2;
111
112 err = nft_lookup_module_init();
113 if (err < 0)
114 goto err3;
115
116 err = nft_bitwise_module_init();
117 if (err < 0)
118 goto err4;
119
120 err = nft_byteorder_module_init();
121 if (err < 0)
122 goto err5;
123
124 err = nft_payload_module_init();
125 if (err < 0)
126 goto err6;
127
128 return 0;
129
130err6:
131 nft_byteorder_module_exit();
132err5:
133 nft_bitwise_module_exit();
134err4:
135 nft_lookup_module_exit();
136err3:
137 nft_cmp_module_exit();
138err2:
139 nft_immediate_module_exit();
140err1:
141 return err;
142}
143
144void nf_tables_core_module_exit(void)
145{
146 nft_payload_module_exit();
147 nft_byteorder_module_exit();
148 nft_bitwise_module_exit();
149 nft_lookup_module_exit();
150 nft_cmp_module_exit();
151 nft_immediate_module_exit();
152}