OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [net/] [ipv4/] [fib_rules.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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(void)
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(&fib4_rules_ops);
318
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.