Branch data Line data Source code
1 : : /*
2 : : * Rusty Russell (C)2000 -- This code is GPL.
3 : : * Patrick McHardy (c) 2006-2012
4 : : */
5 : :
6 : : #include <linux/kernel.h>
7 : : #include <linux/slab.h>
8 : : #include <linux/init.h>
9 : : #include <linux/module.h>
10 : : #include <linux/proc_fs.h>
11 : : #include <linux/skbuff.h>
12 : : #include <linux/netfilter.h>
13 : : #include <linux/seq_file.h>
14 : : #include <linux/rcupdate.h>
15 : : #include <net/protocol.h>
16 : : #include <net/netfilter/nf_queue.h>
17 : : #include <net/dst.h>
18 : :
19 : : #include "nf_internals.h"
20 : :
21 : : /*
22 : : * Hook for nfnetlink_queue to register its queue handler.
23 : : * We do this so that most of the NFQUEUE code can be modular.
24 : : *
25 : : * Once the queue is registered it must reinject all packets it
26 : : * receives, no matter what.
27 : : */
28 : : static const struct nf_queue_handler __rcu *queue_handler __read_mostly;
29 : :
30 : : /* return EBUSY when somebody else is registered, return EEXIST if the
31 : : * same handler is registered, return 0 in case of success. */
32 : 0 : void nf_register_queue_handler(const struct nf_queue_handler *qh)
33 : : {
34 : : /* should never happen, we only have one queueing backend in kernel */
35 [ # # ]: 0 : WARN_ON(rcu_access_pointer(queue_handler));
36 : 0 : rcu_assign_pointer(queue_handler, qh);
37 : 0 : }
38 : : EXPORT_SYMBOL(nf_register_queue_handler);
39 : :
40 : : /* The caller must flush their queue before this */
41 : 0 : void nf_unregister_queue_handler(void)
42 : : {
43 : 0 : RCU_INIT_POINTER(queue_handler, NULL);
44 : : synchronize_rcu();
45 : 0 : }
46 : : EXPORT_SYMBOL(nf_unregister_queue_handler);
47 : :
48 : 0 : void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
49 : : {
50 : : /* Release those devices we held, or Alexey will kill me. */
51 [ # # ]: 0 : if (entry->indev)
52 : : dev_put(entry->indev);
53 [ # # ]: 0 : if (entry->outdev)
54 : : dev_put(entry->outdev);
55 : : #ifdef CONFIG_BRIDGE_NETFILTER
56 [ # # ]: 0 : if (entry->skb->nf_bridge) {
57 : : struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge;
58 : :
59 [ # # ]: 0 : if (nf_bridge->physindev)
60 : : dev_put(nf_bridge->physindev);
61 [ # # ]: 0 : if (nf_bridge->physoutdev)
62 : : dev_put(nf_bridge->physoutdev);
63 : : }
64 : : #endif
65 : : /* Drop reference to owner of hook which queued us. */
66 : 0 : module_put(entry->elem->owner);
67 : 0 : }
68 : : EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
69 : :
70 : : /* Bump dev refs so they don't vanish while packet is out */
71 : 0 : bool nf_queue_entry_get_refs(struct nf_queue_entry *entry)
72 : : {
73 [ # # ]: 0 : if (!try_module_get(entry->elem->owner))
74 : : return false;
75 : :
76 [ # # ]: 0 : if (entry->indev)
77 : : dev_hold(entry->indev);
78 [ # # ]: 0 : if (entry->outdev)
79 : : dev_hold(entry->outdev);
80 : : #ifdef CONFIG_BRIDGE_NETFILTER
81 [ # # ]: 0 : if (entry->skb->nf_bridge) {
82 : : struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge;
83 : : struct net_device *physdev;
84 : :
85 : 0 : physdev = nf_bridge->physindev;
86 [ # # ]: 0 : if (physdev)
87 : : dev_hold(physdev);
88 : 0 : physdev = nf_bridge->physoutdev;
89 [ # # ]: 0 : if (physdev)
90 : : dev_hold(physdev);
91 : : }
92 : : #endif
93 : :
94 : : return true;
95 : : }
96 : : EXPORT_SYMBOL_GPL(nf_queue_entry_get_refs);
97 : :
98 : : /*
99 : : * Any packet that leaves via this function must come back
100 : : * through nf_reinject().
101 : : */
102 : 0 : int nf_queue(struct sk_buff *skb,
103 : : struct nf_hook_ops *elem,
104 : : u_int8_t pf, unsigned int hook,
105 : : struct net_device *indev,
106 : : struct net_device *outdev,
107 : : int (*okfn)(struct sk_buff *),
108 : : unsigned int queuenum)
109 : : {
110 : : int status = -ENOENT;
111 : : struct nf_queue_entry *entry = NULL;
112 : : const struct nf_afinfo *afinfo;
113 : : const struct nf_queue_handler *qh;
114 : :
115 : : /* QUEUE == DROP if no one is waiting, to be safe. */
116 : : rcu_read_lock();
117 : :
118 : 0 : qh = rcu_dereference(queue_handler);
119 [ # # ]: 0 : if (!qh) {
120 : : status = -ESRCH;
121 : : goto err_unlock;
122 : : }
123 : :
124 : : afinfo = nf_get_afinfo(pf);
125 [ # # ]: 0 : if (!afinfo)
126 : : goto err_unlock;
127 : :
128 : 0 : entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC);
129 [ # # ]: 0 : if (!entry) {
130 : : status = -ENOMEM;
131 : : goto err_unlock;
132 : : }
133 : :
134 : 0 : *entry = (struct nf_queue_entry) {
135 : : .skb = skb,
136 : : .elem = elem,
137 : : .pf = pf,
138 : : .hook = hook,
139 : : .indev = indev,
140 : : .outdev = outdev,
141 : : .okfn = okfn,
142 : 0 : .size = sizeof(*entry) + afinfo->route_key_size,
143 : : };
144 : :
145 [ # # ]: 0 : if (!nf_queue_entry_get_refs(entry)) {
146 : : status = -ECANCELED;
147 : : goto err_unlock;
148 : : }
149 : : skb_dst_force(skb);
150 : 0 : afinfo->saveroute(skb, entry);
151 : 0 : status = qh->outfn(entry, queuenum);
152 : :
153 : : rcu_read_unlock();
154 : :
155 [ # # ]: 0 : if (status < 0) {
156 : 0 : nf_queue_entry_release_refs(entry);
157 : 0 : goto err;
158 : : }
159 : :
160 : : return 0;
161 : :
162 : : err_unlock:
163 : : rcu_read_unlock();
164 : : err:
165 : 0 : kfree(entry);
166 : 0 : return status;
167 : : }
168 : :
169 : 0 : void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
170 : : {
171 : 0 : struct sk_buff *skb = entry->skb;
172 : 0 : struct nf_hook_ops *elem = entry->elem;
173 : : const struct nf_afinfo *afinfo;
174 : : int err;
175 : :
176 : : rcu_read_lock();
177 : :
178 : 0 : nf_queue_entry_release_refs(entry);
179 : :
180 : : /* Continue traversal iff userspace said ok... */
181 [ # # ]: 0 : if (verdict == NF_REPEAT) {
182 : 0 : elem = list_entry(elem->list.prev, struct nf_hook_ops, list);
183 : : verdict = NF_ACCEPT;
184 : : }
185 : :
186 [ # # ]: 0 : if (verdict == NF_ACCEPT) {
187 : 0 : afinfo = nf_get_afinfo(entry->pf);
188 [ # # ][ # # ]: 0 : if (!afinfo || afinfo->reroute(skb, entry) < 0)
189 : : verdict = NF_DROP;
190 : : }
191 : :
192 [ # # ]: 0 : if (verdict == NF_ACCEPT) {
193 : : next_hook:
194 : 0 : verdict = nf_iterate(&nf_hooks[entry->pf][entry->hook],
195 : : skb, entry->hook,
196 : 0 : entry->indev, entry->outdev, &elem,
197 : : entry->okfn, INT_MIN);
198 : : }
199 : :
200 [ # # # # ]: 0 : switch (verdict & NF_VERDICT_MASK) {
201 : : case NF_ACCEPT:
202 : : case NF_STOP:
203 : : local_bh_disable();
204 : 0 : entry->okfn(skb);
205 : : local_bh_enable();
206 : : break;
207 : : case NF_QUEUE:
208 : 0 : err = nf_queue(skb, elem, entry->pf, entry->hook,
209 : : entry->indev, entry->outdev, entry->okfn,
210 : : verdict >> NF_VERDICT_QBITS);
211 [ # # ]: 0 : if (err < 0) {
212 [ # # ]: 0 : if (err == -ECANCELED)
213 : : goto next_hook;
214 [ # # ][ # # ]: 0 : if (err == -ESRCH &&
215 : 0 : (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
216 : : goto next_hook;
217 : 0 : kfree_skb(skb);
218 : : }
219 : : break;
220 : : case NF_STOLEN:
221 : : break;
222 : : default:
223 : 0 : kfree_skb(skb);
224 : : }
225 : : rcu_read_unlock();
226 : 0 : kfree(entry);
227 : 0 : }
228 : : EXPORT_SYMBOL(nf_reinject);
|