diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/xfrm4_output.c | 12 | ||||
-rw-r--r-- | net/ipv4/xfrm4_state.c | 1 | ||||
-rw-r--r-- | net/ipv6/xfrm6_output.c | 10 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 1 | ||||
-rw-r--r-- | net/xfrm/xfrm_output.c | 13 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 7 |
6 files changed, 33 insertions, 11 deletions
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 327a617d594c..7a5491ffa4de 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -33,8 +33,7 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb) | |||
33 | mtu = dst_mtu(dst); | 33 | mtu = dst_mtu(dst); |
34 | if (skb->len > mtu) { | 34 | if (skb->len > mtu) { |
35 | if (skb->sk) | 35 | if (skb->sk) |
36 | ip_local_error(skb->sk, EMSGSIZE, ip_hdr(skb)->daddr, | 36 | xfrm_local_error(skb, mtu); |
37 | inet_sk(skb->sk)->inet_dport, mtu); | ||
38 | else | 37 | else |
39 | icmp_send(skb, ICMP_DEST_UNREACH, | 38 | icmp_send(skb, ICMP_DEST_UNREACH, |
40 | ICMP_FRAG_NEEDED, htonl(mtu)); | 39 | ICMP_FRAG_NEEDED, htonl(mtu)); |
@@ -99,3 +98,12 @@ int xfrm4_output(struct sk_buff *skb) | |||
99 | x->outer_mode->afinfo->output_finish, | 98 | x->outer_mode->afinfo->output_finish, |
100 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 99 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
101 | } | 100 | } |
101 | |||
102 | void xfrm4_local_error(struct sk_buff *skb, u32 mtu) | ||
103 | { | ||
104 | struct iphdr *hdr; | ||
105 | |||
106 | hdr = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb); | ||
107 | ip_local_error(skb->sk, EMSGSIZE, hdr->daddr, | ||
108 | inet_sk(skb->sk)->inet_dport, mtu); | ||
109 | } | ||
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 9258e751baba..0b2a0641526a 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -83,6 +83,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = { | |||
83 | .extract_input = xfrm4_extract_input, | 83 | .extract_input = xfrm4_extract_input, |
84 | .extract_output = xfrm4_extract_output, | 84 | .extract_output = xfrm4_extract_output, |
85 | .transport_finish = xfrm4_transport_finish, | 85 | .transport_finish = xfrm4_transport_finish, |
86 | .local_error = xfrm4_local_error, | ||
86 | }; | 87 | }; |
87 | 88 | ||
88 | void __init xfrm4_state_init(void) | 89 | void __init xfrm4_state_init(void) |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 8755a3079d0f..b64fff30eb06 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -34,8 +34,10 @@ static int xfrm6_local_dontfrag(struct sk_buff *skb) | |||
34 | struct sock *sk = skb->sk; | 34 | struct sock *sk = skb->sk; |
35 | 35 | ||
36 | if (sk) { | 36 | if (sk) { |
37 | proto = sk->sk_protocol; | 37 | if (sk->sk_family != AF_INET6) |
38 | return 0; | ||
38 | 39 | ||
40 | proto = sk->sk_protocol; | ||
39 | if (proto == IPPROTO_UDP || proto == IPPROTO_RAW) | 41 | if (proto == IPPROTO_UDP || proto == IPPROTO_RAW) |
40 | return inet6_sk(sk)->dontfrag; | 42 | return inet6_sk(sk)->dontfrag; |
41 | } | 43 | } |
@@ -54,7 +56,7 @@ static void xfrm6_local_rxpmtu(struct sk_buff *skb, u32 mtu) | |||
54 | ipv6_local_rxpmtu(sk, &fl6, mtu); | 56 | ipv6_local_rxpmtu(sk, &fl6, mtu); |
55 | } | 57 | } |
56 | 58 | ||
57 | static void xfrm6_local_error(struct sk_buff *skb, u32 mtu) | 59 | void xfrm6_local_error(struct sk_buff *skb, u32 mtu) |
58 | { | 60 | { |
59 | struct flowi6 fl6; | 61 | struct flowi6 fl6; |
60 | struct sock *sk = skb->sk; | 62 | struct sock *sk = skb->sk; |
@@ -80,7 +82,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) | |||
80 | if (xfrm6_local_dontfrag(skb)) | 82 | if (xfrm6_local_dontfrag(skb)) |
81 | xfrm6_local_rxpmtu(skb, mtu); | 83 | xfrm6_local_rxpmtu(skb, mtu); |
82 | else if (skb->sk) | 84 | else if (skb->sk) |
83 | xfrm6_local_error(skb, mtu); | 85 | xfrm_local_error(skb, mtu); |
84 | else | 86 | else |
85 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 87 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
86 | ret = -EMSGSIZE; | 88 | ret = -EMSGSIZE; |
@@ -142,7 +144,7 @@ static int __xfrm6_output(struct sk_buff *skb) | |||
142 | xfrm6_local_rxpmtu(skb, mtu); | 144 | xfrm6_local_rxpmtu(skb, mtu); |
143 | return -EMSGSIZE; | 145 | return -EMSGSIZE; |
144 | } else if (!skb->local_df && skb->len > mtu && skb->sk) { | 146 | } else if (!skb->local_df && skb->len > mtu && skb->sk) { |
145 | xfrm6_local_error(skb, mtu); | 147 | xfrm_local_error(skb, mtu); |
146 | return -EMSGSIZE; | 148 | return -EMSGSIZE; |
147 | } | 149 | } |
148 | 150 | ||
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index d8c70b8efc24..3fc970135fc6 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -183,6 +183,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = { | |||
183 | .extract_input = xfrm6_extract_input, | 183 | .extract_input = xfrm6_extract_input, |
184 | .extract_output = xfrm6_extract_output, | 184 | .extract_output = xfrm6_extract_output, |
185 | .transport_finish = xfrm6_transport_finish, | 185 | .transport_finish = xfrm6_transport_finish, |
186 | .local_error = xfrm6_local_error, | ||
186 | }; | 187 | }; |
187 | 188 | ||
188 | int __init xfrm6_state_init(void) | 189 | int __init xfrm6_state_init(void) |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index eb4a84288648..6f5fc612b162 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -214,5 +214,18 @@ int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb) | |||
214 | return inner_mode->afinfo->extract_output(x, skb); | 214 | return inner_mode->afinfo->extract_output(x, skb); |
215 | } | 215 | } |
216 | 216 | ||
217 | void xfrm_local_error(struct sk_buff *skb, int mtu) | ||
218 | { | ||
219 | struct xfrm_state_afinfo *afinfo; | ||
220 | |||
221 | afinfo = xfrm_state_get_afinfo(skb->sk->sk_family); | ||
222 | if (!afinfo) | ||
223 | return; | ||
224 | |||
225 | afinfo->local_error(skb, mtu); | ||
226 | xfrm_state_put_afinfo(afinfo); | ||
227 | } | ||
228 | |||
217 | EXPORT_SYMBOL_GPL(xfrm_output); | 229 | EXPORT_SYMBOL_GPL(xfrm_output); |
218 | EXPORT_SYMBOL_GPL(xfrm_inner_extract_output); | 230 | EXPORT_SYMBOL_GPL(xfrm_inner_extract_output); |
231 | EXPORT_SYMBOL_GPL(xfrm_local_error); | ||
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 78f66fa92449..54c0acd29468 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -39,9 +39,6 @@ static DEFINE_SPINLOCK(xfrm_state_lock); | |||
39 | 39 | ||
40 | static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; | 40 | static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; |
41 | 41 | ||
42 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); | ||
43 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); | ||
44 | |||
45 | static inline unsigned int xfrm_dst_hash(struct net *net, | 42 | static inline unsigned int xfrm_dst_hash(struct net *net, |
46 | const xfrm_address_t *daddr, | 43 | const xfrm_address_t *daddr, |
47 | const xfrm_address_t *saddr, | 44 | const xfrm_address_t *saddr, |
@@ -1860,7 +1857,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) | |||
1860 | } | 1857 | } |
1861 | EXPORT_SYMBOL(xfrm_state_unregister_afinfo); | 1858 | EXPORT_SYMBOL(xfrm_state_unregister_afinfo); |
1862 | 1859 | ||
1863 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family) | 1860 | struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family) |
1864 | { | 1861 | { |
1865 | struct xfrm_state_afinfo *afinfo; | 1862 | struct xfrm_state_afinfo *afinfo; |
1866 | if (unlikely(family >= NPROTO)) | 1863 | if (unlikely(family >= NPROTO)) |
@@ -1872,7 +1869,7 @@ static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family) | |||
1872 | return afinfo; | 1869 | return afinfo; |
1873 | } | 1870 | } |
1874 | 1871 | ||
1875 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) | 1872 | void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) |
1876 | { | 1873 | { |
1877 | rcu_read_unlock(); | 1874 | rcu_read_unlock(); |
1878 | } | 1875 | } |