aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2005-05-29 23:23:46 -0400
committerDavid S. Miller <davem@davemloft.net>2005-05-29 23:23:46 -0400
commit8f937c6099858eee15fae14009dcbd05177fa91d (patch)
treec0aa5c7983c4402a46ea397b0612d5ecd3e9a853
parent79158229b09873ca296ac53de5c952488f944646 (diff)
[IPV4]: Primary and secondary addresses
Add an option to make secondary IP addresses get promoted when primary IP addresses are removed from the device. It defaults to off to preserve existing behavior. Signed-off-by: Harald Welte <laforge@gnumonks.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/inetdevice.h2
-rw-r--r--include/linux/sysctl.h1
-rw-r--r--net/ipv4/devinet.c34
3 files changed, 32 insertions, 5 deletions
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 6fafb27877a7..7e1e15f934f3 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -29,6 +29,7 @@ struct ipv4_devconf
29 int no_xfrm; 29 int no_xfrm;
30 int no_policy; 30 int no_policy;
31 int force_igmp_version; 31 int force_igmp_version;
32 int promote_secondaries;
32 void *sysctl; 33 void *sysctl;
33}; 34};
34 35
@@ -71,6 +72,7 @@ struct in_device
71#define IN_DEV_SEC_REDIRECTS(in_dev) (ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects) 72#define IN_DEV_SEC_REDIRECTS(in_dev) (ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects)
72#define IN_DEV_IDTAG(in_dev) ((in_dev)->cnf.tag) 73#define IN_DEV_IDTAG(in_dev) ((in_dev)->cnf.tag)
73#define IN_DEV_MEDIUM_ID(in_dev) ((in_dev)->cnf.medium_id) 74#define IN_DEV_MEDIUM_ID(in_dev) ((in_dev)->cnf.medium_id)
75#define IN_DEV_PROMOTE_SECONDARIES(in_dev) (ipv4_devconf.promote_secondaries || (in_dev)->cnf.promote_secondaries)
74 76
75#define IN_DEV_RX_REDIRECTS(in_dev) \ 77#define IN_DEV_RX_REDIRECTS(in_dev) \
76 ((IN_DEV_FORWARD(in_dev) && \ 78 ((IN_DEV_FORWARD(in_dev) && \
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 772998147e3e..23032d9d6071 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -399,6 +399,7 @@ enum
399 NET_IPV4_CONF_FORCE_IGMP_VERSION=17, 399 NET_IPV4_CONF_FORCE_IGMP_VERSION=17,
400 NET_IPV4_CONF_ARP_ANNOUNCE=18, 400 NET_IPV4_CONF_ARP_ANNOUNCE=18,
401 NET_IPV4_CONF_ARP_IGNORE=19, 401 NET_IPV4_CONF_ARP_IGNORE=19,
402 NET_IPV4_CONF_PROMOTE_SECONDARIES=20,
402 __NET_IPV4_CONF_MAX 403 __NET_IPV4_CONF_MAX
403}; 404};
404 405
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 3cc96730c4ed..478a30179a52 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -233,11 +233,14 @@ int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
233static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, 233static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
234 int destroy) 234 int destroy)
235{ 235{
236 struct in_ifaddr *promote = NULL;
236 struct in_ifaddr *ifa1 = *ifap; 237 struct in_ifaddr *ifa1 = *ifap;
237 238
238 ASSERT_RTNL(); 239 ASSERT_RTNL();
239 240
240 /* 1. Deleting primary ifaddr forces deletion all secondaries */ 241 /* 1. Deleting primary ifaddr forces deletion all secondaries
242 * unless alias promotion is set
243 **/
241 244
242 if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) { 245 if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) {
243 struct in_ifaddr *ifa; 246 struct in_ifaddr *ifa;
@@ -251,11 +254,16 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
251 continue; 254 continue;
252 } 255 }
253 256
254 *ifap1 = ifa->ifa_next; 257 if (!IN_DEV_PROMOTE_SECONDARIES(in_dev)) {
258 *ifap1 = ifa->ifa_next;
255 259
256 rtmsg_ifa(RTM_DELADDR, ifa); 260 rtmsg_ifa(RTM_DELADDR, ifa);
257 notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); 261 notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
258 inet_free_ifa(ifa); 262 inet_free_ifa(ifa);
263 } else {
264 promote = ifa;
265 break;
266 }
259 } 267 }
260 } 268 }
261 269
@@ -281,6 +289,13 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
281 if (!in_dev->ifa_list) 289 if (!in_dev->ifa_list)
282 inetdev_destroy(in_dev); 290 inetdev_destroy(in_dev);
283 } 291 }
292
293 if (promote && IN_DEV_PROMOTE_SECONDARIES(in_dev)) {
294 /* not sure if we should send a delete notify first? */
295 promote->ifa_flags &= ~IFA_F_SECONDARY;
296 rtmsg_ifa(RTM_NEWADDR, promote);
297 notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote);
298 }
284} 299}
285 300
286static int inet_insert_ifa(struct in_ifaddr *ifa) 301static int inet_insert_ifa(struct in_ifaddr *ifa)
@@ -1384,6 +1399,15 @@ static struct devinet_sysctl_table {
1384 .proc_handler = &ipv4_doint_and_flush, 1399 .proc_handler = &ipv4_doint_and_flush,
1385 .strategy = &ipv4_doint_and_flush_strategy, 1400 .strategy = &ipv4_doint_and_flush_strategy,
1386 }, 1401 },
1402 {
1403 .ctl_name = NET_IPV4_CONF_PROMOTE_SECONDARIES,
1404 .procname = "promote_secondaries",
1405 .data = &ipv4_devconf.promote_secondaries,
1406 .maxlen = sizeof(int),
1407 .mode = 0644,
1408 .proc_handler = &ipv4_doint_and_flush,
1409 .strategy = &ipv4_doint_and_flush_strategy,
1410 },
1387 }, 1411 },
1388 .devinet_dev = { 1412 .devinet_dev = {
1389 { 1413 {