Skip to content

Commit 44d28ab

Browse files
committed
Merge branch 'net-next-2.6-v6ready-20080703' of git://git.linux-ipv6.org/gitroot/yoshfuji/linux-2.6-next
2 parents 40b215e + e0835f8 commit 44d28ab

File tree

13 files changed

+223
-26
lines changed

13 files changed

+223
-26
lines changed

Documentation/networking/ip-sysctl.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,17 @@ max_addresses - INTEGER
10251025
autoconfigured addresses.
10261026
Default: 16
10271027

1028+
disable_ipv6 - BOOLEAN
1029+
Disable IPv6 operation.
1030+
Default: FALSE (enable IPv6 operation)
1031+
1032+
accept_dad - INTEGER
1033+
Whether to accept DAD (Duplicate Address Detection).
1034+
0: Disable DAD
1035+
1: Enable DAD (default)
1036+
2: Enable DAD, and disable IPv6 operation if MAC-based duplicate
1037+
link-local address has been found.
1038+
10281039
icmp/*:
10291040
ratelimit - INTEGER
10301041
Limit the maximal rates for sending ICMPv6 packets.

include/linux/igmp.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,6 @@ extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
228228
extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
229229
struct group_filter __user *optval, int __user *optlen);
230230
extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt, int dif);
231-
extern void ip_mr_init(void);
232231
extern void ip_mc_init_dev(struct in_device *);
233232
extern void ip_mc_destroy_dev(struct in_device *);
234233
extern void ip_mc_up(struct in_device *);

include/linux/ipv6.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ struct ipv6_devconf {
163163
#ifdef CONFIG_IPV6_MROUTE
164164
__s32 mc_forwarding;
165165
#endif
166+
__s32 disable_ipv6;
167+
__s32 accept_dad;
166168
void *sysctl;
167169
};
168170

@@ -194,6 +196,8 @@ enum {
194196
DEVCONF_OPTIMISTIC_DAD,
195197
DEVCONF_ACCEPT_SOURCE_ROUTE,
196198
DEVCONF_MC_FORWARDING,
199+
DEVCONF_DISABLE_IPV6,
200+
DEVCONF_ACCEPT_DAD,
197201
DEVCONF_MAX
198202
};
199203

include/linux/mroute.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,37 @@ static inline int ip_mroute_opt(int opt)
144144
}
145145
#endif
146146

147+
#ifdef CONFIG_IP_MROUTE
147148
extern int ip_mroute_setsockopt(struct sock *, int, char __user *, int);
148149
extern int ip_mroute_getsockopt(struct sock *, int, char __user *, int __user *);
149150
extern int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg);
150-
extern void ip_mr_init(void);
151+
extern int ip_mr_init(void);
152+
#else
153+
static inline
154+
int ip_mroute_setsockopt(struct sock *sock,
155+
int optname, char __user *optval, int optlen)
156+
{
157+
return -ENOPROTOOPT;
158+
}
159+
160+
static inline
161+
int ip_mroute_getsockopt(struct sock *sock,
162+
int optname, char __user *optval, int __user *optlen)
163+
{
164+
return -ENOPROTOOPT;
165+
}
151166

167+
static inline
168+
int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
169+
{
170+
return -ENOIOCTLCMD;
171+
}
172+
173+
static inline int ip_mr_init(void)
174+
{
175+
return 0;
176+
}
177+
#endif
152178

153179
struct vif_device
154180
{

include/linux/mroute6.h

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,44 @@ static inline int ip6_mroute_opt(int opt)
131131

132132
struct sock;
133133

134+
#ifdef CONFIG_IPV6_MROUTE
134135
extern int ip6_mroute_setsockopt(struct sock *, int, char __user *, int);
135136
extern int ip6_mroute_getsockopt(struct sock *, int, char __user *, int __user *);
136137
extern int ip6_mr_input(struct sk_buff *skb);
137138
extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg);
138-
extern void ip6_mr_init(void);
139+
extern int ip6_mr_init(void);
140+
extern void ip6_mr_cleanup(void);
141+
#else
142+
static inline
143+
int ip6_mroute_setsockopt(struct sock *sock,
144+
int optname, char __user *optval, int optlen)
145+
{
146+
return -ENOPROTOOPT;
147+
}
148+
149+
static inline
150+
int ip6_mroute_getsockopt(struct sock *sock,
151+
int optname, char __user *optval, int __user *optlen)
152+
{
153+
return -ENOPROTOOPT;
154+
}
155+
156+
static inline
157+
int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
158+
{
159+
return -ENOIOCTLCMD;
160+
}
161+
162+
static inline int ip6_mr_init(void)
163+
{
164+
return 0;
165+
}
166+
167+
static inline void ip6_mr_cleanup(void)
168+
{
169+
return;
170+
}
171+
#endif
139172

140173
struct mif_device
141174
{

net/ipv4/af_inet.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,14 +1479,15 @@ static int __init inet_init(void)
14791479
* Initialise the multicast router
14801480
*/
14811481
#if defined(CONFIG_IP_MROUTE)
1482-
ip_mr_init();
1482+
if (ip_mr_init())
1483+
printk(KERN_CRIT "inet_init: Cannot init ipv4 mroute\n");
14831484
#endif
14841485
/*
14851486
* Initialise per-cpu ipv4 mibs
14861487
*/
14871488

14881489
if (init_ipv4_mibs())
1489-
printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ;
1490+
printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n");
14901491

14911492
ipv4_proc_init();
14921493

net/ipv4/ipmr.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,16 +1878,36 @@ static struct net_protocol pim_protocol = {
18781878
* Setup for IP multicast routing
18791879
*/
18801880

1881-
void __init ip_mr_init(void)
1881+
int __init ip_mr_init(void)
18821882
{
1883+
int err;
1884+
18831885
mrt_cachep = kmem_cache_create("ip_mrt_cache",
18841886
sizeof(struct mfc_cache),
18851887
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
18861888
NULL);
1889+
if (!mrt_cachep)
1890+
return -ENOMEM;
1891+
18871892
setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
1888-
register_netdevice_notifier(&ip_mr_notifier);
1893+
err = register_netdevice_notifier(&ip_mr_notifier);
1894+
if (err)
1895+
goto reg_notif_fail;
18891896
#ifdef CONFIG_PROC_FS
1890-
proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops);
1891-
proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops);
1897+
err = -ENOMEM;
1898+
if (!proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops))
1899+
goto proc_vif_fail;
1900+
if (!proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops))
1901+
goto proc_cache_fail;
18921902
#endif
1903+
return 0;
1904+
reg_notif_fail:
1905+
kmem_cache_destroy(mrt_cachep);
1906+
#ifdef CONFIG_PROC_FS
1907+
proc_vif_fail:
1908+
unregister_netdevice_notifier(&ip_mr_notifier);
1909+
proc_cache_fail:
1910+
proc_net_remove(&init_net, "ip_mr_vif");
1911+
#endif
1912+
return err;
18931913
}

net/ipv6/addrconf.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ static void ipv6_regen_rndid(unsigned long data);
119119
static int desync_factor = MAX_DESYNC_FACTOR * HZ;
120120
#endif
121121

122+
static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
122123
static int ipv6_count_addresses(struct inet6_dev *idev);
123124

124125
/*
@@ -183,6 +184,8 @@ struct ipv6_devconf ipv6_devconf __read_mostly = {
183184
#endif
184185
.proxy_ndp = 0,
185186
.accept_source_route = 0, /* we do not accept RH0 by default. */
187+
.disable_ipv6 = 0,
188+
.accept_dad = 1,
186189
};
187190

188191
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -215,6 +218,8 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
215218
#endif
216219
.proxy_ndp = 0,
217220
.accept_source_route = 0, /* we do not accept RH0 by default. */
221+
.disable_ipv6 = 0,
222+
.accept_dad = 1,
218223
};
219224

220225
/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -378,6 +383,9 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
378383
*/
379384
in6_dev_hold(ndev);
380385

386+
if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
387+
ndev->cnf.accept_dad = -1;
388+
381389
#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
382390
if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) {
383391
printk(KERN_INFO
@@ -578,6 +586,13 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
578586
struct rt6_info *rt;
579587
int hash;
580588
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);
581596

582597
rcu_read_lock_bh();
583598
if (idev->dead) {
@@ -1412,6 +1427,20 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
14121427

14131428
void addrconf_dad_failure(struct inet6_ifaddr *ifp)
14141429
{
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+
14151444
if (net_ratelimit())
14161445
printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
14171446
addrconf_dad_stop(ifp);
@@ -2744,6 +2773,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
27442773
spin_lock_bh(&ifp->lock);
27452774

27462775
if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
2776+
idev->cnf.accept_dad < 1 ||
27472777
!(ifp->flags&IFA_F_TENTATIVE) ||
27482778
ifp->flags & IFA_F_NODAD) {
27492779
ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC);
@@ -2791,6 +2821,11 @@ static void addrconf_dad_timer(unsigned long data)
27912821
read_unlock_bh(&idev->lock);
27922822
goto out;
27932823
}
2824+
if (idev->cnf.accept_dad > 1 && idev->cnf.disable_ipv6) {
2825+
read_unlock_bh(&idev->lock);
2826+
addrconf_dad_failure(ifp);
2827+
return;
2828+
}
27942829
spin_lock_bh(&ifp->lock);
27952830
if (ifp->probes == 0) {
27962831
/*
@@ -3650,6 +3685,8 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
36503685
#ifdef CONFIG_IPV6_MROUTE
36513686
array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
36523687
#endif
3688+
array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
3689+
array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
36533690
}
36543691

36553692
static inline size_t inet6_if_nlmsg_size(void)
@@ -4208,6 +4245,22 @@ static struct addrconf_sysctl_table
42084245
.proc_handler = &proc_dointvec,
42094246
},
42104247
#endif
4248+
{
4249+
.ctl_name = CTL_UNNUMBERED,
4250+
.procname = "disable_ipv6",
4251+
.data = &ipv6_devconf.disable_ipv6,
4252+
.maxlen = sizeof(int),
4253+
.mode = 0644,
4254+
.proc_handler = &proc_dointvec,
4255+
},
4256+
{
4257+
.ctl_name = CTL_UNNUMBERED,
4258+
.procname = "accept_dad",
4259+
.data = &ipv6_devconf.accept_dad,
4260+
.maxlen = sizeof(int),
4261+
.mode = 0644,
4262+
.proc_handler = &proc_dointvec,
4263+
},
42114264
{
42124265
.ctl_name = 0, /* sentinel */
42134266
}

net/ipv6/af_inet6.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,7 @@
5959

6060
#include <asm/uaccess.h>
6161
#include <asm/system.h>
62-
#ifdef CONFIG_IPV6_MROUTE
6362
#include <linux/mroute6.h>
64-
#endif
6563

6664
MODULE_AUTHOR("Cast of dozens");
6765
MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
@@ -952,9 +950,9 @@ static int __init inet6_init(void)
952950
err = icmpv6_init();
953951
if (err)
954952
goto icmp_fail;
955-
#ifdef CONFIG_IPV6_MROUTE
956-
ip6_mr_init();
957-
#endif
953+
err = ip6_mr_init();
954+
if (err)
955+
goto ipmr_fail;
958956
err = ndisc_init();
959957
if (err)
960958
goto ndisc_fail;
@@ -1057,6 +1055,8 @@ static int __init inet6_init(void)
10571055
igmp_fail:
10581056
ndisc_cleanup();
10591057
ndisc_fail:
1058+
ip6_mr_cleanup();
1059+
ipmr_fail:
10601060
icmpv6_cleanup();
10611061
icmp_fail:
10621062
unregister_pernet_subsys(&inet6_net_ops);
@@ -1111,6 +1111,7 @@ static void __exit inet6_exit(void)
11111111
ipv6_netfilter_fini();
11121112
igmp6_cleanup();
11131113
ndisc_cleanup();
1114+
ip6_mr_cleanup();
11141115
icmpv6_cleanup();
11151116
rawv6_exit();
11161117

net/ipv6/ip6_input.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
7171

7272
IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES);
7373

74-
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
74+
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
75+
!idev || unlikely(idev->cnf.disable_ipv6)) {
7576
IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS);
7677
rcu_read_unlock();
7778
goto out;

0 commit comments

Comments
 (0)