diff options
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r-- | net/ipv4/devinet.c | 33 |
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); | |||
176 | static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32); | 176 | static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32); |
177 | 177 | ||
178 | static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); | 178 | static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); |
179 | static BLOCKING_NOTIFIER_HEAD(inetaddr_validator_chain); | ||
179 | static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | 180 | static 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 | } |
1357 | EXPORT_SYMBOL(unregister_inetaddr_notifier); | 1377 | EXPORT_SYMBOL(unregister_inetaddr_notifier); |
1358 | 1378 | ||
1379 | int register_inetaddr_validator_notifier(struct notifier_block *nb) | ||
1380 | { | ||
1381 | return blocking_notifier_chain_register(&inetaddr_validator_chain, nb); | ||
1382 | } | ||
1383 | EXPORT_SYMBOL(register_inetaddr_validator_notifier); | ||
1384 | |||
1385 | int unregister_inetaddr_validator_notifier(struct notifier_block *nb) | ||
1386 | { | ||
1387 | return blocking_notifier_chain_unregister(&inetaddr_validator_chain, | ||
1388 | nb); | ||
1389 | } | ||
1390 | EXPORT_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 | */ |