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

Subversion Repositories test_project

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * xfrm4_output.c - Common IPsec encapsulation code for IPv4.
3
 * Copyright (c) 2004 Herbert Xu <herbert@gondor.apana.org.au>
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version
8
 * 2 of the License, or (at your option) any later version.
9
 */
10
 
11
#include <linux/compiler.h>
12
#include <linux/if_ether.h>
13
#include <linux/kernel.h>
14
#include <linux/skbuff.h>
15
#include <linux/netfilter_ipv4.h>
16
#include <net/ip.h>
17
#include <net/xfrm.h>
18
#include <net/icmp.h>
19
 
20
static int xfrm4_tunnel_check_size(struct sk_buff *skb)
21
{
22
        int mtu, ret = 0;
23
        struct dst_entry *dst;
24
 
25
        if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE)
26
                goto out;
27
 
28
        IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
29
 
30
        if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->local_df)
31
                goto out;
32
 
33
        dst = skb->dst;
34
        mtu = dst_mtu(dst);
35
        if (skb->len > mtu) {
36
                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
37
                ret = -EMSGSIZE;
38
        }
39
out:
40
        return ret;
41
}
42
 
43
static inline int xfrm4_output_one(struct sk_buff *skb)
44
{
45
        struct dst_entry *dst = skb->dst;
46
        struct xfrm_state *x = dst->xfrm;
47
        struct iphdr *iph;
48
        int err;
49
 
50
        if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
51
                err = xfrm4_tunnel_check_size(skb);
52
                if (err)
53
                        goto error_nolock;
54
        }
55
 
56
        err = xfrm_output(skb);
57
        if (err)
58
                goto error_nolock;
59
 
60
        iph = ip_hdr(skb);
61
        iph->tot_len = htons(skb->len);
62
        ip_send_check(iph);
63
 
64
        IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
65
        err = 0;
66
 
67
out_exit:
68
        return err;
69
error_nolock:
70
        kfree_skb(skb);
71
        goto out_exit;
72
}
73
 
74
static int xfrm4_output_finish2(struct sk_buff *skb)
75
{
76
        int err;
77
 
78
        while (likely((err = xfrm4_output_one(skb)) == 0)) {
79
                nf_reset(skb);
80
 
81
                err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
82
                              skb->dst->dev, dst_output);
83
                if (unlikely(err != 1))
84
                        break;
85
 
86
                if (!skb->dst->xfrm)
87
                        return dst_output(skb);
88
 
89
                err = nf_hook(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
90
                              skb->dst->dev, xfrm4_output_finish2);
91
                if (unlikely(err != 1))
92
                        break;
93
        }
94
 
95
        return err;
96
}
97
 
98
static int xfrm4_output_finish(struct sk_buff *skb)
99
{
100
        struct sk_buff *segs;
101
 
102
#ifdef CONFIG_NETFILTER
103
        if (!skb->dst->xfrm) {
104
                IPCB(skb)->flags |= IPSKB_REROUTED;
105
                return dst_output(skb);
106
        }
107
#endif
108
 
109
        if (!skb_is_gso(skb))
110
                return xfrm4_output_finish2(skb);
111
 
112
        skb->protocol = htons(ETH_P_IP);
113
        segs = skb_gso_segment(skb, 0);
114
        kfree_skb(skb);
115
        if (unlikely(IS_ERR(segs)))
116
                return PTR_ERR(segs);
117
 
118
        do {
119
                struct sk_buff *nskb = segs->next;
120
                int err;
121
 
122
                segs->next = NULL;
123
                err = xfrm4_output_finish2(segs);
124
 
125
                if (unlikely(err)) {
126
                        while ((segs = nskb)) {
127
                                nskb = segs->next;
128
                                segs->next = NULL;
129
                                kfree_skb(segs);
130
                        }
131
                        return err;
132
                }
133
 
134
                segs = nskb;
135
        } while (segs);
136
 
137
        return 0;
138
}
139
 
140
int xfrm4_output(struct sk_buff *skb)
141
{
142
        return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev,
143
                            xfrm4_output_finish,
144
                            !(IPCB(skb)->flags & IPSKB_REROUTED));
145
}

powered by: WebSVN 2.1.0

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