[NETNS]: Pass fib_rules_ops into default_pref method.
[safe/jmp/linux-2.6] / net / ipv4 / fib_rules.c
1 /*
2  * INET         An implementation of the TCP/IP protocol suite for the LINUX
3  *              operating system.  INET is implemented using the  BSD Socket
4  *              interface as the means of communication with the user level.
5  *
6  *              IPv4 Forwarding Information Base: policy rules.
7  *
8  * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
9  *              Thomas Graf <tgraf@suug.ch>
10  *
11  *              This program is free software; you can redistribute it and/or
12  *              modify it under the terms of the GNU General Public License
13  *              as published by the Free Software Foundation; either version
14  *              2 of the License, or (at your option) any later version.
15  *
16  * Fixes:
17  *              Rani Assaf      :       local_rule cannot be deleted
18  *              Marc Boucher    :       routing by fwmark
19  */
20
21 #include <linux/types.h>
22 #include <linux/kernel.h>
23 #include <linux/netdevice.h>
24 #include <linux/netlink.h>
25 #include <linux/inetdevice.h>
26 #include <linux/init.h>
27 #include <linux/list.h>
28 #include <linux/rcupdate.h>
29 #include <net/ip.h>
30 #include <net/route.h>
31 #include <net/tcp.h>
32 #include <net/ip_fib.h>
33 #include <net/fib_rules.h>
34
35 static struct fib_rules_ops fib4_rules_ops;
36
37 struct fib4_rule
38 {
39         struct fib_rule         common;
40         u8                      dst_len;
41         u8                      src_len;
42         u8                      tos;
43         __be32                  src;
44         __be32                  srcmask;
45         __be32                  dst;
46         __be32                  dstmask;
47 #ifdef CONFIG_NET_CLS_ROUTE
48         u32                     tclassid;
49 #endif
50 };
51
52 #ifdef CONFIG_NET_CLS_ROUTE
53 u32 fib_rules_tclass(struct fib_result *res)
54 {
55         return res->r ? ((struct fib4_rule *) res->r)->tclassid : 0;
56 }
57 #endif
58
59 int fib_lookup(struct flowi *flp, struct fib_result *res)
60 {
61         struct fib_lookup_arg arg = {
62                 .result = res,
63         };
64         int err;
65
66         err = fib_rules_lookup(&fib4_rules_ops, flp, 0, &arg);
67         res->r = arg.rule;
68
69         return err;
70 }
71
72 static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp,
73                             int flags, struct fib_lookup_arg *arg)
74 {
75         int err = -EAGAIN;
76         struct fib_table *tbl;
77
78         switch (rule->action) {
79         case FR_ACT_TO_TBL:
80                 break;
81
82         case FR_ACT_UNREACHABLE:
83                 err = -ENETUNREACH;
84                 goto errout;
85
86         case FR_ACT_PROHIBIT:
87                 err = -EACCES;
88                 goto errout;
89
90         case FR_ACT_BLACKHOLE:
91         default:
92                 err = -EINVAL;
93                 goto errout;
94         }
95
96         if ((tbl = fib_get_table(rule->table)) == NULL)
97                 goto errout;
98
99         err = tbl->tb_lookup(tbl, flp, (struct fib_result *) arg->result);
100         if (err > 0)
101                 err = -EAGAIN;
102 errout:
103         return err;
104 }
105
106
107 void fib_select_default(const struct flowi *flp, struct fib_result *res)
108 {
109         if (res->r && res->r->action == FR_ACT_TO_TBL &&
110             FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) {
111                 struct fib_table *tb;
112                 if ((tb = fib_get_table(res->r->table)) != NULL)
113                         tb->tb_select_default(tb, flp, res);
114         }
115 }
116
117 static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
118 {
119         struct fib4_rule *r = (struct fib4_rule *) rule;
120         __be32 daddr = fl->fl4_dst;
121         __be32 saddr = fl->fl4_src;
122
123         if (((saddr ^ r->src) & r->srcmask) ||
124             ((daddr ^ r->dst) & r->dstmask))
125                 return 0;
126
127         if (r->tos && (r->tos != fl->fl4_tos))
128                 return 0;
129
130         return 1;
131 }
132
133 static struct fib_table *fib_empty_table(void)
134 {
135         u32 id;
136
137         for (id = 1; id <= RT_TABLE_MAX; id++)
138                 if (fib_get_table(id) == NULL)
139                         return fib_new_table(id);
140         return NULL;
141 }
142
143 static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {
144         FRA_GENERIC_POLICY,
145         [FRA_FLOW]      = { .type = NLA_U32 },
146 };
147
148 static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
149                                struct nlmsghdr *nlh, struct fib_rule_hdr *frh,
150                                struct nlattr **tb)
151 {
152         int err = -EINVAL;
153         struct fib4_rule *rule4 = (struct fib4_rule *) rule;
154
155         if (frh->tos & ~IPTOS_TOS_MASK)
156                 goto errout;
157
158         if (rule->table == RT_TABLE_UNSPEC) {
159                 if (rule->action == FR_ACT_TO_TBL) {
160                         struct fib_table *table;
161
162                         table = fib_empty_table();
163                         if (table == NULL) {
164                                 err = -ENOBUFS;
165                                 goto errout;
166                         }
167
168                         rule->table = table->tb_id;
169                 }
170         }
171
172         if (frh->src_len)
173                 rule4->src = nla_get_be32(tb[FRA_SRC]);
174
175         if (frh->dst_len)
176                 rule4->dst = nla_get_be32(tb[FRA_DST]);
177
178 #ifdef CONFIG_NET_CLS_ROUTE
179         if (tb[FRA_FLOW])
180                 rule4->tclassid = nla_get_u32(tb[FRA_FLOW]);
181 #endif
182
183         rule4->src_len = frh->src_len;
184         rule4->srcmask = inet_make_mask(rule4->src_len);
185         rule4->dst_len = frh->dst_len;
186         rule4->dstmask = inet_make_mask(rule4->dst_len);
187         rule4->tos = frh->tos;
188
189         err = 0;
190 errout:
191         return err;
192 }
193
194 static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
195                              struct nlattr **tb)
196 {
197         struct fib4_rule *rule4 = (struct fib4_rule *) rule;
198
199         if (frh->src_len && (rule4->src_len != frh->src_len))
200                 return 0;
201
202         if (frh->dst_len && (rule4->dst_len != frh->dst_len))
203                 return 0;
204
205         if (frh->tos && (rule4->tos != frh->tos))
206                 return 0;
207
208 #ifdef CONFIG_NET_CLS_ROUTE
209         if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW])))
210                 return 0;
211 #endif
212
213         if (frh->src_len && (rule4->src != nla_get_be32(tb[FRA_SRC])))
214                 return 0;
215
216         if (frh->dst_len && (rule4->dst != nla_get_be32(tb[FRA_DST])))
217                 return 0;
218
219         return 1;
220 }
221
222 static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
223                           struct nlmsghdr *nlh, struct fib_rule_hdr *frh)
224 {
225         struct fib4_rule *rule4 = (struct fib4_rule *) rule;
226
227         frh->family = AF_INET;
228         frh->dst_len = rule4->dst_len;
229         frh->src_len = rule4->src_len;
230         frh->tos = rule4->tos;
231
232         if (rule4->dst_len)
233                 NLA_PUT_BE32(skb, FRA_DST, rule4->dst);
234
235         if (rule4->src_len)
236                 NLA_PUT_BE32(skb, FRA_SRC, rule4->src);
237
238 #ifdef CONFIG_NET_CLS_ROUTE
239         if (rule4->tclassid)
240                 NLA_PUT_U32(skb, FRA_FLOW, rule4->tclassid);
241 #endif
242         return 0;
243
244 nla_put_failure:
245         return -ENOBUFS;
246 }
247
248 static u32 fib4_rule_default_pref(struct fib_rules_ops *ops)
249 {
250         struct list_head *pos;
251         struct fib_rule *rule;
252
253         if (!list_empty(&fib4_rules_ops.rules_list)) {
254                 pos = fib4_rules_ops.rules_list.next;
255                 if (pos->next != &fib4_rules_ops.rules_list) {
256                         rule = list_entry(pos->next, struct fib_rule, list);
257                         if (rule->pref)
258                                 return rule->pref - 1;
259                 }
260         }
261
262         return 0;
263 }
264
265 static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
266 {
267         return nla_total_size(4) /* dst */
268                + nla_total_size(4) /* src */
269                + nla_total_size(4); /* flow */
270 }
271
272 static void fib4_rule_flush_cache(void)
273 {
274         rt_cache_flush(-1);
275 }
276
277 static struct fib_rules_ops fib4_rules_ops = {
278         .family         = AF_INET,
279         .rule_size      = sizeof(struct fib4_rule),
280         .addr_size      = sizeof(u32),
281         .action         = fib4_rule_action,
282         .match          = fib4_rule_match,
283         .configure      = fib4_rule_configure,
284         .compare        = fib4_rule_compare,
285         .fill           = fib4_rule_fill,
286         .default_pref   = fib4_rule_default_pref,
287         .nlmsg_payload  = fib4_rule_nlmsg_payload,
288         .flush_cache    = fib4_rule_flush_cache,
289         .nlgroup        = RTNLGRP_IPV4_RULE,
290         .policy         = fib4_rule_policy,
291         .rules_list     = LIST_HEAD_INIT(fib4_rules_ops.rules_list),
292         .owner          = THIS_MODULE,
293 };
294
295 static int __init fib_default_rules_init(void)
296 {
297         int err;
298
299         err = fib_default_rule_add(&fib4_rules_ops, 0,
300                                    RT_TABLE_LOCAL, FIB_RULE_PERMANENT);
301         if (err < 0)
302                 return err;
303         err = fib_default_rule_add(&fib4_rules_ops, 0x7FFE,
304                                    RT_TABLE_MAIN, 0);
305         if (err < 0)
306                 return err;
307         err = fib_default_rule_add(&fib4_rules_ops, 0x7FFF,
308                                    RT_TABLE_DEFAULT, 0);
309         if (err < 0)
310                 return err;
311         return 0;
312 }
313
314 void __init fib4_rules_init(void)
315 {
316         BUG_ON(fib_default_rules_init());
317         fib_rules_register(&init_net, &fib4_rules_ops);
318 }