Merge branch 'net-next-2.6-v6ready-20080703' of git://git.linux-ipv6.org/gitroot/yoshfuji/linux-2.6-next
This commit is contained in:
commit
44d28ab19c
|
@ -1025,6 +1025,17 @@ max_addresses - INTEGER
|
||||||
autoconfigured addresses.
|
autoconfigured addresses.
|
||||||
Default: 16
|
Default: 16
|
||||||
|
|
||||||
|
disable_ipv6 - BOOLEAN
|
||||||
|
Disable IPv6 operation.
|
||||||
|
Default: FALSE (enable IPv6 operation)
|
||||||
|
|
||||||
|
accept_dad - INTEGER
|
||||||
|
Whether to accept DAD (Duplicate Address Detection).
|
||||||
|
0: Disable DAD
|
||||||
|
1: Enable DAD (default)
|
||||||
|
2: Enable DAD, and disable IPv6 operation if MAC-based duplicate
|
||||||
|
link-local address has been found.
|
||||||
|
|
||||||
icmp/*:
|
icmp/*:
|
||||||
ratelimit - INTEGER
|
ratelimit - INTEGER
|
||||||
Limit the maximal rates for sending ICMPv6 packets.
|
Limit the maximal rates for sending ICMPv6 packets.
|
||||||
|
|
|
@ -228,7 +228,6 @@ extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
|
||||||
extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
|
extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
|
||||||
struct group_filter __user *optval, int __user *optlen);
|
struct group_filter __user *optval, int __user *optlen);
|
||||||
extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt, int dif);
|
extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt, int dif);
|
||||||
extern void ip_mr_init(void);
|
|
||||||
extern void ip_mc_init_dev(struct in_device *);
|
extern void ip_mc_init_dev(struct in_device *);
|
||||||
extern void ip_mc_destroy_dev(struct in_device *);
|
extern void ip_mc_destroy_dev(struct in_device *);
|
||||||
extern void ip_mc_up(struct in_device *);
|
extern void ip_mc_up(struct in_device *);
|
||||||
|
|
|
@ -163,6 +163,8 @@ struct ipv6_devconf {
|
||||||
#ifdef CONFIG_IPV6_MROUTE
|
#ifdef CONFIG_IPV6_MROUTE
|
||||||
__s32 mc_forwarding;
|
__s32 mc_forwarding;
|
||||||
#endif
|
#endif
|
||||||
|
__s32 disable_ipv6;
|
||||||
|
__s32 accept_dad;
|
||||||
void *sysctl;
|
void *sysctl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -194,6 +196,8 @@ enum {
|
||||||
DEVCONF_OPTIMISTIC_DAD,
|
DEVCONF_OPTIMISTIC_DAD,
|
||||||
DEVCONF_ACCEPT_SOURCE_ROUTE,
|
DEVCONF_ACCEPT_SOURCE_ROUTE,
|
||||||
DEVCONF_MC_FORWARDING,
|
DEVCONF_MC_FORWARDING,
|
||||||
|
DEVCONF_DISABLE_IPV6,
|
||||||
|
DEVCONF_ACCEPT_DAD,
|
||||||
DEVCONF_MAX
|
DEVCONF_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -144,11 +144,37 @@ static inline int ip_mroute_opt(int opt)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_IP_MROUTE
|
||||||
extern int ip_mroute_setsockopt(struct sock *, int, char __user *, int);
|
extern int ip_mroute_setsockopt(struct sock *, int, char __user *, int);
|
||||||
extern int ip_mroute_getsockopt(struct sock *, int, char __user *, int __user *);
|
extern int ip_mroute_getsockopt(struct sock *, int, char __user *, int __user *);
|
||||||
extern int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg);
|
extern int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg);
|
||||||
extern void ip_mr_init(void);
|
extern int ip_mr_init(void);
|
||||||
|
#else
|
||||||
|
static inline
|
||||||
|
int ip_mroute_setsockopt(struct sock *sock,
|
||||||
|
int optname, char __user *optval, int optlen)
|
||||||
|
{
|
||||||
|
return -ENOPROTOOPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
int ip_mroute_getsockopt(struct sock *sock,
|
||||||
|
int optname, char __user *optval, int __user *optlen)
|
||||||
|
{
|
||||||
|
return -ENOPROTOOPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
|
||||||
|
{
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ip_mr_init(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct vif_device
|
struct vif_device
|
||||||
{
|
{
|
||||||
|
|
|
@ -131,11 +131,44 @@ static inline int ip6_mroute_opt(int opt)
|
||||||
|
|
||||||
struct sock;
|
struct sock;
|
||||||
|
|
||||||
|
#ifdef CONFIG_IPV6_MROUTE
|
||||||
extern int ip6_mroute_setsockopt(struct sock *, int, char __user *, int);
|
extern int ip6_mroute_setsockopt(struct sock *, int, char __user *, int);
|
||||||
extern int ip6_mroute_getsockopt(struct sock *, int, char __user *, int __user *);
|
extern int ip6_mroute_getsockopt(struct sock *, int, char __user *, int __user *);
|
||||||
extern int ip6_mr_input(struct sk_buff *skb);
|
extern int ip6_mr_input(struct sk_buff *skb);
|
||||||
extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg);
|
extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg);
|
||||||
extern void ip6_mr_init(void);
|
extern int ip6_mr_init(void);
|
||||||
|
extern void ip6_mr_cleanup(void);
|
||||||
|
#else
|
||||||
|
static inline
|
||||||
|
int ip6_mroute_setsockopt(struct sock *sock,
|
||||||
|
int optname, char __user *optval, int optlen)
|
||||||
|
{
|
||||||
|
return -ENOPROTOOPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
int ip6_mroute_getsockopt(struct sock *sock,
|
||||||
|
int optname, char __user *optval, int __user *optlen)
|
||||||
|
{
|
||||||
|
return -ENOPROTOOPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
|
||||||
|
{
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ip6_mr_init(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ip6_mr_cleanup(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct mif_device
|
struct mif_device
|
||||||
{
|
{
|
||||||
|
|
|
@ -1479,14 +1479,15 @@ static int __init inet_init(void)
|
||||||
* Initialise the multicast router
|
* Initialise the multicast router
|
||||||
*/
|
*/
|
||||||
#if defined(CONFIG_IP_MROUTE)
|
#if defined(CONFIG_IP_MROUTE)
|
||||||
ip_mr_init();
|
if (ip_mr_init())
|
||||||
|
printk(KERN_CRIT "inet_init: Cannot init ipv4 mroute\n");
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* Initialise per-cpu ipv4 mibs
|
* Initialise per-cpu ipv4 mibs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (init_ipv4_mibs())
|
if (init_ipv4_mibs())
|
||||||
printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ;
|
printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n");
|
||||||
|
|
||||||
ipv4_proc_init();
|
ipv4_proc_init();
|
||||||
|
|
||||||
|
|
|
@ -1878,16 +1878,36 @@ static struct net_protocol pim_protocol = {
|
||||||
* Setup for IP multicast routing
|
* Setup for IP multicast routing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void __init ip_mr_init(void)
|
int __init ip_mr_init(void)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
mrt_cachep = kmem_cache_create("ip_mrt_cache",
|
mrt_cachep = kmem_cache_create("ip_mrt_cache",
|
||||||
sizeof(struct mfc_cache),
|
sizeof(struct mfc_cache),
|
||||||
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
|
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
|
||||||
NULL);
|
NULL);
|
||||||
|
if (!mrt_cachep)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
|
setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
|
||||||
register_netdevice_notifier(&ip_mr_notifier);
|
err = register_netdevice_notifier(&ip_mr_notifier);
|
||||||
|
if (err)
|
||||||
|
goto reg_notif_fail;
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops);
|
err = -ENOMEM;
|
||||||
proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops);
|
if (!proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops))
|
||||||
|
goto proc_vif_fail;
|
||||||
|
if (!proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops))
|
||||||
|
goto proc_cache_fail;
|
||||||
#endif
|
#endif
|
||||||
|
return 0;
|
||||||
|
reg_notif_fail:
|
||||||
|
kmem_cache_destroy(mrt_cachep);
|
||||||
|
#ifdef CONFIG_PROC_FS
|
||||||
|
proc_vif_fail:
|
||||||
|
unregister_netdevice_notifier(&ip_mr_notifier);
|
||||||
|
proc_cache_fail:
|
||||||
|
proc_net_remove(&init_net, "ip_mr_vif");
|
||||||
|
#endif
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,7 @@ static void ipv6_regen_rndid(unsigned long data);
|
||||||
static int desync_factor = MAX_DESYNC_FACTOR * HZ;
|
static int desync_factor = MAX_DESYNC_FACTOR * HZ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
|
||||||
static int ipv6_count_addresses(struct inet6_dev *idev);
|
static int ipv6_count_addresses(struct inet6_dev *idev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -183,6 +184,8 @@ struct ipv6_devconf ipv6_devconf __read_mostly = {
|
||||||
#endif
|
#endif
|
||||||
.proxy_ndp = 0,
|
.proxy_ndp = 0,
|
||||||
.accept_source_route = 0, /* we do not accept RH0 by default. */
|
.accept_source_route = 0, /* we do not accept RH0 by default. */
|
||||||
|
.disable_ipv6 = 0,
|
||||||
|
.accept_dad = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
|
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
|
||||||
|
@ -215,6 +218,8 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
|
||||||
#endif
|
#endif
|
||||||
.proxy_ndp = 0,
|
.proxy_ndp = 0,
|
||||||
.accept_source_route = 0, /* we do not accept RH0 by default. */
|
.accept_source_route = 0, /* we do not accept RH0 by default. */
|
||||||
|
.disable_ipv6 = 0,
|
||||||
|
.accept_dad = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
|
/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
|
||||||
|
@ -378,6 +383,9 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
|
||||||
*/
|
*/
|
||||||
in6_dev_hold(ndev);
|
in6_dev_hold(ndev);
|
||||||
|
|
||||||
|
if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
|
||||||
|
ndev->cnf.accept_dad = -1;
|
||||||
|
|
||||||
#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
|
#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
|
||||||
if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) {
|
if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) {
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
|
@ -578,6 +586,13 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
|
||||||
struct rt6_info *rt;
|
struct rt6_info *rt;
|
||||||
int hash;
|
int hash;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
int addr_type = ipv6_addr_type(addr);
|
||||||
|
|
||||||
|
if (addr_type == IPV6_ADDR_ANY ||
|
||||||
|
addr_type & IPV6_ADDR_MULTICAST ||
|
||||||
|
(!(idev->dev->flags & IFF_LOOPBACK) &&
|
||||||
|
addr_type & IPV6_ADDR_LOOPBACK))
|
||||||
|
return ERR_PTR(-EADDRNOTAVAIL);
|
||||||
|
|
||||||
rcu_read_lock_bh();
|
rcu_read_lock_bh();
|
||||||
if (idev->dead) {
|
if (idev->dead) {
|
||||||
|
@ -1412,6 +1427,20 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
|
||||||
|
|
||||||
void addrconf_dad_failure(struct inet6_ifaddr *ifp)
|
void addrconf_dad_failure(struct inet6_ifaddr *ifp)
|
||||||
{
|
{
|
||||||
|
struct inet6_dev *idev = ifp->idev;
|
||||||
|
if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) {
|
||||||
|
struct in6_addr addr;
|
||||||
|
|
||||||
|
addr.s6_addr32[0] = htonl(0xfe800000);
|
||||||
|
addr.s6_addr32[1] = 0;
|
||||||
|
|
||||||
|
if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) &&
|
||||||
|
ipv6_addr_equal(&ifp->addr, &addr)) {
|
||||||
|
/* DAD failed for link-local based on MAC address */
|
||||||
|
idev->cnf.disable_ipv6 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
|
printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name);
|
||||||
addrconf_dad_stop(ifp);
|
addrconf_dad_stop(ifp);
|
||||||
|
@ -2744,6 +2773,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
|
||||||
spin_lock_bh(&ifp->lock);
|
spin_lock_bh(&ifp->lock);
|
||||||
|
|
||||||
if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
|
if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
|
||||||
|
idev->cnf.accept_dad < 1 ||
|
||||||
!(ifp->flags&IFA_F_TENTATIVE) ||
|
!(ifp->flags&IFA_F_TENTATIVE) ||
|
||||||
ifp->flags & IFA_F_NODAD) {
|
ifp->flags & IFA_F_NODAD) {
|
||||||
ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC);
|
ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC);
|
||||||
|
@ -2791,6 +2821,11 @@ static void addrconf_dad_timer(unsigned long data)
|
||||||
read_unlock_bh(&idev->lock);
|
read_unlock_bh(&idev->lock);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (idev->cnf.accept_dad > 1 && idev->cnf.disable_ipv6) {
|
||||||
|
read_unlock_bh(&idev->lock);
|
||||||
|
addrconf_dad_failure(ifp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
spin_lock_bh(&ifp->lock);
|
spin_lock_bh(&ifp->lock);
|
||||||
if (ifp->probes == 0) {
|
if (ifp->probes == 0) {
|
||||||
/*
|
/*
|
||||||
|
@ -3650,6 +3685,8 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
|
||||||
#ifdef CONFIG_IPV6_MROUTE
|
#ifdef CONFIG_IPV6_MROUTE
|
||||||
array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
|
array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
|
||||||
#endif
|
#endif
|
||||||
|
array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
|
||||||
|
array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t inet6_if_nlmsg_size(void)
|
static inline size_t inet6_if_nlmsg_size(void)
|
||||||
|
@ -4208,6 +4245,22 @@ static struct addrconf_sysctl_table
|
||||||
.proc_handler = &proc_dointvec,
|
.proc_handler = &proc_dointvec,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
.ctl_name = CTL_UNNUMBERED,
|
||||||
|
.procname = "disable_ipv6",
|
||||||
|
.data = &ipv6_devconf.disable_ipv6,
|
||||||
|
.maxlen = sizeof(int),
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = &proc_dointvec,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctl_name = CTL_UNNUMBERED,
|
||||||
|
.procname = "accept_dad",
|
||||||
|
.data = &ipv6_devconf.accept_dad,
|
||||||
|
.maxlen = sizeof(int),
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = &proc_dointvec,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.ctl_name = 0, /* sentinel */
|
.ctl_name = 0, /* sentinel */
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,9 +59,7 @@
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#ifdef CONFIG_IPV6_MROUTE
|
|
||||||
#include <linux/mroute6.h>
|
#include <linux/mroute6.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Cast of dozens");
|
MODULE_AUTHOR("Cast of dozens");
|
||||||
MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
|
MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
|
||||||
|
@ -952,9 +950,9 @@ static int __init inet6_init(void)
|
||||||
err = icmpv6_init();
|
err = icmpv6_init();
|
||||||
if (err)
|
if (err)
|
||||||
goto icmp_fail;
|
goto icmp_fail;
|
||||||
#ifdef CONFIG_IPV6_MROUTE
|
err = ip6_mr_init();
|
||||||
ip6_mr_init();
|
if (err)
|
||||||
#endif
|
goto ipmr_fail;
|
||||||
err = ndisc_init();
|
err = ndisc_init();
|
||||||
if (err)
|
if (err)
|
||||||
goto ndisc_fail;
|
goto ndisc_fail;
|
||||||
|
@ -1057,6 +1055,8 @@ netfilter_fail:
|
||||||
igmp_fail:
|
igmp_fail:
|
||||||
ndisc_cleanup();
|
ndisc_cleanup();
|
||||||
ndisc_fail:
|
ndisc_fail:
|
||||||
|
ip6_mr_cleanup();
|
||||||
|
ipmr_fail:
|
||||||
icmpv6_cleanup();
|
icmpv6_cleanup();
|
||||||
icmp_fail:
|
icmp_fail:
|
||||||
unregister_pernet_subsys(&inet6_net_ops);
|
unregister_pernet_subsys(&inet6_net_ops);
|
||||||
|
@ -1111,6 +1111,7 @@ static void __exit inet6_exit(void)
|
||||||
ipv6_netfilter_fini();
|
ipv6_netfilter_fini();
|
||||||
igmp6_cleanup();
|
igmp6_cleanup();
|
||||||
ndisc_cleanup();
|
ndisc_cleanup();
|
||||||
|
ip6_mr_cleanup();
|
||||||
icmpv6_cleanup();
|
icmpv6_cleanup();
|
||||||
rawv6_exit();
|
rawv6_exit();
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,8 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
|
||||||
|
|
||||||
IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES);
|
IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES);
|
||||||
|
|
||||||
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
|
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
|
||||||
|
!idev || unlikely(idev->cnf.disable_ipv6)) {
|
||||||
IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS);
|
IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -173,6 +173,13 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
|
||||||
|
|
||||||
int ip6_output(struct sk_buff *skb)
|
int ip6_output(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
struct inet6_dev *idev = ip6_dst_idev(skb->dst);
|
||||||
|
if (unlikely(idev->cnf.disable_ipv6)) {
|
||||||
|
IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS);
|
||||||
|
kfree_skb(skb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
|
if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
|
||||||
dst_allfrag(skb->dst))
|
dst_allfrag(skb->dst))
|
||||||
return ip6_fragment(skb, ip6_output2);
|
return ip6_fragment(skb, ip6_output2);
|
||||||
|
@ -498,7 +505,8 @@ int ip6_forward(struct sk_buff *skb)
|
||||||
int addrtype = ipv6_addr_type(&hdr->saddr);
|
int addrtype = ipv6_addr_type(&hdr->saddr);
|
||||||
|
|
||||||
/* This check is security critical. */
|
/* This check is security critical. */
|
||||||
if (addrtype & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK))
|
if (addrtype == IPV6_ADDR_ANY ||
|
||||||
|
addrtype & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LOOPBACK))
|
||||||
goto error;
|
goto error;
|
||||||
if (addrtype & IPV6_ADDR_LINKLOCAL) {
|
if (addrtype & IPV6_ADDR_LINKLOCAL) {
|
||||||
icmpv6_send(skb, ICMPV6_DEST_UNREACH,
|
icmpv6_send(skb, ICMPV6_DEST_UNREACH,
|
||||||
|
|
|
@ -948,23 +948,51 @@ static struct notifier_block ip6_mr_notifier = {
|
||||||
* Setup for IP multicast routing
|
* Setup for IP multicast routing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void __init ip6_mr_init(void)
|
int __init ip6_mr_init(void)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
mrt_cachep = kmem_cache_create("ip6_mrt_cache",
|
mrt_cachep = kmem_cache_create("ip6_mrt_cache",
|
||||||
sizeof(struct mfc6_cache),
|
sizeof(struct mfc6_cache),
|
||||||
0, SLAB_HWCACHE_ALIGN,
|
0, SLAB_HWCACHE_ALIGN,
|
||||||
NULL);
|
NULL);
|
||||||
if (!mrt_cachep)
|
if (!mrt_cachep)
|
||||||
panic("cannot allocate ip6_mrt_cache");
|
return -ENOMEM;
|
||||||
|
|
||||||
setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
|
setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
|
||||||
register_netdevice_notifier(&ip6_mr_notifier);
|
err = register_netdevice_notifier(&ip6_mr_notifier);
|
||||||
|
if (err)
|
||||||
|
goto reg_notif_fail;
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops);
|
err = -ENOMEM;
|
||||||
proc_net_fops_create(&init_net, "ip6_mr_cache", 0, &ip6mr_mfc_fops);
|
if (!proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops))
|
||||||
|
goto proc_vif_fail;
|
||||||
|
if (!proc_net_fops_create(&init_net, "ip6_mr_cache",
|
||||||
|
0, &ip6mr_mfc_fops))
|
||||||
|
goto proc_cache_fail;
|
||||||
#endif
|
#endif
|
||||||
|
return 0;
|
||||||
|
reg_notif_fail:
|
||||||
|
kmem_cache_destroy(mrt_cachep);
|
||||||
|
#ifdef CONFIG_PROC_FS
|
||||||
|
proc_vif_fail:
|
||||||
|
unregister_netdevice_notifier(&ip6_mr_notifier);
|
||||||
|
proc_cache_fail:
|
||||||
|
proc_net_remove(&init_net, "ip6_mr_vif");
|
||||||
|
#endif
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ip6_mr_cleanup(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_PROC_FS
|
||||||
|
proc_net_remove(&init_net, "ip6_mr_cache");
|
||||||
|
proc_net_remove(&init_net, "ip6_mr_vif");
|
||||||
|
#endif
|
||||||
|
unregister_netdevice_notifier(&ip6_mr_notifier);
|
||||||
|
del_timer(&ipmr_expire_timer);
|
||||||
|
kmem_cache_destroy(mrt_cachep);
|
||||||
|
}
|
||||||
|
|
||||||
static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
|
static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
|
||||||
{
|
{
|
||||||
|
|
|
@ -228,7 +228,7 @@ static __inline__ int rt6_check_expired(const struct rt6_info *rt)
|
||||||
static inline int rt6_need_strict(struct in6_addr *daddr)
|
static inline int rt6_need_strict(struct in6_addr *daddr)
|
||||||
{
|
{
|
||||||
return (ipv6_addr_type(daddr) &
|
return (ipv6_addr_type(daddr) &
|
||||||
(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
|
(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -237,15 +237,20 @@ static inline int rt6_need_strict(struct in6_addr *daddr)
|
||||||
|
|
||||||
static inline struct rt6_info *rt6_device_match(struct net *net,
|
static inline struct rt6_info *rt6_device_match(struct net *net,
|
||||||
struct rt6_info *rt,
|
struct rt6_info *rt,
|
||||||
|
struct in6_addr *saddr,
|
||||||
int oif,
|
int oif,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
struct rt6_info *local = NULL;
|
struct rt6_info *local = NULL;
|
||||||
struct rt6_info *sprt;
|
struct rt6_info *sprt;
|
||||||
|
|
||||||
if (oif) {
|
if (!oif && ipv6_addr_any(saddr))
|
||||||
for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) {
|
goto out;
|
||||||
struct net_device *dev = sprt->rt6i_dev;
|
|
||||||
|
for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) {
|
||||||
|
struct net_device *dev = sprt->rt6i_dev;
|
||||||
|
|
||||||
|
if (oif) {
|
||||||
if (dev->ifindex == oif)
|
if (dev->ifindex == oif)
|
||||||
return sprt;
|
return sprt;
|
||||||
if (dev->flags & IFF_LOOPBACK) {
|
if (dev->flags & IFF_LOOPBACK) {
|
||||||
|
@ -259,14 +264,21 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
|
||||||
}
|
}
|
||||||
local = sprt;
|
local = sprt;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (ipv6_chk_addr(net, saddr, dev,
|
||||||
|
flags & RT6_LOOKUP_F_IFACE))
|
||||||
|
return sprt;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oif) {
|
||||||
if (local)
|
if (local)
|
||||||
return local;
|
return local;
|
||||||
|
|
||||||
if (flags & RT6_LOOKUP_F_IFACE)
|
if (flags & RT6_LOOKUP_F_IFACE)
|
||||||
return net->ipv6.ip6_null_entry;
|
return net->ipv6.ip6_null_entry;
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,7 +551,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
|
||||||
fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
|
fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
|
||||||
restart:
|
restart:
|
||||||
rt = fn->leaf;
|
rt = fn->leaf;
|
||||||
rt = rt6_device_match(net, rt, fl->oif, flags);
|
rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags);
|
||||||
BACKTRACK(net, &fl->fl6_src);
|
BACKTRACK(net, &fl->fl6_src);
|
||||||
out:
|
out:
|
||||||
dst_use(&rt->u.dst, jiffies);
|
dst_use(&rt->u.dst, jiffies);
|
||||||
|
|
Loading…
Reference in a new issue