Merge branch 'master' into for-next
This commit is contained in:
@@ -420,9 +420,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
|
||||
dev->type == ARPHRD_TUNNEL6 ||
|
||||
dev->type == ARPHRD_SIT ||
|
||||
dev->type == ARPHRD_NONE) {
|
||||
printk(KERN_INFO
|
||||
"%s: Disabled Privacy Extensions\n",
|
||||
dev->name);
|
||||
ndev->cnf.use_tempaddr = -1;
|
||||
} else {
|
||||
in6_dev_hold(ndev);
|
||||
@@ -2664,14 +2661,12 @@ static int addrconf_ifdown(struct net_device *dev, int how)
|
||||
struct net *net = dev_net(dev);
|
||||
struct inet6_dev *idev;
|
||||
struct inet6_ifaddr *ifa;
|
||||
LIST_HEAD(keep_list);
|
||||
int state;
|
||||
int state, i;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
/* Flush routes if device is being removed or it is not loopback */
|
||||
if (how || !(dev->flags & IFF_LOOPBACK))
|
||||
rt6_ifdown(net, dev);
|
||||
rt6_ifdown(net, dev);
|
||||
neigh_ifdown(&nd_tbl, dev);
|
||||
|
||||
idev = __in6_dev_get(dev);
|
||||
if (idev == NULL)
|
||||
@@ -2692,6 +2687,23 @@ static int addrconf_ifdown(struct net_device *dev, int how)
|
||||
|
||||
}
|
||||
|
||||
/* Step 2: clear hash table */
|
||||
for (i = 0; i < IN6_ADDR_HSIZE; i++) {
|
||||
struct hlist_head *h = &inet6_addr_lst[i];
|
||||
struct hlist_node *n;
|
||||
|
||||
spin_lock_bh(&addrconf_hash_lock);
|
||||
restart:
|
||||
hlist_for_each_entry_rcu(ifa, n, h, addr_lst) {
|
||||
if (ifa->idev == idev) {
|
||||
hlist_del_init_rcu(&ifa->addr_lst);
|
||||
addrconf_del_timer(ifa);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&addrconf_hash_lock);
|
||||
}
|
||||
|
||||
write_lock_bh(&idev->lock);
|
||||
|
||||
/* Step 2: clear flags for stateless addrconf */
|
||||
@@ -2725,52 +2737,23 @@ static int addrconf_ifdown(struct net_device *dev, int how)
|
||||
struct inet6_ifaddr, if_list);
|
||||
addrconf_del_timer(ifa);
|
||||
|
||||
/* If just doing link down, and address is permanent
|
||||
and not link-local, then retain it. */
|
||||
if (!how &&
|
||||
(ifa->flags&IFA_F_PERMANENT) &&
|
||||
!(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) {
|
||||
list_move_tail(&ifa->if_list, &keep_list);
|
||||
list_del(&ifa->if_list);
|
||||
|
||||
/* If not doing DAD on this address, just keep it. */
|
||||
if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) ||
|
||||
idev->cnf.accept_dad <= 0 ||
|
||||
(ifa->flags & IFA_F_NODAD))
|
||||
continue;
|
||||
write_unlock_bh(&idev->lock);
|
||||
|
||||
/* If it was tentative already, no need to notify */
|
||||
if (ifa->flags & IFA_F_TENTATIVE)
|
||||
continue;
|
||||
spin_lock_bh(&ifa->state_lock);
|
||||
state = ifa->state;
|
||||
ifa->state = INET6_IFADDR_STATE_DEAD;
|
||||
spin_unlock_bh(&ifa->state_lock);
|
||||
|
||||
/* Flag it for later restoration when link comes up */
|
||||
ifa->flags |= IFA_F_TENTATIVE;
|
||||
ifa->state = INET6_IFADDR_STATE_DAD;
|
||||
} else {
|
||||
list_del(&ifa->if_list);
|
||||
|
||||
/* clear hash table */
|
||||
spin_lock_bh(&addrconf_hash_lock);
|
||||
hlist_del_init_rcu(&ifa->addr_lst);
|
||||
spin_unlock_bh(&addrconf_hash_lock);
|
||||
|
||||
write_unlock_bh(&idev->lock);
|
||||
spin_lock_bh(&ifa->state_lock);
|
||||
state = ifa->state;
|
||||
ifa->state = INET6_IFADDR_STATE_DEAD;
|
||||
spin_unlock_bh(&ifa->state_lock);
|
||||
|
||||
if (state != INET6_IFADDR_STATE_DEAD) {
|
||||
__ipv6_ifa_notify(RTM_DELADDR, ifa);
|
||||
atomic_notifier_call_chain(&inet6addr_chain,
|
||||
NETDEV_DOWN, ifa);
|
||||
}
|
||||
|
||||
in6_ifa_put(ifa);
|
||||
write_lock_bh(&idev->lock);
|
||||
if (state != INET6_IFADDR_STATE_DEAD) {
|
||||
__ipv6_ifa_notify(RTM_DELADDR, ifa);
|
||||
atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa);
|
||||
}
|
||||
}
|
||||
in6_ifa_put(ifa);
|
||||
|
||||
list_splice(&keep_list, &idev->addr_list);
|
||||
write_lock_bh(&idev->lock);
|
||||
}
|
||||
|
||||
write_unlock_bh(&idev->lock);
|
||||
|
||||
@@ -4159,8 +4142,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
|
||||
addrconf_leave_solict(ifp->idev, &ifp->addr);
|
||||
dst_hold(&ifp->rt->dst);
|
||||
|
||||
if (ifp->state == INET6_IFADDR_STATE_DEAD &&
|
||||
ip6_del_rt(ifp->rt))
|
||||
if (ip6_del_rt(ifp->rt))
|
||||
dst_free(&ifp->rt->dst);
|
||||
break;
|
||||
}
|
||||
|
@@ -401,6 +401,9 @@ int ip6_forward(struct sk_buff *skb)
|
||||
goto drop;
|
||||
}
|
||||
|
||||
if (skb->pkt_type != PACKET_HOST)
|
||||
goto drop;
|
||||
|
||||
skb_forward_csum(skb);
|
||||
|
||||
/*
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/compat.h>
|
||||
#include <net/protocol.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/sock.h>
|
||||
@@ -1804,6 +1805,80 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct compat_sioc_sg_req6 {
|
||||
struct sockaddr_in6 src;
|
||||
struct sockaddr_in6 grp;
|
||||
compat_ulong_t pktcnt;
|
||||
compat_ulong_t bytecnt;
|
||||
compat_ulong_t wrong_if;
|
||||
};
|
||||
|
||||
struct compat_sioc_mif_req6 {
|
||||
mifi_t mifi;
|
||||
compat_ulong_t icount;
|
||||
compat_ulong_t ocount;
|
||||
compat_ulong_t ibytes;
|
||||
compat_ulong_t obytes;
|
||||
};
|
||||
|
||||
int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
|
||||
{
|
||||
struct compat_sioc_sg_req6 sr;
|
||||
struct compat_sioc_mif_req6 vr;
|
||||
struct mif_device *vif;
|
||||
struct mfc6_cache *c;
|
||||
struct net *net = sock_net(sk);
|
||||
struct mr6_table *mrt;
|
||||
|
||||
mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
|
||||
if (mrt == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCGETMIFCNT_IN6:
|
||||
if (copy_from_user(&vr, arg, sizeof(vr)))
|
||||
return -EFAULT;
|
||||
if (vr.mifi >= mrt->maxvif)
|
||||
return -EINVAL;
|
||||
read_lock(&mrt_lock);
|
||||
vif = &mrt->vif6_table[vr.mifi];
|
||||
if (MIF_EXISTS(mrt, vr.mifi)) {
|
||||
vr.icount = vif->pkt_in;
|
||||
vr.ocount = vif->pkt_out;
|
||||
vr.ibytes = vif->bytes_in;
|
||||
vr.obytes = vif->bytes_out;
|
||||
read_unlock(&mrt_lock);
|
||||
|
||||
if (copy_to_user(arg, &vr, sizeof(vr)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
read_unlock(&mrt_lock);
|
||||
return -EADDRNOTAVAIL;
|
||||
case SIOCGETSGCNT_IN6:
|
||||
if (copy_from_user(&sr, arg, sizeof(sr)))
|
||||
return -EFAULT;
|
||||
|
||||
read_lock(&mrt_lock);
|
||||
c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
|
||||
if (c) {
|
||||
sr.pktcnt = c->mfc_un.res.pkt;
|
||||
sr.bytecnt = c->mfc_un.res.bytes;
|
||||
sr.wrong_if = c->mfc_un.res.wrong_if;
|
||||
read_unlock(&mrt_lock);
|
||||
|
||||
if (copy_to_user(arg, &sr, sizeof(sr)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
read_unlock(&mrt_lock);
|
||||
return -EADDRNOTAVAIL;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int ip6mr_forward2_finish(struct sk_buff *skb)
|
||||
{
|
||||
|
@@ -19,13 +19,15 @@
|
||||
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter_bridge.h>
|
||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_conntrack_helper.h>
|
||||
#include <net/netfilter/nf_conntrack_l4proto.h>
|
||||
#include <net/netfilter/nf_conntrack_l3proto.h>
|
||||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
|
||||
#endif
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
|
||||
|
||||
static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
|
||||
@@ -33,8 +35,10 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
|
||||
{
|
||||
u16 zone = NF_CT_DEFAULT_ZONE;
|
||||
|
||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||
if (skb->nfct)
|
||||
zone = nf_ct_zone((struct nf_conn *)skb->nfct);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
if (skb->nf_bridge &&
|
||||
@@ -56,9 +60,11 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
|
||||
{
|
||||
struct sk_buff *reasm;
|
||||
|
||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||
/* Previously seen (loopback)? */
|
||||
if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
|
||||
return NF_ACCEPT;
|
||||
#endif
|
||||
|
||||
reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
|
||||
/* queued */
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/compat.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/ioctls.h>
|
||||
|
||||
@@ -1157,6 +1158,23 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static int compat_rawv6_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
case SIOCOUTQ:
|
||||
case SIOCINQ:
|
||||
return -ENOIOCTLCMD;
|
||||
default:
|
||||
#ifdef CONFIG_IPV6_MROUTE
|
||||
return ip6mr_compat_ioctl(sk, cmd, compat_ptr(arg));
|
||||
#else
|
||||
return -ENOIOCTLCMD;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void rawv6_close(struct sock *sk, long timeout)
|
||||
{
|
||||
if (inet_sk(sk)->inet_num == IPPROTO_RAW)
|
||||
@@ -1215,6 +1233,7 @@ struct proto rawv6_prot = {
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_setsockopt = compat_rawv6_setsockopt,
|
||||
.compat_getsockopt = compat_rawv6_getsockopt,
|
||||
.compat_ioctl = compat_rawv6_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@@ -72,8 +72,6 @@
|
||||
#define RT6_TRACE(x...) do { ; } while (0)
|
||||
#endif
|
||||
|
||||
#define CLONE_OFFLINK_ROUTE 0
|
||||
|
||||
static struct rt6_info * ip6_rt_copy(struct rt6_info *ort);
|
||||
static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
|
||||
static unsigned int ip6_default_advmss(const struct dst_entry *dst);
|
||||
@@ -115,6 +113,11 @@ static struct dst_ops ip6_dst_ops_template = {
|
||||
.local_out = __ip6_local_out,
|
||||
};
|
||||
|
||||
static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
|
||||
{
|
||||
}
|
||||
@@ -124,6 +127,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
|
||||
.protocol = cpu_to_be16(ETH_P_IPV6),
|
||||
.destroy = ip6_dst_destroy,
|
||||
.check = ip6_dst_check,
|
||||
.default_mtu = ip6_blackhole_default_mtu,
|
||||
.update_pmtu = ip6_rt_blackhole_update_pmtu,
|
||||
};
|
||||
|
||||
@@ -196,7 +200,6 @@ static void ip6_dst_destroy(struct dst_entry *dst)
|
||||
in6_dev_put(idev);
|
||||
}
|
||||
if (peer) {
|
||||
BUG_ON(!(rt->rt6i_flags & RTF_CACHE));
|
||||
rt->rt6i_peer = NULL;
|
||||
inet_putpeer(peer);
|
||||
}
|
||||
@@ -206,9 +209,6 @@ void rt6_bind_peer(struct rt6_info *rt, int create)
|
||||
{
|
||||
struct inet_peer *peer;
|
||||
|
||||
if (WARN_ON(!(rt->rt6i_flags & RTF_CACHE)))
|
||||
return;
|
||||
|
||||
peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create);
|
||||
if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL)
|
||||
inet_putpeer(peer);
|
||||
@@ -738,13 +738,8 @@ restart:
|
||||
|
||||
if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
|
||||
nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src);
|
||||
else {
|
||||
#if CLONE_OFFLINK_ROUTE
|
||||
else
|
||||
nrt = rt6_alloc_clone(rt, &fl->fl6_dst);
|
||||
#else
|
||||
goto out2;
|
||||
#endif
|
||||
}
|
||||
|
||||
dst_release(&rt->dst);
|
||||
rt = nrt ? : net->ipv6.ip6_null_entry;
|
||||
|
@@ -15,6 +15,8 @@
|
||||
#include <net/addrconf.h>
|
||||
#include <net/inet_frag.h>
|
||||
|
||||
static struct ctl_table empty[1];
|
||||
|
||||
static ctl_table ipv6_table_template[] = {
|
||||
{
|
||||
.procname = "route",
|
||||
@@ -35,6 +37,12 @@ static ctl_table ipv6_table_template[] = {
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec
|
||||
},
|
||||
{
|
||||
.procname = "neigh",
|
||||
.maxlen = 0,
|
||||
.mode = 0555,
|
||||
.child = empty,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -152,7 +160,6 @@ static struct ctl_table_header *ip6_base;
|
||||
|
||||
int ipv6_static_sysctl_register(void)
|
||||
{
|
||||
static struct ctl_table empty[1];
|
||||
ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty);
|
||||
if (ip6_base == NULL)
|
||||
return -ENOMEM;
|
||||
|
@@ -98,6 +98,10 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
|
||||
if (!xdst->u.rt6.rt6i_idev)
|
||||
return -ENODEV;
|
||||
|
||||
xdst->u.rt6.rt6i_peer = rt->rt6i_peer;
|
||||
if (rt->rt6i_peer)
|
||||
atomic_inc(&rt->rt6i_peer->refcnt);
|
||||
|
||||
/* Sheit... I remember I did this right. Apparently,
|
||||
* it was magically lost, so this code needs audit */
|
||||
xdst->u.rt6.rt6i_flags = rt->rt6i_flags & (RTF_ANYCAST |
|
||||
@@ -216,6 +220,8 @@ static void xfrm6_dst_destroy(struct dst_entry *dst)
|
||||
|
||||
if (likely(xdst->u.rt6.rt6i_idev))
|
||||
in6_dev_put(xdst->u.rt6.rt6i_idev);
|
||||
if (likely(xdst->u.rt6.rt6i_peer))
|
||||
inet_putpeer(xdst->u.rt6.rt6i_peer);
|
||||
xfrm_dst_destroy(xdst);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user