From 983398a9d722268e5a828bdcf1e0a39e8fe5994c Mon Sep 17 00:00:00 2001 From: victek Date: Fri, 27 Sep 2013 06:56:37 +0200 Subject: [PATCH] bonding / ipv6: no addrconf for slaves separately from master. bonding: fix enslavement error unwinds. ipv6: Add IFA_F_DADFAILED flag. ipv6: Send netlink notification when DAD fails. --- .../linux-2.6/drivers/net/bonding/bond_main.c | 22 +++++++++++----------- .../src-rt/linux/linux-2.6/include/linux/icmpv6.h | 3 +++ .../src-rt/linux/linux-2.6/include/linux/if_addr.h | 1 + release/src-rt/linux/linux-2.6/net/ipv6/addrconf.c | 17 ++++++++++++----- release/src-rt/linux/linux-2.6/net/ipv6/icmp.c | 10 +++++++++- 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/release/src-rt/linux/linux-2.6/drivers/net/bonding/bond_main.c b/release/src-rt/linux/linux-2.6/drivers/net/bonding/bond_main.c index 0af7bc8d41..99cd0818f3 100644 --- a/release/src-rt/linux/linux-2.6/drivers/net/bonding/bond_main.c +++ b/release/src-rt/linux/linux-2.6/drivers/net/bonding/bond_main.c @@ -1378,17 +1378,17 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_free; } - /* open the slave since the application closed it */ - res = dev_open(slave_dev); + res = netdev_set_master(slave_dev, bond_dev); if (res) { - dprintk("Openning slave %s failed\n", slave_dev->name); + dprintk("Error %d calling netdev_set_master\n", res); goto err_restore_mac; } - res = netdev_set_master(slave_dev, bond_dev); + /* open the slave since the application closed it */ + res = dev_open(slave_dev); if (res) { - dprintk("Error %d calling netdev_set_master\n", res); - goto err_close; + dprintk("Openning slave %s failed\n", slave_dev->name); + goto err_unset_master; } new_slave->dev = slave_dev; @@ -1401,7 +1401,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) */ res = bond_alb_init_slave(bond, new_slave); if (res) { - goto err_unset_master; + goto err_close; } } @@ -1582,7 +1582,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) res = bond_create_slave_symlinks(bond_dev, slave_dev); if (res) - goto err_unset_master; + goto err_close; printk(KERN_INFO DRV_NAME ": %s: enslaving %s as a%s interface with a%s link.\n", @@ -1594,12 +1594,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) return 0; /* Undo stages on error */ -err_unset_master: - netdev_set_master(slave_dev, NULL); - err_close: dev_close(slave_dev); +err_unset_master: + netdev_set_master(slave_dev, NULL); + err_restore_mac: memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN); addr.sa_family = slave_dev->type; diff --git a/release/src-rt/linux/linux-2.6/include/linux/icmpv6.h b/release/src-rt/linux/linux-2.6/include/linux/icmpv6.h index 7c5e9817e9..767c167e6e 100644 --- a/release/src-rt/linux/linux-2.6/include/linux/icmpv6.h +++ b/release/src-rt/linux/linux-2.6/include/linux/icmpv6.h @@ -120,6 +120,9 @@ static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb) #define ICMPV6_NOT_NEIGHBOUR 2 #define ICMPV6_ADDR_UNREACH 3 #define ICMPV6_PORT_UNREACH 4 +#define ICMPV6_POLICY_FAIL 5 +#define ICMPV6_REJECT_ROUTE 6 + /* * Codes for Time Exceeded diff --git a/release/src-rt/linux/linux-2.6/include/linux/if_addr.h b/release/src-rt/linux/linux-2.6/include/linux/if_addr.h index 43f3bedaaf..bee1133e54 100644 --- a/release/src-rt/linux/linux-2.6/include/linux/if_addr.h +++ b/release/src-rt/linux/linux-2.6/include/linux/if_addr.h @@ -40,6 +40,7 @@ enum #define IFA_F_NODAD 0x02 #define IFA_F_OPTIMISTIC 0x04 +#define IFA_F_DADFAILED 0x08 #define IFA_F_HOMEADDRESS 0x10 #define IFA_F_DEPRECATED 0x20 #define IFA_F_TENTATIVE 0x40 diff --git a/release/src-rt/linux/linux-2.6/net/ipv6/addrconf.c b/release/src-rt/linux/linux-2.6/net/ipv6/addrconf.c index 69c88d5a14..ee2861fbc5 100644 --- a/release/src-rt/linux/linux-2.6/net/ipv6/addrconf.c +++ b/release/src-rt/linux/linux-2.6/net/ipv6/addrconf.c @@ -1319,13 +1319,17 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) /* Gets referenced address, destroys ifaddr */ -static void addrconf_dad_stop(struct inet6_ifaddr *ifp) +static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) { if (ifp->flags&IFA_F_PERMANENT) { spin_lock_bh(&ifp->lock); addrconf_del_timer(ifp); ifp->flags |= IFA_F_TENTATIVE; + if (dad_failed) + ifp->flags |= IFA_F_DADFAILED; spin_unlock_bh(&ifp->lock); + if (dad_failed) + ipv6_ifa_notify(0, ifp); in6_ifa_put(ifp); #ifdef CONFIG_IPV6_PRIVACY } else if (ifp->flags&IFA_F_TEMPORARY) { @@ -1352,7 +1356,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) printk(KERN_INFO "%s: IPv6 duplicate address detected!\n", ifp->idev->dev->name); - addrconf_dad_stop(ifp); + addrconf_dad_stop(ifp, 1); } /* Join to solicited addr multicast group. */ @@ -2353,6 +2357,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, break; case NETDEV_UP: case NETDEV_CHANGE: + if (dev->flags & IFF_SLAVE) + break; + if (event == NETDEV_UP) { if (!addrconf_qdisc_ok(dev)) { /* device is not ready yet. */ @@ -2677,7 +2684,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || !(ifp->flags&IFA_F_TENTATIVE) || ifp->flags & IFA_F_NODAD) { - ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); + ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); spin_unlock_bh(&ifp->lock); read_unlock_bh(&idev->lock); @@ -2694,7 +2701,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) * - otherwise, kill it. */ in6_ifa_hold(ifp); - addrconf_dad_stop(ifp); + addrconf_dad_stop(ifp, 0); return; } @@ -2729,7 +2736,7 @@ static void addrconf_dad_timer(unsigned long data) * DAD was successful */ - ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); + ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); spin_unlock_bh(&ifp->lock); read_unlock_bh(&idev->lock); diff --git a/release/src-rt/linux/linux-2.6/net/ipv6/icmp.c b/release/src-rt/linux/linux-2.6/net/ipv6/icmp.c index 930cfb8838..023438b66b 100644 --- a/release/src-rt/linux/linux-2.6/net/ipv6/icmp.c +++ b/release/src-rt/linux/linux-2.6/net/ipv6/icmp.c @@ -836,6 +836,14 @@ static const struct icmp6_err { .err = ECONNREFUSED, .fatal = 1, }, + { /* POLICY_FAIL */ + .err = EACCES, + .fatal = 1, + }, + { /* REJECT_ROUTE */ + .err = EACCES, + .fatal = 1, + }, }; int icmpv6_err_convert(int type, int code, int *err) @@ -847,7 +855,7 @@ int icmpv6_err_convert(int type, int code, int *err) switch (type) { case ICMPV6_DEST_UNREACH: fatal = 1; - if (code <= ICMPV6_PORT_UNREACH) { + if (code < ARRAY_SIZE(tab_unreach)) { *err = tab_unreach[code].err; fatal = tab_unreach[code].fatal; } -- 2.11.4.GIT