diff options
Diffstat (limited to 'net/ipv6/icmp.c')
-rw-r--r-- | net/ipv6/icmp.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index e3a8e27af950..4ec876066b3f 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -273,6 +273,29 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st | |||
273 | return 0; | 273 | return 0; |
274 | } | 274 | } |
275 | 275 | ||
276 | #ifdef CONFIG_IPV6_MIP6 | ||
277 | static void mip6_addr_swap(struct sk_buff *skb) | ||
278 | { | ||
279 | struct ipv6hdr *iph = skb->nh.ipv6h; | ||
280 | struct inet6_skb_parm *opt = IP6CB(skb); | ||
281 | struct ipv6_destopt_hao *hao; | ||
282 | struct in6_addr tmp; | ||
283 | int off; | ||
284 | |||
285 | if (opt->dsthao) { | ||
286 | off = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO); | ||
287 | if (likely(off >= 0)) { | ||
288 | hao = (struct ipv6_destopt_hao *)(skb->nh.raw + off); | ||
289 | ipv6_addr_copy(&tmp, &iph->saddr); | ||
290 | ipv6_addr_copy(&iph->saddr, &hao->addr); | ||
291 | ipv6_addr_copy(&hao->addr, &tmp); | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | #else | ||
296 | static inline void mip6_addr_swap(struct sk_buff *skb) {} | ||
297 | #endif | ||
298 | |||
276 | /* | 299 | /* |
277 | * Send an ICMP message in response to a packet in error | 300 | * Send an ICMP message in response to a packet in error |
278 | */ | 301 | */ |
@@ -350,6 +373,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
350 | return; | 373 | return; |
351 | } | 374 | } |
352 | 375 | ||
376 | mip6_addr_swap(skb); | ||
377 | |||
353 | memset(&fl, 0, sizeof(fl)); | 378 | memset(&fl, 0, sizeof(fl)); |
354 | fl.proto = IPPROTO_ICMPV6; | 379 | fl.proto = IPPROTO_ICMPV6; |
355 | ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr); | 380 | ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr); |