Blame view
net/ipv6/xfrm6_output.c
3.56 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 |
/* * xfrm6_output.c - Common IPsec encapsulation code for IPv6. * Copyright (C) 2002 USAGI/WIDE Project * Copyright (c) 2004 Herbert Xu <herbert@gondor.apana.org.au> |
1ab1457c4 [NET] IPV6: Fix w... |
5 |
* |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 9 10 |
* This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ |
406ef77c8 [IPSEC]: Move com... |
11 |
#include <linux/if_ether.h> |
36cf9acf9 [IPSEC]: Separate... |
12 13 |
#include <linux/kernel.h> #include <linux/module.h> |
1da177e4c Linux-2.6.12-rc2 |
14 |
#include <linux/skbuff.h> |
1da177e4c Linux-2.6.12-rc2 |
15 |
#include <linux/icmpv6.h> |
16a6677fd [XFRM]: Netfilter... |
16 |
#include <linux/netfilter_ipv6.h> |
36cf9acf9 [IPSEC]: Separate... |
17 |
#include <net/dst.h> |
1da177e4c Linux-2.6.12-rc2 |
18 |
#include <net/ipv6.h> |
ad0081e43 ipv6: Fragment lo... |
19 |
#include <net/ip6_route.h> |
1da177e4c Linux-2.6.12-rc2 |
20 |
#include <net/xfrm.h> |
aee5adb43 [XFRM] STATE: Add... |
21 22 23 24 25 |
int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, u8 **prevhdr) { return ip6_find_1stfragopt(skb, prevhdr); } |
7159039a1 [IPV6]: Decentral... |
26 |
EXPORT_SYMBOL(xfrm6_find_1stfragopt); |
dd767856a xfrm6: Don't call... |
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
static int xfrm6_local_dontfrag(struct sk_buff *skb) { int proto; struct sock *sk = skb->sk; if (sk) { proto = sk->sk_protocol; if (proto == IPPROTO_UDP || proto == IPPROTO_RAW) return inet6_sk(sk)->dontfrag; } return 0; } static void xfrm6_local_rxpmtu(struct sk_buff *skb, u32 mtu) { struct flowi6 fl6; struct sock *sk = skb->sk; fl6.flowi6_oif = sk->sk_bound_dev_if; |
4e3fd7a06 net: remove ipv6_... |
48 |
fl6.daddr = ipv6_hdr(skb)->daddr; |
dd767856a xfrm6: Don't call... |
49 50 51 52 53 54 55 56 57 58 |
ipv6_local_rxpmtu(sk, &fl6, mtu); } static void xfrm6_local_error(struct sk_buff *skb, u32 mtu) { struct flowi6 fl6; struct sock *sk = skb->sk; fl6.fl6_dport = inet_sk(sk)->inet_dport; |
4e3fd7a06 net: remove ipv6_... |
59 |
fl6.daddr = ipv6_hdr(skb)->daddr; |
dd767856a xfrm6: Don't call... |
60 61 62 |
ipv6_local_error(sk, EMSGSIZE, &fl6, mtu); } |
1da177e4c Linux-2.6.12-rc2 |
63 64 65 |
static int xfrm6_tunnel_check_size(struct sk_buff *skb) { int mtu, ret = 0; |
adf30907d net: skb->dst acc... |
66 |
struct dst_entry *dst = skb_dst(skb); |
1da177e4c Linux-2.6.12-rc2 |
67 68 69 70 |
mtu = dst_mtu(dst); if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU; |
28a89453b [IPV6]: Fix IPsec... |
71 |
if (!skb->local_df && skb->len > mtu) { |
180e42503 [IPV6]: Fix xfrm ... |
72 |
skb->dev = dst->dev; |
dd767856a xfrm6: Don't call... |
73 74 75 76 77 78 79 |
if (xfrm6_local_dontfrag(skb)) xfrm6_local_rxpmtu(skb, mtu); else if (skb->sk) xfrm6_local_error(skb, mtu); else icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
1da177e4c Linux-2.6.12-rc2 |
80 81 82 83 84 |
ret = -EMSGSIZE; } return ret; } |
36cf9acf9 [IPSEC]: Separate... |
85 86 87 88 89 90 91 |
int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb) { int err; err = xfrm6_tunnel_check_size(skb); if (err) return err; |
60d5fcfb1 [IPSEC]: Remove n... |
92 |
XFRM_MODE_SKB_CB(skb)->protocol = ipv6_hdr(skb)->nexthdr; |
36cf9acf9 [IPSEC]: Separate... |
93 94 95 96 97 98 |
return xfrm6_extract_header(skb); } int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb) { int err; |
df9dcb458 [IPSEC]: Fix inte... |
99 |
err = xfrm_inner_extract_output(x, skb); |
36cf9acf9 [IPSEC]: Separate... |
100 101 102 103 |
if (err) return err; memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); |
862b82c6f [IPSEC]: Merge mo... |
104 105 106 |
#ifdef CONFIG_NETFILTER IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; #endif |
36cf9acf9 [IPSEC]: Separate... |
107 108 |
skb->protocol = htons(ETH_P_IPV6); |
d1d88e5de xfrm: fix fragmen... |
109 |
skb->local_df = 1; |
36cf9acf9 [IPSEC]: Separate... |
110 111 112 113 |
return x->outer_mode->output2(x, skb); } EXPORT_SYMBOL(xfrm6_prepare_output); |
43a4dea4c xfrm: Assign the ... |
114 |
int xfrm6_output_finish(struct sk_buff *skb) |
09b8f7a93 [IPSEC]: Handle G... |
115 |
{ |
862b82c6f [IPSEC]: Merge mo... |
116 117 118 |
#ifdef CONFIG_NETFILTER IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; #endif |
09b8f7a93 [IPSEC]: Handle G... |
119 |
|
679e898a4 [XFRM]: Fix proto... |
120 |
skb->protocol = htons(ETH_P_IPV6); |
862b82c6f [IPSEC]: Merge mo... |
121 |
return xfrm_output(skb); |
09b8f7a93 [IPSEC]: Handle G... |
122 |
} |
ad0081e43 ipv6: Fragment lo... |
123 124 125 126 |
static int __xfrm6_output(struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); struct xfrm_state *x = dst->xfrm; |
dd767856a xfrm6: Don't call... |
127 128 129 130 131 132 133 134 135 |
int mtu = ip6_skb_dst_mtu(skb); if (skb->len > mtu && xfrm6_local_dontfrag(skb)) { xfrm6_local_rxpmtu(skb, mtu); return -EMSGSIZE; } else if (!skb->local_df && skb->len > mtu && skb->sk) { xfrm6_local_error(skb, mtu); return -EMSGSIZE; } |
ad0081e43 ipv6: Fragment lo... |
136 137 |
if ((x && x->props.mode == XFRM_MODE_TUNNEL) && |
dd767856a xfrm6: Don't call... |
138 |
((skb->len > mtu && !skb_is_gso(skb)) || |
ad0081e43 ipv6: Fragment lo... |
139 |
dst_allfrag(skb_dst(skb)))) { |
43a4dea4c xfrm: Assign the ... |
140 |
return ip6_fragment(skb, x->outer_mode->afinfo->output_finish); |
ad0081e43 ipv6: Fragment lo... |
141 |
} |
43a4dea4c xfrm: Assign the ... |
142 |
return x->outer_mode->afinfo->output_finish(skb); |
ad0081e43 ipv6: Fragment lo... |
143 |
} |
16a6677fd [XFRM]: Netfilter... |
144 145 |
int xfrm6_output(struct sk_buff *skb) { |
b2e0b385d netfilter: ipv6: ... |
146 |
return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, |
ad0081e43 ipv6: Fragment lo... |
147 |
skb_dst(skb)->dev, __xfrm6_output); |
16a6677fd [XFRM]: Netfilter... |
148 |
} |