diff options
author | Eric Dumazet <edumazet@google.com> | 2016-06-19 07:52:02 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-06-19 08:11:38 +0300 |
commit | b1cadc1a0949c82ff7fcb15603e3caf2d32ff9f6 (patch) | |
tree | fb574ee11be97ef84b0c29ff46c3aaa992821ba9 | |
parent | adc01582e36fc228f6f1c82188f7501eb4c6154f (diff) | |
download | linux-b1cadc1a0949c82ff7fcb15603e3caf2d32ff9f6.tar.xz |
ipv6: icmp: add a force_saddr param to icmp6_send()
SIT or GRE tunnels might want to translate an IPV4 address
into a v4mapped one when translating ICMP to ICMPv6.
This patch adds the parameter to icmp6_send() but
does not change icmpv6_send() signature.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/icmpv6.h | 3 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 7 | ||||
-rw-r--r-- | net/ipv6/ip6_icmp.c | 2 |
3 files changed, 8 insertions, 4 deletions
diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h index 630f45335c73..432611a297fb 100644 --- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -14,7 +14,8 @@ static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb) #if IS_ENABLED(CONFIG_IPV6) extern void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info); -typedef void ip6_icmp_send_t(struct sk_buff *skb, u8 type, u8 code, __u32 info); +typedef void ip6_icmp_send_t(struct sk_buff *skb, u8 type, u8 code, __u32 info, + const struct in6_addr *force_saddr); extern int inet6_register_icmp_sender(ip6_icmp_send_t *fn); extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn); diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index e32a72fb9982..6c57e6e90301 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -388,7 +388,8 @@ relookup_failed: /* * Send an ICMP message in response to a packet in error */ -static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) +static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + const struct in6_addr *force_saddr) { struct net *net = dev_net(skb->dev); struct inet6_dev *idev = NULL; @@ -475,6 +476,8 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_proto = IPPROTO_ICMPV6; fl6.daddr = hdr->saddr; + if (force_saddr) + saddr = force_saddr; if (saddr) fl6.saddr = *saddr; fl6.flowi6_mark = mark; @@ -551,7 +554,7 @@ out: */ void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos) { - icmp6_send(skb, ICMPV6_PARAMPROB, code, pos); + icmp6_send(skb, ICMPV6_PARAMPROB, code, pos, NULL); kfree_skb(skb); } diff --git a/net/ipv6/ip6_icmp.c b/net/ipv6/ip6_icmp.c index 14dacc544c3e..713676f14a0e 100644 --- a/net/ipv6/ip6_icmp.c +++ b/net/ipv6/ip6_icmp.c @@ -39,7 +39,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) if (!send) goto out; - send(skb, type, code, info); + send(skb, type, code, info, NULL); out: rcu_read_unlock(); } |