Merge tag 'at91-5.2-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux...
[linux-2.6-microblaze.git] / net / sched / act_nat.c
1 /*
2  * Stateless NAT actions
3  *
4  * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; either version 2 of the License, or (at your option)
9  * any later version.
10  */
11
12 #include <linux/errno.h>
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/netfilter.h>
17 #include <linux/rtnetlink.h>
18 #include <linux/skbuff.h>
19 #include <linux/slab.h>
20 #include <linux/spinlock.h>
21 #include <linux/string.h>
22 #include <linux/tc_act/tc_nat.h>
23 #include <net/act_api.h>
24 #include <net/pkt_cls.h>
25 #include <net/icmp.h>
26 #include <net/ip.h>
27 #include <net/netlink.h>
28 #include <net/tc_act/tc_nat.h>
29 #include <net/tcp.h>
30 #include <net/udp.h>
31
32
33 static unsigned int nat_net_id;
34 static struct tc_action_ops act_nat_ops;
35
36 static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
37         [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) },
38 };
39
40 static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
41                         struct tc_action **a, int ovr, int bind,
42                         bool rtnl_held, struct tcf_proto *tp,
43                         struct netlink_ext_ack *extack)
44 {
45         struct tc_action_net *tn = net_generic(net, nat_net_id);
46         struct nlattr *tb[TCA_NAT_MAX + 1];
47         struct tcf_chain *goto_ch = NULL;
48         struct tc_nat *parm;
49         int ret = 0, err;
50         struct tcf_nat *p;
51
52         if (nla == NULL)
53                 return -EINVAL;
54
55         err = nla_parse_nested_deprecated(tb, TCA_NAT_MAX, nla, nat_policy,
56                                           NULL);
57         if (err < 0)
58                 return err;
59
60         if (tb[TCA_NAT_PARMS] == NULL)
61                 return -EINVAL;
62         parm = nla_data(tb[TCA_NAT_PARMS]);
63
64         err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
65         if (!err) {
66                 ret = tcf_idr_create(tn, parm->index, est, a,
67                                      &act_nat_ops, bind, false);
68                 if (ret) {
69                         tcf_idr_cleanup(tn, parm->index);
70                         return ret;
71                 }
72                 ret = ACT_P_CREATED;
73         } else if (err > 0) {
74                 if (bind)
75                         return 0;
76                 if (!ovr) {
77                         tcf_idr_release(*a, bind);
78                         return -EEXIST;
79                 }
80         } else {
81                 return err;
82         }
83         err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
84         if (err < 0)
85                 goto release_idr;
86         p = to_tcf_nat(*a);
87
88         spin_lock_bh(&p->tcf_lock);
89         p->old_addr = parm->old_addr;
90         p->new_addr = parm->new_addr;
91         p->mask = parm->mask;
92         p->flags = parm->flags;
93
94         goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
95         spin_unlock_bh(&p->tcf_lock);
96         if (goto_ch)
97                 tcf_chain_put_by_act(goto_ch);
98
99         if (ret == ACT_P_CREATED)
100                 tcf_idr_insert(tn, *a);
101
102         return ret;
103 release_idr:
104         tcf_idr_release(*a, bind);
105         return err;
106 }
107
108 static int tcf_nat_act(struct sk_buff *skb, const struct tc_action *a,
109                        struct tcf_result *res)
110 {
111         struct tcf_nat *p = to_tcf_nat(a);
112         struct iphdr *iph;
113         __be32 old_addr;
114         __be32 new_addr;
115         __be32 mask;
116         __be32 addr;
117         int egress;
118         int action;
119         int ihl;
120         int noff;
121
122         spin_lock(&p->tcf_lock);
123
124         tcf_lastuse_update(&p->tcf_tm);
125         old_addr = p->old_addr;
126         new_addr = p->new_addr;
127         mask = p->mask;
128         egress = p->flags & TCA_NAT_FLAG_EGRESS;
129         action = p->tcf_action;
130
131         bstats_update(&p->tcf_bstats, skb);
132
133         spin_unlock(&p->tcf_lock);
134
135         if (unlikely(action == TC_ACT_SHOT))
136                 goto drop;
137
138         noff = skb_network_offset(skb);
139         if (!pskb_may_pull(skb, sizeof(*iph) + noff))
140                 goto drop;
141
142         iph = ip_hdr(skb);
143
144         if (egress)
145                 addr = iph->saddr;
146         else
147                 addr = iph->daddr;
148
149         if (!((old_addr ^ addr) & mask)) {
150                 if (skb_try_make_writable(skb, sizeof(*iph) + noff))
151                         goto drop;
152
153                 new_addr &= mask;
154                 new_addr |= addr & ~mask;
155
156                 /* Rewrite IP header */
157                 iph = ip_hdr(skb);
158                 if (egress)
159                         iph->saddr = new_addr;
160                 else
161                         iph->daddr = new_addr;
162
163                 csum_replace4(&iph->check, addr, new_addr);
164         } else if ((iph->frag_off & htons(IP_OFFSET)) ||
165                    iph->protocol != IPPROTO_ICMP) {
166                 goto out;
167         }
168
169         ihl = iph->ihl * 4;
170
171         /* It would be nice to share code with stateful NAT. */
172         switch (iph->frag_off & htons(IP_OFFSET) ? 0 : iph->protocol) {
173         case IPPROTO_TCP:
174         {
175                 struct tcphdr *tcph;
176
177                 if (!pskb_may_pull(skb, ihl + sizeof(*tcph) + noff) ||
178                     skb_try_make_writable(skb, ihl + sizeof(*tcph) + noff))
179                         goto drop;
180
181                 tcph = (void *)(skb_network_header(skb) + ihl);
182                 inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr,
183                                          true);
184                 break;
185         }
186         case IPPROTO_UDP:
187         {
188                 struct udphdr *udph;
189
190                 if (!pskb_may_pull(skb, ihl + sizeof(*udph) + noff) ||
191                     skb_try_make_writable(skb, ihl + sizeof(*udph) + noff))
192                         goto drop;
193
194                 udph = (void *)(skb_network_header(skb) + ihl);
195                 if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) {
196                         inet_proto_csum_replace4(&udph->check, skb, addr,
197                                                  new_addr, true);
198                         if (!udph->check)
199                                 udph->check = CSUM_MANGLED_0;
200                 }
201                 break;
202         }
203         case IPPROTO_ICMP:
204         {
205                 struct icmphdr *icmph;
206
207                 if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + noff))
208                         goto drop;
209
210                 icmph = (void *)(skb_network_header(skb) + ihl);
211
212                 if ((icmph->type != ICMP_DEST_UNREACH) &&
213                     (icmph->type != ICMP_TIME_EXCEEDED) &&
214                     (icmph->type != ICMP_PARAMETERPROB))
215                         break;
216
217                 if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph) +
218                                         noff))
219                         goto drop;
220
221                 icmph = (void *)(skb_network_header(skb) + ihl);
222                 iph = (void *)(icmph + 1);
223                 if (egress)
224                         addr = iph->daddr;
225                 else
226                         addr = iph->saddr;
227
228                 if ((old_addr ^ addr) & mask)
229                         break;
230
231                 if (skb_try_make_writable(skb, ihl + sizeof(*icmph) +
232                                           sizeof(*iph) + noff))
233                         goto drop;
234
235                 icmph = (void *)(skb_network_header(skb) + ihl);
236                 iph = (void *)(icmph + 1);
237
238                 new_addr &= mask;
239                 new_addr |= addr & ~mask;
240
241                 /* XXX Fix up the inner checksums. */
242                 if (egress)
243                         iph->daddr = new_addr;
244                 else
245                         iph->saddr = new_addr;
246
247                 inet_proto_csum_replace4(&icmph->checksum, skb, addr, new_addr,
248                                          false);
249                 break;
250         }
251         default:
252                 break;
253         }
254
255 out:
256         return action;
257
258 drop:
259         spin_lock(&p->tcf_lock);
260         p->tcf_qstats.drops++;
261         spin_unlock(&p->tcf_lock);
262         return TC_ACT_SHOT;
263 }
264
265 static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
266                         int bind, int ref)
267 {
268         unsigned char *b = skb_tail_pointer(skb);
269         struct tcf_nat *p = to_tcf_nat(a);
270         struct tc_nat opt = {
271                 .index    = p->tcf_index,
272                 .refcnt   = refcount_read(&p->tcf_refcnt) - ref,
273                 .bindcnt  = atomic_read(&p->tcf_bindcnt) - bind,
274         };
275         struct tcf_t t;
276
277         spin_lock_bh(&p->tcf_lock);
278         opt.old_addr = p->old_addr;
279         opt.new_addr = p->new_addr;
280         opt.mask = p->mask;
281         opt.flags = p->flags;
282         opt.action = p->tcf_action;
283
284         if (nla_put(skb, TCA_NAT_PARMS, sizeof(opt), &opt))
285                 goto nla_put_failure;
286
287         tcf_tm_dump(&t, &p->tcf_tm);
288         if (nla_put_64bit(skb, TCA_NAT_TM, sizeof(t), &t, TCA_NAT_PAD))
289                 goto nla_put_failure;
290         spin_unlock_bh(&p->tcf_lock);
291
292         return skb->len;
293
294 nla_put_failure:
295         spin_unlock_bh(&p->tcf_lock);
296         nlmsg_trim(skb, b);
297         return -1;
298 }
299
300 static int tcf_nat_walker(struct net *net, struct sk_buff *skb,
301                           struct netlink_callback *cb, int type,
302                           const struct tc_action_ops *ops,
303                           struct netlink_ext_ack *extack)
304 {
305         struct tc_action_net *tn = net_generic(net, nat_net_id);
306
307         return tcf_generic_walker(tn, skb, cb, type, ops, extack);
308 }
309
310 static int tcf_nat_search(struct net *net, struct tc_action **a, u32 index)
311 {
312         struct tc_action_net *tn = net_generic(net, nat_net_id);
313
314         return tcf_idr_search(tn, a, index);
315 }
316
317 static struct tc_action_ops act_nat_ops = {
318         .kind           =       "nat",
319         .id             =       TCA_ID_NAT,
320         .owner          =       THIS_MODULE,
321         .act            =       tcf_nat_act,
322         .dump           =       tcf_nat_dump,
323         .init           =       tcf_nat_init,
324         .walk           =       tcf_nat_walker,
325         .lookup         =       tcf_nat_search,
326         .size           =       sizeof(struct tcf_nat),
327 };
328
329 static __net_init int nat_init_net(struct net *net)
330 {
331         struct tc_action_net *tn = net_generic(net, nat_net_id);
332
333         return tc_action_net_init(tn, &act_nat_ops);
334 }
335
336 static void __net_exit nat_exit_net(struct list_head *net_list)
337 {
338         tc_action_net_exit(net_list, nat_net_id);
339 }
340
341 static struct pernet_operations nat_net_ops = {
342         .init = nat_init_net,
343         .exit_batch = nat_exit_net,
344         .id   = &nat_net_id,
345         .size = sizeof(struct tc_action_net),
346 };
347
348 MODULE_DESCRIPTION("Stateless NAT actions");
349 MODULE_LICENSE("GPL");
350
351 static int __init nat_init_module(void)
352 {
353         return tcf_register_action(&act_nat_ops, &nat_net_ops);
354 }
355
356 static void __exit nat_cleanup_module(void)
357 {
358         tcf_unregister_action(&act_nat_ops, &nat_net_ops);
359 }
360
361 module_init(nat_init_module);
362 module_exit(nat_cleanup_module);