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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [ipv6/] [ip6_fw.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      IPv6 Firewall
3
 *      Linux INET6 implementation
4
 *
5
 *      Authors:
6
 *      Pedro Roque             <roque@di.fc.ul.pt>
7
 *
8
 *      $Id: ip6_fw.c,v 1.1.1.1 2004-04-15 01:14:44 phoenix Exp $
9
 *
10
 *      This program is free software; you can redistribute it and/or
11
 *      modify it under the terms of the GNU General Public License
12
 *      as published by the Free Software Foundation; either version
13
 *      2 of the License, or (at your option) any later version.
14
 */
15
 
16
#include <linux/config.h>
17
#include <linux/errno.h>
18
#include <linux/types.h>
19
#include <linux/string.h>
20
#include <linux/socket.h>
21
#include <linux/sockios.h>
22
#include <linux/net.h>
23
#include <linux/route.h>
24
#include <linux/netdevice.h>
25
#include <linux/in6.h>
26
#include <linux/udp.h>
27
#include <linux/init.h>
28
 
29
#include <net/ipv6.h>
30
#include <net/ip6_route.h>
31
#include <net/ip6_fw.h>
32
#include <net/netlink.h>
33
 
34
static unsigned long ip6_fw_rule_cnt;
35
static struct ip6_fw_rule ip6_fw_rule_list = {
36
        {0},
37
        NULL, NULL,
38
        {0},
39
        IP6_FW_REJECT
40
};
41
 
42
static int ip6_fw_accept(struct dst_entry *dst, struct fl_acc_args *args);
43
 
44
struct flow_rule_ops ip6_fw_ops = {
45
        ip6_fw_accept
46
};
47
 
48
 
49
static struct rt6_info ip6_fw_null_entry = {
50
        {{NULL, 0, 0, NULL,
51
          0, 0, 0, 0, 0, 0, 0, 0, -ENETUNREACH, NULL, NULL,
52
          ip6_pkt_discard, ip6_pkt_discard, NULL}},
53
        NULL, {{{0}}}, 256, RTF_REJECT|RTF_NONEXTHOP, ~0UL,
54
        0, &ip6_fw_rule_list, {{{{0}}}, 128}, {{{{0}}}, 128}
55
};
56
 
57
static struct fib6_node ip6_fw_fib = {
58
        NULL, NULL, NULL, NULL,
59
        &ip6_fw_null_entry,
60
        0, RTN_ROOT|RTN_TL_ROOT, 0
61
};
62
 
63
rwlock_t ip6_fw_lock = RW_LOCK_UNLOCKED;
64
 
65
 
66
static void ip6_rule_add(struct ip6_fw_rule *rl)
67
{
68
        struct ip6_fw_rule *next;
69
 
70
        write_lock_bh(&ip6_fw_lock);
71
        ip6_fw_rule_cnt++;
72
        next = &ip6_fw_rule_list;
73
        rl->next = next;
74
        rl->prev = next->prev;
75
        rl->prev->next = rl;
76
        next->prev = rl;
77
        write_unlock_bh(&ip6_fw_lock);
78
}
79
 
80
static void ip6_rule_del(struct ip6_fw_rule *rl)
81
{
82
        struct ip6_fw_rule *next, *prev;
83
 
84
        write_lock_bh(&ip6_fw_lock);
85
        ip6_fw_rule_cnt--;
86
        next = rl->next;
87
        prev = rl->prev;
88
        next->prev = prev;
89
        prev->next = next;
90
        write_unlock_bh(&ip6_fw_lock);
91
}
92
 
93
static __inline__ struct ip6_fw_rule * ip6_fwrule_alloc(void)
94
{
95
        struct ip6_fw_rule *rl;
96
 
97
        rl = kmalloc(sizeof(struct ip6_fw_rule), GFP_ATOMIC);
98
        if (rl)
99
        {
100
                memset(rl, 0, sizeof(struct ip6_fw_rule));
101
                rl->flowr.ops = &ip6_fw_ops;
102
        }
103
        return rl;
104
}
105
 
106
static __inline__ void ip6_fwrule_free(struct ip6_fw_rule * rl)
107
{
108
        kfree(rl);
109
}
110
 
111
static __inline__ int port_match(int rl_port, int fl_port)
112
{
113
        int res = 0;
114
        if (rl_port == 0 || (rl_port == fl_port))
115
                res = 1;
116
        return res;
117
}
118
 
119
static int ip6_fw_accept_trans(struct ip6_fw_rule *rl,
120
                               struct fl_acc_args *args)
121
{
122
        int res = FLOWR_NODECISION;
123
        int proto = 0;
124
        int sport = 0;
125
        int dport = 0;
126
 
127
        switch (args->type) {
128
        case FL_ARG_FORWARD:
129
        {
130
                struct sk_buff *skb = args->fl_u.skb;
131
                struct ipv6hdr *hdr = skb->nh.ipv6h;
132
                int len;
133
 
134
                len = skb->len - sizeof(struct ipv6hdr);
135
 
136
                proto = hdr->nexthdr;
137
 
138
                switch (proto) {
139
                case IPPROTO_TCP:
140
                {
141
                        struct tcphdr *th;
142
 
143
                        if (len < sizeof(struct tcphdr)) {
144
                                res = FLOWR_ERROR;
145
                                goto out;
146
                        }
147
                        th = (struct tcphdr *)(hdr + 1);
148
                        sport = th->source;
149
                        dport = th->dest;
150
                        break;
151
                }
152
                case IPPROTO_UDP:
153
                {
154
                        struct udphdr *uh;
155
 
156
                        if (len < sizeof(struct udphdr)) {
157
                                res = FLOWR_ERROR;
158
                                goto out;
159
                        }
160
                        uh = (struct udphdr *)(hdr + 1);
161
                        sport = uh->source;
162
                        dport = uh->dest;
163
                        break;
164
                }
165
                default:
166
                        goto out;
167
                };
168
                break;
169
        }
170
 
171
        case FL_ARG_ORIGIN:
172
        {
173
                proto = args->fl_u.fl_o.flow->proto;
174
 
175
                if (proto == IPPROTO_ICMPV6) {
176
                        goto out;
177
                } else {
178
                        sport = args->fl_u.fl_o.flow->uli_u.ports.sport;
179
                        dport = args->fl_u.fl_o.flow->uli_u.ports.dport;
180
                }
181
                break;
182
        }
183
 
184
        if (proto == rl->info.proto &&
185
            port_match(args->fl_u.fl_o.flow->uli_u.ports.sport, sport) &&
186
            port_match(args->fl_u.fl_o.flow->uli_u.ports.dport, dport)) {
187
                if (rl->policy & IP6_FW_REJECT)
188
                        res = FLOWR_SELECT;
189
                else
190
                        res = FLOWR_CLEAR;
191
        }
192
 
193
        default:
194
#if IP6_FW_DEBUG >= 1
195
                printk(KERN_DEBUG "ip6_fw_accept: unknown arg type\n");
196
#endif
197
                goto out;
198
        };
199
 
200
out:
201
        return res;
202
}
203
 
204
static int ip6_fw_accept(struct dst_entry *dst, struct fl_acc_args *args)
205
{
206
        struct rt6_info *rt;
207
        struct ip6_fw_rule *rl;
208
        int proto;
209
        int res = FLOWR_NODECISION;
210
 
211
        rt = (struct rt6_info *) dst;
212
        rl = (struct ip6_fw_rule *) rt->rt6i_flowr;
213
 
214
        proto = rl->info.proto;
215
 
216
        switch (proto) {
217
        case 0:
218
                if (rl->policy & IP6_FW_REJECT)
219
                        res = FLOWR_SELECT;
220
                else
221
                        res = FLOWR_CLEAR;
222
                break;
223
        case IPPROTO_TCP:
224
        case IPPROTO_UDP:
225
                res = ip6_fw_accept_trans(rl, args);
226
                break;
227
        case IPPROTO_ICMPV6:
228
        };
229
 
230
        return res;
231
}
232
 
233
static struct dst_entry * ip6_fw_dup(struct dst_entry *frule,
234
                                     struct dst_entry *rt,
235
                                     struct fl_acc_args *args)
236
{
237
        struct ip6_fw_rule *rl;
238
        struct rt6_info *nrt;
239
        struct rt6_info *frt;
240
 
241
        frt = (struct rt6_info *) frule;
242
 
243
        rl = (struct ip6_fw_rule *) frt->rt6i_flowr;
244
 
245
        nrt = ip6_rt_copy((struct rt6_info *) rt);
246
 
247
        if (nrt) {
248
                nrt->u.dst.input = frule->input;
249
                nrt->u.dst.output = frule->output;
250
 
251
                nrt->rt6i_flowr = flow_clone(frt->rt6i_flowr);
252
 
253
                nrt->rt6i_flags |= RTF_CACHE;
254
                nrt->rt6i_tstamp = jiffies;
255
        }
256
 
257
        return (struct dst_entry *) nrt;
258
}
259
 
260
int ip6_fw_reject(struct sk_buff *skb)
261
{
262
#if IP6_FW_DEBUG >= 1
263
        printk(KERN_DEBUG "packet rejected: \n");
264
#endif
265
 
266
        icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0,
267
                    skb->dev);
268
        /*
269
         *      send it via netlink, as (rule, skb)
270
         */
271
 
272
        kfree_skb(skb);
273
        return 0;
274
}
275
 
276
int ip6_fw_discard(struct sk_buff *skb)
277
{
278
        printk(KERN_DEBUG "ip6_fw: BUG fw_reject called\n");
279
        kfree_skb(skb);
280
        return 0;
281
}
282
 
283
int ip6_fw_msg_add(struct ip6_fw_msg *msg)
284
{
285
        struct in6_rtmsg rtmsg;
286
        struct ip6_fw_rule *rl;
287
        struct rt6_info *rt;
288
        int err;
289
 
290
        ipv6_addr_copy(&rtmsg.rtmsg_dst, &msg->dst);
291
        ipv6_addr_copy(&rtmsg.rtmsg_src, &msg->src);
292
        rtmsg.rtmsg_dst_len = msg->dst_len;
293
        rtmsg.rtmsg_src_len = msg->src_len;
294
        rtmsg.rtmsg_metric = IP6_RT_PRIO_FW;
295
 
296
        rl = ip6_fwrule_alloc();
297
 
298
        if (rl == NULL)
299
                return -ENOMEM;
300
 
301
        rl->policy = msg->policy;
302
        rl->info.proto = msg->proto;
303
        rl->info.uli_u.data = msg->u.data;
304
 
305
        rtmsg.rtmsg_flags = RTF_NONEXTHOP|RTF_POLICY;
306
        err = ip6_route_add(&rtmsg);
307
 
308
        if (err) {
309
                ip6_fwrule_free(rl);
310
                return err;
311
        }
312
 
313
        /* The rest will not work for now. --ABK (989725) */
314
 
315
#ifndef notdef
316
        ip6_fwrule_free(rl);
317
        return -EPERM;
318
#else
319
        rt->u.dst.error = -EPERM;
320
 
321
        if (msg->policy == IP6_FW_ACCEPT) {
322
                /*
323
                 *      Accept rules are never selected
324
                 *      (i.e. packets use normal forwarding)
325
                 */
326
                rt->u.dst.input = ip6_fw_discard;
327
                rt->u.dst.output = ip6_fw_discard;
328
        } else {
329
                rt->u.dst.input = ip6_fw_reject;
330
                rt->u.dst.output = ip6_fw_reject;
331
        }
332
 
333
        ip6_rule_add(rl);
334
 
335
        rt->rt6i_flowr = flow_clone((struct flow_rule *)rl);
336
 
337
        return 0;
338
#endif
339
}
340
 
341
static int ip6_fw_msgrcv(int unit, struct sk_buff *skb)
342
{
343
        int count = 0;
344
 
345
        while (skb->len) {
346
                struct ip6_fw_msg *msg;
347
 
348
                if (skb->len < sizeof(struct ip6_fw_msg)) {
349
                        count = -EINVAL;
350
                        break;
351
                }
352
 
353
                msg = (struct ip6_fw_msg *) skb->data;
354
                skb_pull(skb, sizeof(struct ip6_fw_msg));
355
                count += sizeof(struct ip6_fw_msg);
356
 
357
                switch (msg->action) {
358
                case IP6_FW_MSG_ADD:
359
                        ip6_fw_msg_add(msg);
360
                        break;
361
                case IP6_FW_MSG_DEL:
362
                        break;
363
                default:
364
                        return -EINVAL;
365
                };
366
        }
367
 
368
        return count;
369
}
370
 
371
static void ip6_fw_destroy(struct flow_rule *rl)
372
{
373
        ip6_fwrule_free((struct ip6_fw_rule *)rl);
374
}
375
 
376
#ifdef MODULE
377
#define ip6_fw_init module_init
378
#endif
379
 
380
void __init ip6_fw_init(void)
381
{
382
        netlink_attach(NETLINK_IP6_FW, ip6_fw_msgrcv);
383
}
384
 
385
#ifdef MODULE
386
void cleanup_module(void)
387
{
388
        netlink_detach(NETLINK_IP6_FW);
389
}
390
#endif

powered by: WebSVN 2.1.0

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