aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-21 11:19:50 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-21 11:19:50 -0400
commiteb6a12c2428d21a9f3e0f1a50e927d5fd80fc3d0 (patch)
tree5ac6f43899648abeab1d43aad3107f664e7f13d5 /net/ipv6/addrconf.c
parentc4762aba0b1f72659aae9ce37b772ca8bd8f06f4 (diff)
parent14b395e35d1afdd8019d11b92e28041fad591b71 (diff)
Merge branch 'linus' into cpus4096-for-linus
Conflicts: net/sunrpc/svc.c Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c94
1 files changed, 80 insertions, 14 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index ff61a5cdb0b3..9f4fcce6379b 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -6,8 +6,6 @@
6 * Pedro Roque <roque@di.fc.ul.pt> 6 * Pedro Roque <roque@di.fc.ul.pt>
7 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 7 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
8 * 8 *
9 * $Id: addrconf.c,v 1.69 2001/10/31 21:55:54 davem Exp $
10 *
11 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 11 * as published by the Free Software Foundation; either version
@@ -121,6 +119,7 @@ static void ipv6_regen_rndid(unsigned long data);
121static int desync_factor = MAX_DESYNC_FACTOR * HZ; 119static int desync_factor = MAX_DESYNC_FACTOR * HZ;
122#endif 120#endif
123 121
122static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
124static int ipv6_count_addresses(struct inet6_dev *idev); 123static int ipv6_count_addresses(struct inet6_dev *idev);
125 124
126/* 125/*
@@ -185,6 +184,8 @@ struct ipv6_devconf ipv6_devconf __read_mostly = {
185#endif 184#endif
186 .proxy_ndp = 0, 185 .proxy_ndp = 0,
187 .accept_source_route = 0, /* we do not accept RH0 by default. */ 186 .accept_source_route = 0, /* we do not accept RH0 by default. */
187 .disable_ipv6 = 0,
188 .accept_dad = 1,
188}; 189};
189 190
190static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { 191static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -217,6 +218,8 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
217#endif 218#endif
218 .proxy_ndp = 0, 219 .proxy_ndp = 0,
219 .accept_source_route = 0, /* we do not accept RH0 by default. */ 220 .accept_source_route = 0, /* we do not accept RH0 by default. */
221 .disable_ipv6 = 0,
222 .accept_dad = 1,
220}; 223};
221 224
222/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ 225/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -226,9 +229,15 @@ const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_IN
226const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT; 229const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
227 230
228/* Check if a valid qdisc is available */ 231/* Check if a valid qdisc is available */
229static inline int addrconf_qdisc_ok(struct net_device *dev) 232static inline bool addrconf_qdisc_ok(const struct net_device *dev)
233{
234 return !qdisc_tx_is_noop(dev);
235}
236
237/* Check if a route is valid prefix route */
238static inline int addrconf_is_prefix_route(const struct rt6_info *rt)
230{ 239{
231 return (dev->qdisc != &noop_qdisc); 240 return ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0);
232} 241}
233 242
234static void addrconf_del_timer(struct inet6_ifaddr *ifp) 243static void addrconf_del_timer(struct inet6_ifaddr *ifp)
@@ -344,6 +353,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
344 kfree(ndev); 353 kfree(ndev);
345 return NULL; 354 return NULL;
346 } 355 }
356 if (ndev->cnf.forwarding)
357 dev_disable_lro(dev);
347 /* We refer to the device */ 358 /* We refer to the device */
348 dev_hold(dev); 359 dev_hold(dev);
349 360
@@ -372,6 +383,9 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
372 */ 383 */
373 in6_dev_hold(ndev); 384 in6_dev_hold(ndev);
374 385
386 if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
387 ndev->cnf.accept_dad = -1;
388
375#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) 389#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
376 if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) { 390 if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) {
377 printk(KERN_INFO 391 printk(KERN_INFO
@@ -438,6 +452,8 @@ static void dev_forward_change(struct inet6_dev *idev)
438 if (!idev) 452 if (!idev)
439 return; 453 return;
440 dev = idev->dev; 454 dev = idev->dev;
455 if (idev->cnf.forwarding)
456 dev_disable_lro(dev);
441 if (dev && (dev->flags & IFF_MULTICAST)) { 457 if (dev && (dev->flags & IFF_MULTICAST)) {
442 if (idev->cnf.forwarding) 458 if (idev->cnf.forwarding)
443 ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters); 459 ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters);
@@ -483,12 +499,14 @@ static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
483 if (p == &net->ipv6.devconf_dflt->forwarding) 499 if (p == &net->ipv6.devconf_dflt->forwarding)
484 return; 500 return;
485 501
502 rtnl_lock();
486 if (p == &net->ipv6.devconf_all->forwarding) { 503 if (p == &net->ipv6.devconf_all->forwarding) {
487 __s32 newf = net->ipv6.devconf_all->forwarding; 504 __s32 newf = net->ipv6.devconf_all->forwarding;
488 net->ipv6.devconf_dflt->forwarding = newf; 505 net->ipv6.devconf_dflt->forwarding = newf;
489 addrconf_forward_change(net, newf); 506 addrconf_forward_change(net, newf);
490 } else if ((!*p) ^ (!old)) 507 } else if ((!*p) ^ (!old))
491 dev_forward_change((struct inet6_dev *)table->extra1); 508 dev_forward_change((struct inet6_dev *)table->extra1);
509 rtnl_unlock();
492 510
493 if (*p) 511 if (*p)
494 rt6_purge_dflt_routers(net); 512 rt6_purge_dflt_routers(net);
@@ -568,6 +586,13 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
568 struct rt6_info *rt; 586 struct rt6_info *rt;
569 int hash; 587 int hash;
570 int err = 0; 588 int err = 0;
589 int addr_type = ipv6_addr_type(addr);
590
591 if (addr_type == IPV6_ADDR_ANY ||
592 addr_type & IPV6_ADDR_MULTICAST ||
593 (!(idev->dev->flags & IFF_LOOPBACK) &&
594 addr_type & IPV6_ADDR_LOOPBACK))
595 return ERR_PTR(-EADDRNOTAVAIL);
571 596
572 rcu_read_lock_bh(); 597 rcu_read_lock_bh();
573 if (idev->dead) { 598 if (idev->dead) {
@@ -777,7 +802,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
777 ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); 802 ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
778 rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); 803 rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1);
779 804
780 if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { 805 if (rt && addrconf_is_prefix_route(rt)) {
781 if (onlink == 0) { 806 if (onlink == 0) {
782 ip6_del_rt(rt); 807 ip6_del_rt(rt);
783 rt = NULL; 808 rt = NULL;
@@ -958,7 +983,8 @@ static inline int ipv6_saddr_preferred(int type)
958 return 0; 983 return 0;
959} 984}
960 985
961static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score, 986static int ipv6_get_saddr_eval(struct net *net,
987 struct ipv6_saddr_score *score,
962 struct ipv6_saddr_dst *dst, 988 struct ipv6_saddr_dst *dst,
963 int i) 989 int i)
964{ 990{
@@ -1037,7 +1063,8 @@ static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score,
1037 break; 1063 break;
1038 case IPV6_SADDR_RULE_LABEL: 1064 case IPV6_SADDR_RULE_LABEL:
1039 /* Rule 6: Prefer matching label */ 1065 /* Rule 6: Prefer matching label */
1040 ret = ipv6_addr_label(&score->ifa->addr, score->addr_type, 1066 ret = ipv6_addr_label(net,
1067 &score->ifa->addr, score->addr_type,
1041 score->ifa->idev->dev->ifindex) == dst->label; 1068 score->ifa->idev->dev->ifindex) == dst->label;
1042 break; 1069 break;
1043#ifdef CONFIG_IPV6_PRIVACY 1070#ifdef CONFIG_IPV6_PRIVACY
@@ -1091,7 +1118,7 @@ int ipv6_dev_get_saddr(struct net_device *dst_dev,
1091 dst.addr = daddr; 1118 dst.addr = daddr;
1092 dst.ifindex = dst_dev ? dst_dev->ifindex : 0; 1119 dst.ifindex = dst_dev ? dst_dev->ifindex : 0;
1093 dst.scope = __ipv6_addr_src_scope(dst_type); 1120 dst.scope = __ipv6_addr_src_scope(dst_type);
1094 dst.label = ipv6_addr_label(daddr, dst_type, dst.ifindex); 1121 dst.label = ipv6_addr_label(net, daddr, dst_type, dst.ifindex);
1095 dst.prefs = prefs; 1122 dst.prefs = prefs;
1096 1123
1097 hiscore->rule = -1; 1124 hiscore->rule = -1;
@@ -1159,8 +1186,8 @@ int ipv6_dev_get_saddr(struct net_device *dst_dev,
1159 for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) { 1186 for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) {
1160 int minihiscore, miniscore; 1187 int minihiscore, miniscore;
1161 1188
1162 minihiscore = ipv6_get_saddr_eval(hiscore, &dst, i); 1189 minihiscore = ipv6_get_saddr_eval(net, hiscore, &dst, i);
1163 miniscore = ipv6_get_saddr_eval(score, &dst, i); 1190 miniscore = ipv6_get_saddr_eval(net, score, &dst, i);
1164 1191
1165 if (minihiscore > miniscore) { 1192 if (minihiscore > miniscore) {
1166 if (i == IPV6_SADDR_RULE_SCOPE && 1193 if (i == IPV6_SADDR_RULE_SCOPE &&
@@ -1400,6 +1427,20 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
1400 1427
1401void addrconf_dad_failure(struct inet6_ifaddr *ifp) 1428void addrconf_dad_failure(struct inet6_ifaddr *ifp)
1402{ 1429{
1430 struct inet6_dev *idev = ifp->idev;
1431 if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) {
1432 struct in6_addr addr;
1433
1434 addr.s6_addr32[0] = htonl(0xfe800000);
1435 addr.s6_addr32[1] = 0;
1436
1437 if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) &&
1438 ipv6_addr_equal(&ifp->addr, &addr)) {
1439 /* DAD failed for link-local based on MAC address */
1440 idev->cnf.disable_ipv6 = 1;
1441 }
1442 }
1443
1403 if (net_ratelimit()) 1444 if (net_ratelimit())
1404 printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name); 1445 printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
1405 addrconf_dad_stop(ifp); 1446 addrconf_dad_stop(ifp);
@@ -1788,7 +1829,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
1788 rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL, 1829 rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL,
1789 dev->ifindex, 1); 1830 dev->ifindex, 1);
1790 1831
1791 if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { 1832 if (rt && addrconf_is_prefix_route(rt)) {
1792 /* Autoconf prefix route */ 1833 /* Autoconf prefix route */
1793 if (valid_lft == 0) { 1834 if (valid_lft == 0) {
1794 ip6_del_rt(rt); 1835 ip6_del_rt(rt);
@@ -1822,6 +1863,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
1822 struct inet6_ifaddr * ifp; 1863 struct inet6_ifaddr * ifp;
1823 struct in6_addr addr; 1864 struct in6_addr addr;
1824 int create = 0, update_lft = 0; 1865 int create = 0, update_lft = 0;
1866 struct net *net = dev_net(dev);
1825 1867
1826 if (pinfo->prefix_len == 64) { 1868 if (pinfo->prefix_len == 64) {
1827 memcpy(&addr, &pinfo->prefix, 8); 1869 memcpy(&addr, &pinfo->prefix, 8);
@@ -1840,7 +1882,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
1840 1882
1841ok: 1883ok:
1842 1884
1843 ifp = ipv6_get_ifaddr(dev_net(dev), &addr, dev, 1); 1885 ifp = ipv6_get_ifaddr(net, &addr, dev, 1);
1844 1886
1845 if (ifp == NULL && valid_lft) { 1887 if (ifp == NULL && valid_lft) {
1846 int max_addresses = in6_dev->cnf.max_addresses; 1888 int max_addresses = in6_dev->cnf.max_addresses;
@@ -1848,7 +1890,7 @@ ok:
1848 1890
1849#ifdef CONFIG_IPV6_OPTIMISTIC_DAD 1891#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
1850 if (in6_dev->cnf.optimistic_dad && 1892 if (in6_dev->cnf.optimistic_dad &&
1851 !ipv6_devconf.forwarding) 1893 !net->ipv6.devconf_all->forwarding)
1852 addr_flags = IFA_F_OPTIMISTIC; 1894 addr_flags = IFA_F_OPTIMISTIC;
1853#endif 1895#endif
1854 1896
@@ -2277,7 +2319,7 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr
2277 2319
2278#ifdef CONFIG_IPV6_OPTIMISTIC_DAD 2320#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
2279 if (idev->cnf.optimistic_dad && 2321 if (idev->cnf.optimistic_dad &&
2280 !ipv6_devconf.forwarding) 2322 !dev_net(idev->dev)->ipv6.devconf_all->forwarding)
2281 addr_flags |= IFA_F_OPTIMISTIC; 2323 addr_flags |= IFA_F_OPTIMISTIC;
2282#endif 2324#endif
2283 2325
@@ -2732,6 +2774,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
2732 spin_lock_bh(&ifp->lock); 2774 spin_lock_bh(&ifp->lock);
2733 2775
2734 if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || 2776 if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
2777 idev->cnf.accept_dad < 1 ||
2735 !(ifp->flags&IFA_F_TENTATIVE) || 2778 !(ifp->flags&IFA_F_TENTATIVE) ||
2736 ifp->flags & IFA_F_NODAD) { 2779 ifp->flags & IFA_F_NODAD) {
2737 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); 2780 ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC);
@@ -2779,6 +2822,11 @@ static void addrconf_dad_timer(unsigned long data)
2779 read_unlock_bh(&idev->lock); 2822 read_unlock_bh(&idev->lock);
2780 goto out; 2823 goto out;
2781 } 2824 }
2825 if (idev->cnf.accept_dad > 1 && idev->cnf.disable_ipv6) {
2826 read_unlock_bh(&idev->lock);
2827 addrconf_dad_failure(ifp);
2828 return;
2829 }
2782 spin_lock_bh(&ifp->lock); 2830 spin_lock_bh(&ifp->lock);
2783 if (ifp->probes == 0) { 2831 if (ifp->probes == 0) {
2784 /* 2832 /*
@@ -3638,6 +3686,8 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
3638#ifdef CONFIG_IPV6_MROUTE 3686#ifdef CONFIG_IPV6_MROUTE
3639 array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding; 3687 array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
3640#endif 3688#endif
3689 array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
3690 array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
3641} 3691}
3642 3692
3643static inline size_t inet6_if_nlmsg_size(void) 3693static inline size_t inet6_if_nlmsg_size(void)
@@ -4197,6 +4247,22 @@ static struct addrconf_sysctl_table
4197 }, 4247 },
4198#endif 4248#endif
4199 { 4249 {
4250 .ctl_name = CTL_UNNUMBERED,
4251 .procname = "disable_ipv6",
4252 .data = &ipv6_devconf.disable_ipv6,
4253 .maxlen = sizeof(int),
4254 .mode = 0644,
4255 .proc_handler = &proc_dointvec,
4256 },
4257 {
4258 .ctl_name = CTL_UNNUMBERED,
4259 .procname = "accept_dad",
4260 .data = &ipv6_devconf.accept_dad,
4261 .maxlen = sizeof(int),
4262 .mode = 0644,
4263 .proc_handler = &proc_dointvec,
4264 },
4265 {
4200 .ctl_name = 0, /* sentinel */ 4266 .ctl_name = 0, /* sentinel */
4201 } 4267 }
4202 }, 4268 },