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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [net/] [ipv6/] [netfilter/] [ip6t_hbh.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/* Kernel module to match Hop-by-Hop and Destination parameters. */
2
 
3
/* (C) 2001-2002 Andras Kis-Szabo <kisza@sch.bme.hu>
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation.
8
 */
9
 
10
#include <linux/module.h>
11
#include <linux/skbuff.h>
12
#include <linux/ipv6.h>
13
#include <linux/types.h>
14
#include <net/checksum.h>
15
#include <net/ipv6.h>
16
 
17
#include <asm/byteorder.h>
18
 
19
#include <linux/netfilter/x_tables.h>
20
#include <linux/netfilter_ipv6/ip6_tables.h>
21
#include <linux/netfilter_ipv6/ip6t_opts.h>
22
 
23
MODULE_LICENSE("GPL");
24
MODULE_DESCRIPTION("IPv6 opts match");
25
MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
26
MODULE_ALIAS("ip6t_dst");
27
 
28
/*
29
 *  (Type & 0xC0) >> 6
30
 *      0        -> ignorable
31
 *      1       -> must drop the packet
32
 *      2       -> send ICMP PARM PROB regardless and drop packet
33
 *      3       -> Send ICMP if not a multicast address and drop packet
34
 *  (Type & 0x20) >> 5
35
 *      0        -> invariant
36
 *      1       -> can change the routing
37
 *  (Type & 0x1F) Type
38
 *      0        -> Pad1 (only 1 byte!)
39
 *      1       -> PadN LENGTH info (total length = length + 2)
40
 *      C0 | 2  -> JUMBO 4 x x x x ( xxxx > 64k )
41
 *      5       -> RTALERT 2 x x
42
 */
43
 
44
static bool
45
match(const struct sk_buff *skb,
46
      const struct net_device *in,
47
      const struct net_device *out,
48
      const struct xt_match *match,
49
      const void *matchinfo,
50
      int offset,
51
      unsigned int protoff,
52
      bool *hotdrop)
53
{
54
        struct ipv6_opt_hdr _optsh;
55
        const struct ipv6_opt_hdr *oh;
56
        const struct ip6t_opts *optinfo = matchinfo;
57
        unsigned int temp;
58
        unsigned int ptr;
59
        unsigned int hdrlen = 0;
60
        bool ret = false;
61
        u8 _opttype;
62
        u8 _optlen;
63
        const u_int8_t *tp = NULL;
64
        const u_int8_t *lp = NULL;
65
        unsigned int optlen;
66
        int err;
67
 
68
        err = ipv6_find_hdr(skb, &ptr, match->data, NULL);
69
        if (err < 0) {
70
                if (err != -ENOENT)
71
                        *hotdrop = true;
72
                return false;
73
        }
74
 
75
        oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
76
        if (oh == NULL) {
77
                *hotdrop = true;
78
                return false;
79
        }
80
 
81
        hdrlen = ipv6_optlen(oh);
82
        if (skb->len - ptr < hdrlen) {
83
                /* Packet smaller than it's length field */
84
                return false;
85
        }
86
 
87
        pr_debug("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
88
 
89
        pr_debug("len %02X %04X %02X ",
90
                 optinfo->hdrlen, hdrlen,
91
                 (!(optinfo->flags & IP6T_OPTS_LEN) ||
92
                  ((optinfo->hdrlen == hdrlen) ^
93
                   !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
94
 
95
        ret = (oh != NULL) &&
96
              (!(optinfo->flags & IP6T_OPTS_LEN) ||
97
               ((optinfo->hdrlen == hdrlen) ^
98
                !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
99
 
100
        ptr += 2;
101
        hdrlen -= 2;
102
        if (!(optinfo->flags & IP6T_OPTS_OPTS)) {
103
                return ret;
104
        } else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
105
                pr_debug("Not strict - not implemented");
106
        } else {
107
                pr_debug("Strict ");
108
                pr_debug("#%d ", optinfo->optsnr);
109
                for (temp = 0; temp < optinfo->optsnr; temp++) {
110
                        /* type field exists ? */
111
                        if (hdrlen < 1)
112
                                break;
113
                        tp = skb_header_pointer(skb, ptr, sizeof(_opttype),
114
                                                &_opttype);
115
                        if (tp == NULL)
116
                                break;
117
 
118
                        /* Type check */
119
                        if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) {
120
                                pr_debug("Tbad %02X %02X\n", *tp,
121
                                         (optinfo->opts[temp] & 0xFF00) >> 8);
122
                                return false;
123
                        } else {
124
                                pr_debug("Tok ");
125
                        }
126
                        /* Length check */
127
                        if (*tp) {
128
                                u16 spec_len;
129
 
130
                                /* length field exists ? */
131
                                if (hdrlen < 2)
132
                                        break;
133
                                lp = skb_header_pointer(skb, ptr + 1,
134
                                                        sizeof(_optlen),
135
                                                        &_optlen);
136
                                if (lp == NULL)
137
                                        break;
138
                                spec_len = optinfo->opts[temp] & 0x00FF;
139
 
140
                                if (spec_len != 0x00FF && spec_len != *lp) {
141
                                        pr_debug("Lbad %02X %04X\n", *lp,
142
                                                 spec_len);
143
                                        return false;
144
                                }
145
                                pr_debug("Lok ");
146
                                optlen = *lp + 2;
147
                        } else {
148
                                pr_debug("Pad1\n");
149
                                optlen = 1;
150
                        }
151
 
152
                        /* Step to the next */
153
                        pr_debug("len%04X \n", optlen);
154
 
155
                        if ((ptr > skb->len - optlen || hdrlen < optlen) &&
156
                            temp < optinfo->optsnr - 1) {
157
                                pr_debug("new pointer is too large! \n");
158
                                break;
159
                        }
160
                        ptr += optlen;
161
                        hdrlen -= optlen;
162
                }
163
                if (temp == optinfo->optsnr)
164
                        return ret;
165
                else
166
                        return false;
167
        }
168
 
169
        return false;
170
}
171
 
172
/* Called when user tries to insert an entry of this type. */
173
static bool
174
checkentry(const char *tablename,
175
           const void *entry,
176
           const struct xt_match *match,
177
           void *matchinfo,
178
           unsigned int hook_mask)
179
{
180
        const struct ip6t_opts *optsinfo = matchinfo;
181
 
182
        if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
183
                pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
184
                return false;
185
        }
186
        return true;
187
}
188
 
189
static struct xt_match opts_match[] __read_mostly = {
190
        {
191
                .name           = "hbh",
192
                .family         = AF_INET6,
193
                .match          = match,
194
                .matchsize      = sizeof(struct ip6t_opts),
195
                .checkentry     = checkentry,
196
                .me             = THIS_MODULE,
197
                .data           = NEXTHDR_HOP,
198
        },
199
        {
200
                .name           = "dst",
201
                .family         = AF_INET6,
202
                .match          = match,
203
                .matchsize      = sizeof(struct ip6t_opts),
204
                .checkentry     = checkentry,
205
                .me             = THIS_MODULE,
206
                .data           = NEXTHDR_DEST,
207
        },
208
};
209
 
210
static int __init ip6t_hbh_init(void)
211
{
212
        return xt_register_matches(opts_match, ARRAY_SIZE(opts_match));
213
}
214
 
215
static void __exit ip6t_hbh_fini(void)
216
{
217
        xt_unregister_matches(opts_match, ARRAY_SIZE(opts_match));
218
}
219
 
220
module_init(ip6t_hbh_init);
221
module_exit(ip6t_hbh_fini);

powered by: WebSVN 2.1.0

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