summaryrefslogtreecommitdiffstats
path: root/net/ipv4/devinet.c
diff options
context:
space:
mode:
authorKrister Johansen <kjlx@templeofstupid.com>2017-06-08 16:12:14 -0400
committerDavid S. Miller <davem@davemloft.net>2017-06-09 12:26:07 -0400
commit3ad7d2468f79fc13215eb941f766a692d34b1381 (patch)
tree5a742b551c95c8587e40bb5421c214e76d78c5d8 /net/ipv4/devinet.c
parent2b3a9afc63ab6af58417b3aaca2746dee2fbdc86 (diff)
Ipvlan should return an error when an address is already in use.
The ipvlan code already knows how to detect when a duplicate address is about to be assigned to an ipvlan device. However, that failure is not propogated outward and leads to a silent failure. Introduce a validation step at ip address creation time and allow device drivers to register to validate the incoming ip addresses. The ipvlan code is the first consumer. If it detects an address in use, we can return an error to the user before beginning to commit the new ifa in the networking code. This can be especially useful if it is necessary to provision many ipvlans in containers. The provisioning software (or operator) can use this to detect situations where an ip address is unexpectedly in use. Signed-off-by: Krister Johansen <kjlx@templeofstupid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r--net/ipv4/devinet.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index df14815a3b8c..a7dd088d5fc9 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -176,6 +176,7 @@ EXPORT_SYMBOL(__ip_dev_find);
176static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32); 176static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32);
177 177
178static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); 178static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
179static BLOCKING_NOTIFIER_HEAD(inetaddr_validator_chain);
179static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, 180static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
180 int destroy); 181 int destroy);
181#ifdef CONFIG_SYSCTL 182#ifdef CONFIG_SYSCTL
@@ -441,6 +442,8 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
441{ 442{
442 struct in_device *in_dev = ifa->ifa_dev; 443 struct in_device *in_dev = ifa->ifa_dev;
443 struct in_ifaddr *ifa1, **ifap, **last_primary; 444 struct in_ifaddr *ifa1, **ifap, **last_primary;
445 struct in_validator_info ivi;
446 int ret;
444 447
445 ASSERT_RTNL(); 448 ASSERT_RTNL();
446 449
@@ -471,6 +474,23 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
471 } 474 }
472 } 475 }
473 476
477 /* Allow any devices that wish to register ifaddr validtors to weigh
478 * in now, before changes are committed. The rntl lock is serializing
479 * access here, so the state should not change between a validator call
480 * and a final notify on commit. This isn't invoked on promotion under
481 * the assumption that validators are checking the address itself, and
482 * not the flags.
483 */
484 ivi.ivi_addr = ifa->ifa_address;
485 ivi.ivi_dev = ifa->ifa_dev;
486 ret = blocking_notifier_call_chain(&inetaddr_validator_chain,
487 NETDEV_UP, &ivi);
488 ret = notifier_to_errno(ret);
489 if (ret) {
490 inet_free_ifa(ifa);
491 return ret;
492 }
493
474 if (!(ifa->ifa_flags & IFA_F_SECONDARY)) { 494 if (!(ifa->ifa_flags & IFA_F_SECONDARY)) {
475 prandom_seed((__force u32) ifa->ifa_local); 495 prandom_seed((__force u32) ifa->ifa_local);
476 ifap = last_primary; 496 ifap = last_primary;
@@ -1356,6 +1376,19 @@ int unregister_inetaddr_notifier(struct notifier_block *nb)
1356} 1376}
1357EXPORT_SYMBOL(unregister_inetaddr_notifier); 1377EXPORT_SYMBOL(unregister_inetaddr_notifier);
1358 1378
1379int register_inetaddr_validator_notifier(struct notifier_block *nb)
1380{
1381 return blocking_notifier_chain_register(&inetaddr_validator_chain, nb);
1382}
1383EXPORT_SYMBOL(register_inetaddr_validator_notifier);
1384
1385int unregister_inetaddr_validator_notifier(struct notifier_block *nb)
1386{
1387 return blocking_notifier_chain_unregister(&inetaddr_validator_chain,
1388 nb);
1389}
1390EXPORT_SYMBOL(unregister_inetaddr_validator_notifier);
1391
1359/* Rename ifa_labels for a device name change. Make some effort to preserve 1392/* Rename ifa_labels for a device name change. Make some effort to preserve
1360 * existing alias numbering and to create unique labels if possible. 1393 * existing alias numbering and to create unique labels if possible.
1361*/ 1394*/