diff options
-rw-r--r-- | include/net/addrconf.h | 5 | ||||
-rw-r--r-- | net/ipv6/anycast.c | 11 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 4 |
3 files changed, 17 insertions, 3 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 66c4a44d8f5c..50e39a8822b4 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h | |||
@@ -205,8 +205,9 @@ void ipv6_sock_ac_close(struct sock *sk); | |||
205 | int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr); | 205 | int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr); |
206 | int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr); | 206 | int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr); |
207 | bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, | 207 | bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, |
208 | const struct in6_addr *addr); | 208 | const struct in6_addr *addr); |
209 | 209 | bool ipv6_chk_acast_addr_src(struct net *net, struct net_device *dev, | |
210 | const struct in6_addr *addr); | ||
210 | 211 | ||
211 | /* Device notifier */ | 212 | /* Device notifier */ |
212 | int register_inet6addr_notifier(struct notifier_block *nb); | 213 | int register_inet6addr_notifier(struct notifier_block *nb); |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 5a80f15a9de2..210183244689 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -383,6 +383,17 @@ bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, | |||
383 | return found; | 383 | return found; |
384 | } | 384 | } |
385 | 385 | ||
386 | /* check if this anycast address is link-local on given interface or | ||
387 | * is global | ||
388 | */ | ||
389 | bool ipv6_chk_acast_addr_src(struct net *net, struct net_device *dev, | ||
390 | const struct in6_addr *addr) | ||
391 | { | ||
392 | return ipv6_chk_acast_addr(net, | ||
393 | (ipv6_addr_type(addr) & IPV6_ADDR_LINKLOCAL ? | ||
394 | dev : NULL), | ||
395 | addr); | ||
396 | } | ||
386 | 397 | ||
387 | #ifdef CONFIG_PROC_FS | 398 | #ifdef CONFIG_PROC_FS |
388 | struct ac6_iter_state { | 399 | struct ac6_iter_state { |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 2f5e2f154d21..c3bf2d2e519e 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -699,7 +699,9 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, | |||
699 | int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL; | 699 | int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL; |
700 | if (!(inet_sk(sk)->freebind || inet_sk(sk)->transparent) && | 700 | if (!(inet_sk(sk)->freebind || inet_sk(sk)->transparent) && |
701 | !ipv6_chk_addr(net, &src_info->ipi6_addr, | 701 | !ipv6_chk_addr(net, &src_info->ipi6_addr, |
702 | strict ? dev : NULL, 0)) | 702 | strict ? dev : NULL, 0) && |
703 | !ipv6_chk_acast_addr_src(net, dev, | ||
704 | &src_info->ipi6_addr)) | ||
703 | err = -EINVAL; | 705 | err = -EINVAL; |
704 | else | 706 | else |
705 | fl6->saddr = src_info->ipi6_addr; | 707 | fl6->saddr = src_info->ipi6_addr; |