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/] [xfrm6_input.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * xfrm6_input.c: based on net/ipv4/xfrm4_input.c
3
 *
4
 * Authors:
5
 *      Mitsuru KANDA @USAGI
6
 *      Kazunori MIYAZAWA @USAGI
7
 *      Kunihiro Ishiguro <kunihiro@ipinfusion.com>
8
 *      YOSHIFUJI Hideaki @USAGI
9
 *              IPv6 support
10
 */
11
 
12
#include <linux/module.h>
13
#include <linux/string.h>
14
#include <linux/netfilter.h>
15
#include <linux/netfilter_ipv6.h>
16
#include <net/ipv6.h>
17
#include <net/xfrm.h>
18
 
19
int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
20
{
21
        int err;
22
        __be32 seq;
23
        struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
24
        struct xfrm_state *x;
25
        int xfrm_nr = 0;
26
        int decaps = 0;
27
        unsigned int nhoff;
28
 
29
        nhoff = IP6CB(skb)->nhoff;
30
 
31
        seq = 0;
32
        if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
33
                goto drop;
34
 
35
        do {
36
                struct ipv6hdr *iph = ipv6_hdr(skb);
37
 
38
                if (xfrm_nr == XFRM_MAX_DEPTH)
39
                        goto drop;
40
 
41
                x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
42
                                      nexthdr, AF_INET6);
43
                if (x == NULL)
44
                        goto drop;
45
                spin_lock(&x->lock);
46
                if (unlikely(x->km.state != XFRM_STATE_VALID))
47
                        goto drop_unlock;
48
 
49
                if (x->props.replay_window && xfrm_replay_check(x, seq))
50
                        goto drop_unlock;
51
 
52
                if (xfrm_state_check_expire(x))
53
                        goto drop_unlock;
54
 
55
                nexthdr = x->type->input(x, skb);
56
                if (nexthdr <= 0)
57
                        goto drop_unlock;
58
 
59
                skb_network_header(skb)[nhoff] = nexthdr;
60
 
61
                if (x->props.replay_window)
62
                        xfrm_replay_advance(x, seq);
63
 
64
                x->curlft.bytes += skb->len;
65
                x->curlft.packets++;
66
 
67
                spin_unlock(&x->lock);
68
 
69
                xfrm_vec[xfrm_nr++] = x;
70
 
71
                if (x->outer_mode->input(x, skb))
72
                        goto drop;
73
 
74
                if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
75
                        decaps = 1;
76
                        break;
77
                }
78
 
79
                if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) < 0)
80
                        goto drop;
81
        } while (!err);
82
 
83
        /* Allocate new secpath or COW existing one. */
84
        if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
85
                struct sec_path *sp;
86
                sp = secpath_dup(skb->sp);
87
                if (!sp)
88
                        goto drop;
89
                if (skb->sp)
90
                        secpath_put(skb->sp);
91
                skb->sp = sp;
92
        }
93
 
94
        if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
95
                goto drop;
96
 
97
        memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
98
               xfrm_nr * sizeof(xfrm_vec[0]));
99
        skb->sp->len += xfrm_nr;
100
 
101
        nf_reset(skb);
102
 
103
        if (decaps) {
104
                dst_release(skb->dst);
105
                skb->dst = NULL;
106
                netif_rx(skb);
107
                return -1;
108
        } else {
109
#ifdef CONFIG_NETFILTER
110
                ipv6_hdr(skb)->payload_len = htons(skb->len);
111
                __skb_push(skb, skb->data - skb_network_header(skb));
112
 
113
                NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
114
                        ip6_rcv_finish);
115
                return -1;
116
#else
117
                return 1;
118
#endif
119
        }
120
 
121
drop_unlock:
122
        spin_unlock(&x->lock);
123
        xfrm_state_put(x);
124
drop:
125
        while (--xfrm_nr >= 0)
126
                xfrm_state_put(xfrm_vec[xfrm_nr]);
127
        kfree_skb(skb);
128
        return -1;
129
}
130
 
131
EXPORT_SYMBOL(xfrm6_rcv_spi);
132
 
133
int xfrm6_rcv(struct sk_buff *skb)
134
{
135
        return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
136
                             0);
137
}
138
 
139
EXPORT_SYMBOL(xfrm6_rcv);
140
 
141
int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
142
                     xfrm_address_t *saddr, u8 proto)
143
{
144
        struct xfrm_state *x = NULL;
145
        int wildcard = 0;
146
        xfrm_address_t *xany;
147
        struct xfrm_state *xfrm_vec_one = NULL;
148
        int nh = 0;
149
        int i = 0;
150
 
151
        xany = (xfrm_address_t *)&in6addr_any;
152
 
153
        for (i = 0; i < 3; i++) {
154
                xfrm_address_t *dst, *src;
155
                switch (i) {
156
                case 0:
157
                        dst = daddr;
158
                        src = saddr;
159
                        break;
160
                case 1:
161
                        /* lookup state with wild-card source address */
162
                        wildcard = 1;
163
                        dst = daddr;
164
                        src = xany;
165
                        break;
166
                case 2:
167
                default:
168
                        /* lookup state with wild-card addresses */
169
                        wildcard = 1; /* XXX */
170
                        dst = xany;
171
                        src = xany;
172
                        break;
173
                }
174
 
175
                x = xfrm_state_lookup_byaddr(dst, src, proto, AF_INET6);
176
                if (!x)
177
                        continue;
178
 
179
                spin_lock(&x->lock);
180
 
181
                if (wildcard) {
182
                        if ((x->props.flags & XFRM_STATE_WILDRECV) == 0) {
183
                                spin_unlock(&x->lock);
184
                                xfrm_state_put(x);
185
                                x = NULL;
186
                                continue;
187
                        }
188
                }
189
 
190
                if (unlikely(x->km.state != XFRM_STATE_VALID)) {
191
                        spin_unlock(&x->lock);
192
                        xfrm_state_put(x);
193
                        x = NULL;
194
                        continue;
195
                }
196
                if (xfrm_state_check_expire(x)) {
197
                        spin_unlock(&x->lock);
198
                        xfrm_state_put(x);
199
                        x = NULL;
200
                        continue;
201
                }
202
 
203
                nh = x->type->input(x, skb);
204
                if (nh <= 0) {
205
                        spin_unlock(&x->lock);
206
                        xfrm_state_put(x);
207
                        x = NULL;
208
                        continue;
209
                }
210
 
211
                x->curlft.bytes += skb->len;
212
                x->curlft.packets++;
213
 
214
                spin_unlock(&x->lock);
215
 
216
                xfrm_vec_one = x;
217
                break;
218
        }
219
 
220
        if (!xfrm_vec_one)
221
                goto drop;
222
 
223
        /* Allocate new secpath or COW existing one. */
224
        if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
225
                struct sec_path *sp;
226
                sp = secpath_dup(skb->sp);
227
                if (!sp)
228
                        goto drop;
229
                if (skb->sp)
230
                        secpath_put(skb->sp);
231
                skb->sp = sp;
232
        }
233
 
234
        if (1 + skb->sp->len > XFRM_MAX_DEPTH)
235
                goto drop;
236
 
237
        skb->sp->xvec[skb->sp->len] = xfrm_vec_one;
238
        skb->sp->len ++;
239
 
240
        return 1;
241
drop:
242
        if (xfrm_vec_one)
243
                xfrm_state_put(xfrm_vec_one);
244
        return -1;
245
}
246
 
247
EXPORT_SYMBOL(xfrm6_input_addr);

powered by: WebSVN 2.1.0

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