aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c116
1 files changed, 40 insertions, 76 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 1220e2c7831e..a8218bc1806a 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -40,6 +40,7 @@
40 40
41#include <linux/errno.h> 41#include <linux/errno.h>
42#include <linux/types.h> 42#include <linux/types.h>
43#include <linux/kernel.h>
43#include <linux/socket.h> 44#include <linux/socket.h>
44#include <linux/sockios.h> 45#include <linux/sockios.h>
45#include <linux/net.h> 46#include <linux/net.h>
@@ -590,6 +591,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
590{ 591{
591 struct inet6_ifaddr *ifa = NULL; 592 struct inet6_ifaddr *ifa = NULL;
592 struct rt6_info *rt; 593 struct rt6_info *rt;
594 struct net *net = dev_net(idev->dev);
593 int hash; 595 int hash;
594 int err = 0; 596 int err = 0;
595 int addr_type = ipv6_addr_type(addr); 597 int addr_type = ipv6_addr_type(addr);
@@ -606,6 +608,11 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
606 goto out2; 608 goto out2;
607 } 609 }
608 610
611 if (idev->cnf.disable_ipv6 || net->ipv6.devconf_all->disable_ipv6) {
612 err = -EACCES;
613 goto out2;
614 }
615
609 write_lock(&addrconf_hash_lock); 616 write_lock(&addrconf_hash_lock);
610 617
611 /* Ignore adding duplicate addresses on an interface */ 618 /* Ignore adding duplicate addresses on an interface */
@@ -1209,16 +1216,12 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
1209 } 1216 }
1210 break; 1217 break;
1211 } else if (minihiscore < miniscore) { 1218 } else if (minihiscore < miniscore) {
1212 struct ipv6_saddr_score *tmp;
1213
1214 if (hiscore->ifa) 1219 if (hiscore->ifa)
1215 in6_ifa_put(hiscore->ifa); 1220 in6_ifa_put(hiscore->ifa);
1216 1221
1217 in6_ifa_hold(score->ifa); 1222 in6_ifa_hold(score->ifa);
1218 1223
1219 tmp = hiscore; 1224 swap(hiscore, score);
1220 hiscore = score;
1221 score = tmp;
1222 1225
1223 /* restore our iterator */ 1226 /* restore our iterator */
1224 score->ifa = hiscore->ifa; 1227 score->ifa = hiscore->ifa;
@@ -1367,40 +1370,6 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add
1367 return ifp; 1370 return ifp;
1368} 1371}
1369 1372
1370int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
1371{
1372 const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr;
1373 const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);
1374 __be32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr;
1375 __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
1376 int sk_ipv6only = ipv6_only_sock(sk);
1377 int sk2_ipv6only = inet_v6_ipv6only(sk2);
1378 int addr_type = ipv6_addr_type(sk_rcv_saddr6);
1379 int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED;
1380
1381 if (!sk2_rcv_saddr && !sk_ipv6only)
1382 return 1;
1383
1384 if (addr_type2 == IPV6_ADDR_ANY &&
1385 !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED))
1386 return 1;
1387
1388 if (addr_type == IPV6_ADDR_ANY &&
1389 !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED))
1390 return 1;
1391
1392 if (sk2_rcv_saddr6 &&
1393 ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6))
1394 return 1;
1395
1396 if (addr_type == IPV6_ADDR_MAPPED &&
1397 !sk2_ipv6only &&
1398 (!sk2_rcv_saddr || !sk_rcv_saddr || sk_rcv_saddr == sk2_rcv_saddr))
1399 return 1;
1400
1401 return 0;
1402}
1403
1404/* Gets referenced address, destroys ifaddr */ 1373/* Gets referenced address, destroys ifaddr */
1405 1374
1406static void addrconf_dad_stop(struct inet6_ifaddr *ifp) 1375static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
@@ -1433,6 +1402,11 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
1433void addrconf_dad_failure(struct inet6_ifaddr *ifp) 1402void addrconf_dad_failure(struct inet6_ifaddr *ifp)
1434{ 1403{
1435 struct inet6_dev *idev = ifp->idev; 1404 struct inet6_dev *idev = ifp->idev;
1405
1406 if (net_ratelimit())
1407 printk(KERN_INFO "%s: IPv6 duplicate address detected!\n",
1408 ifp->idev->dev->name);
1409
1436 if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) { 1410 if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) {
1437 struct in6_addr addr; 1411 struct in6_addr addr;
1438 1412
@@ -1443,11 +1417,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
1443 ipv6_addr_equal(&ifp->addr, &addr)) { 1417 ipv6_addr_equal(&ifp->addr, &addr)) {
1444 /* DAD failed for link-local based on MAC address */ 1418 /* DAD failed for link-local based on MAC address */
1445 idev->cnf.disable_ipv6 = 1; 1419 idev->cnf.disable_ipv6 = 1;
1420
1421 printk(KERN_INFO "%s: IPv6 being disabled!\n",
1422 ifp->idev->dev->name);
1446 } 1423 }
1447 } 1424 }
1448 1425
1449 if (net_ratelimit())
1450 printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
1451 addrconf_dad_stop(ifp); 1426 addrconf_dad_stop(ifp);
1452} 1427}
1453 1428
@@ -2227,10 +2202,24 @@ int addrconf_del_ifaddr(struct net *net, void __user *arg)
2227 return err; 2202 return err;
2228} 2203}
2229 2204
2205static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
2206 int plen, int scope)
2207{
2208 struct inet6_ifaddr *ifp;
2209
2210 ifp = ipv6_add_addr(idev, addr, plen, scope, IFA_F_PERMANENT);
2211 if (!IS_ERR(ifp)) {
2212 spin_lock_bh(&ifp->lock);
2213 ifp->flags &= ~IFA_F_TENTATIVE;
2214 spin_unlock_bh(&ifp->lock);
2215 ipv6_ifa_notify(RTM_NEWADDR, ifp);
2216 in6_ifa_put(ifp);
2217 }
2218}
2219
2230#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) 2220#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
2231static void sit_add_v4_addrs(struct inet6_dev *idev) 2221static void sit_add_v4_addrs(struct inet6_dev *idev)
2232{ 2222{
2233 struct inet6_ifaddr * ifp;
2234 struct in6_addr addr; 2223 struct in6_addr addr;
2235 struct net_device *dev; 2224 struct net_device *dev;
2236 struct net *net = dev_net(idev->dev); 2225 struct net *net = dev_net(idev->dev);
@@ -2249,14 +2238,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
2249 } 2238 }
2250 2239
2251 if (addr.s6_addr32[3]) { 2240 if (addr.s6_addr32[3]) {
2252 ifp = ipv6_add_addr(idev, &addr, 128, scope, IFA_F_PERMANENT); 2241 add_addr(idev, &addr, 128, scope);
2253 if (!IS_ERR(ifp)) {
2254 spin_lock_bh(&ifp->lock);
2255 ifp->flags &= ~IFA_F_TENTATIVE;
2256 spin_unlock_bh(&ifp->lock);
2257 ipv6_ifa_notify(RTM_NEWADDR, ifp);
2258 in6_ifa_put(ifp);
2259 }
2260 return; 2242 return;
2261 } 2243 }
2262 2244
@@ -2284,15 +2266,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
2284 else 2266 else
2285 plen = 96; 2267 plen = 96;
2286 2268
2287 ifp = ipv6_add_addr(idev, &addr, plen, flag, 2269 add_addr(idev, &addr, plen, flag);
2288 IFA_F_PERMANENT);
2289 if (!IS_ERR(ifp)) {
2290 spin_lock_bh(&ifp->lock);
2291 ifp->flags &= ~IFA_F_TENTATIVE;
2292 spin_unlock_bh(&ifp->lock);
2293 ipv6_ifa_notify(RTM_NEWADDR, ifp);
2294 in6_ifa_put(ifp);
2295 }
2296 } 2270 }
2297 } 2271 }
2298 } 2272 }
@@ -2302,7 +2276,6 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
2302static void init_loopback(struct net_device *dev) 2276static void init_loopback(struct net_device *dev)
2303{ 2277{
2304 struct inet6_dev *idev; 2278 struct inet6_dev *idev;
2305 struct inet6_ifaddr * ifp;
2306 2279
2307 /* ::1 */ 2280 /* ::1 */
2308 2281
@@ -2313,14 +2286,7 @@ static void init_loopback(struct net_device *dev)
2313 return; 2286 return;
2314 } 2287 }
2315 2288
2316 ifp = ipv6_add_addr(idev, &in6addr_loopback, 128, IFA_HOST, IFA_F_PERMANENT); 2289 add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
2317 if (!IS_ERR(ifp)) {
2318 spin_lock_bh(&ifp->lock);
2319 ifp->flags &= ~IFA_F_TENTATIVE;
2320 spin_unlock_bh(&ifp->lock);
2321 ipv6_ifa_notify(RTM_NEWADDR, ifp);
2322 in6_ifa_put(ifp);
2323 }
2324} 2290}
2325 2291
2326static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) 2292static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr)
@@ -2832,11 +2798,6 @@ static void addrconf_dad_timer(unsigned long data)
2832 read_unlock_bh(&idev->lock); 2798 read_unlock_bh(&idev->lock);
2833 goto out; 2799 goto out;
2834 } 2800 }
2835 if (idev->cnf.accept_dad > 1 && idev->cnf.disable_ipv6) {
2836 read_unlock_bh(&idev->lock);
2837 addrconf_dad_failure(ifp);
2838 return;
2839 }
2840 spin_lock_bh(&ifp->lock); 2801 spin_lock_bh(&ifp->lock);
2841 if (ifp->probes == 0) { 2802 if (ifp->probes == 0) {
2842 /* 2803 /*
@@ -3647,7 +3608,8 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
3647 kfree_skb(skb); 3608 kfree_skb(skb);
3648 goto errout; 3609 goto errout;
3649 } 3610 }
3650 err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); 3611 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
3612 return;
3651errout: 3613errout:
3652 if (err < 0) 3614 if (err < 0)
3653 rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); 3615 rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
@@ -3858,7 +3820,8 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
3858 kfree_skb(skb); 3820 kfree_skb(skb);
3859 goto errout; 3821 goto errout;
3860 } 3822 }
3861 err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); 3823 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
3824 return;
3862errout: 3825errout:
3863 if (err < 0) 3826 if (err < 0)
3864 rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err); 3827 rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
@@ -3928,7 +3891,8 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
3928 kfree_skb(skb); 3891 kfree_skb(skb);
3929 goto errout; 3892 goto errout;
3930 } 3893 }
3931 err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); 3894 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
3895 return;
3932errout: 3896errout:
3933 if (err < 0) 3897 if (err < 0)
3934 rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); 3898 rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err);