|
@@ -233,11 +233,14 @@ int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
|
|
|
static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
|
|
|
int destroy)
|
|
|
{
|
|
|
+ struct in_ifaddr *promote = NULL;
|
|
|
struct in_ifaddr *ifa1 = *ifap;
|
|
|
|
|
|
ASSERT_RTNL();
|
|
|
|
|
|
- /* 1. Deleting primary ifaddr forces deletion all secondaries */
|
|
|
+ /* 1. Deleting primary ifaddr forces deletion all secondaries
|
|
|
+ * unless alias promotion is set
|
|
|
+ **/
|
|
|
|
|
|
if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) {
|
|
|
struct in_ifaddr *ifa;
|
|
@@ -251,11 +254,16 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- *ifap1 = ifa->ifa_next;
|
|
|
+ if (!IN_DEV_PROMOTE_SECONDARIES(in_dev)) {
|
|
|
+ *ifap1 = ifa->ifa_next;
|
|
|
|
|
|
- rtmsg_ifa(RTM_DELADDR, ifa);
|
|
|
- notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
|
|
|
- inet_free_ifa(ifa);
|
|
|
+ rtmsg_ifa(RTM_DELADDR, ifa);
|
|
|
+ notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
|
|
|
+ inet_free_ifa(ifa);
|
|
|
+ } else {
|
|
|
+ promote = ifa;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -281,6 +289,13 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
|
|
|
if (!in_dev->ifa_list)
|
|
|
inetdev_destroy(in_dev);
|
|
|
}
|
|
|
+
|
|
|
+ if (promote && IN_DEV_PROMOTE_SECONDARIES(in_dev)) {
|
|
|
+ /* not sure if we should send a delete notify first? */
|
|
|
+ promote->ifa_flags &= ~IFA_F_SECONDARY;
|
|
|
+ rtmsg_ifa(RTM_NEWADDR, promote);
|
|
|
+ notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static int inet_insert_ifa(struct in_ifaddr *ifa)
|
|
@@ -1384,6 +1399,15 @@ static struct devinet_sysctl_table {
|
|
|
.proc_handler = &ipv4_doint_and_flush,
|
|
|
.strategy = &ipv4_doint_and_flush_strategy,
|
|
|
},
|
|
|
+ {
|
|
|
+ .ctl_name = NET_IPV4_CONF_PROMOTE_SECONDARIES,
|
|
|
+ .procname = "promote_secondaries",
|
|
|
+ .data = &ipv4_devconf.promote_secondaries,
|
|
|
+ .maxlen = sizeof(int),
|
|
|
+ .mode = 0644,
|
|
|
+ .proc_handler = &ipv4_doint_and_flush,
|
|
|
+ .strategy = &ipv4_doint_and_flush_strategy,
|
|
|
+ },
|
|
|
},
|
|
|
.devinet_dev = {
|
|
|
{
|