diff options
author | pauljensen@chromium.org <pauljensen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-23 18:12:20 +0000 |
---|---|---|
committer | pauljensen@chromium.org <pauljensen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-23 18:12:20 +0000 |
commit | fb5dead7e644df782b1e63e97fa532940d1cc7bb (patch) | |
tree | 333192f875355251820a0ca074b24a31768d786d /net/base/address_tracker_linux.cc | |
parent | 4d89a9279940415b80c79f51beb3394f7e991560 (diff) | |
download | chromium_src-fb5dead7e644df782b1e63e97fa532940d1cc7bb.zip chromium_src-fb5dead7e644df782b1e63e97fa532940d1cc7bb.tar.gz chromium_src-fb5dead7e644df782b1e63e97fa532940d1cc7bb.tar.bz2 |
Work around linux kernel bug by interpreting IPv6 "Preferred Lifetimes" of 0 as implying the address is deprecated. This avoids spurious network changed signals on linux by ignoring more duplicate messages by canonicalizing them before matching them.
BUG=268042
TEST=net_unittests --gtest_filter=AddressTrackerLinuxTest.DeprecatedLifetime
Review URL: https://codereview.chromium.org/109213004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@246641 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/address_tracker_linux.cc')
-rw-r--r-- | net/base/address_tracker_linux.cc | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/net/base/address_tracker_linux.cc b/net/base/address_tracker_linux.cc index f863ccd..37911de 100644 --- a/net/base/address_tracker_linux.cc +++ b/net/base/address_tracker_linux.cc @@ -18,7 +18,12 @@ namespace internal { namespace { // Retrieves address from NETLINK address message. -bool GetAddress(const struct nlmsghdr* header, IPAddressNumber* out) { +// Sets |really_deprecated| for IPv6 addresses with preferred lifetimes of 0. +bool GetAddress(const struct nlmsghdr* header, + IPAddressNumber* out, + bool* really_deprecated) { + if (really_deprecated) + *really_deprecated = false; const struct ifaddrmsg* msg = reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); size_t address_length = 0; @@ -53,6 +58,12 @@ bool GetAddress(const struct nlmsghdr* header, IPAddressNumber* out) { DCHECK_GE(RTA_PAYLOAD(attr), address_length); local = reinterpret_cast<unsigned char*>(RTA_DATA(attr)); break; + case IFA_CACHEINFO: { + const struct ifa_cacheinfo *cache_info = + reinterpret_cast<const struct ifa_cacheinfo*>(RTA_DATA(attr)); + if (really_deprecated) + *really_deprecated = (cache_info->ifa_prefered == 0); + } break; default: break; } @@ -225,13 +236,12 @@ void AddressTrackerLinux::ReadMessages(bool* address_changed, } } -void AddressTrackerLinux::HandleMessage(const char* buffer, +void AddressTrackerLinux::HandleMessage(char* buffer, size_t length, bool* address_changed, bool* link_changed) { DCHECK(buffer); - for (const struct nlmsghdr* header = - reinterpret_cast<const struct nlmsghdr*>(buffer); + for (struct nlmsghdr* header = reinterpret_cast<struct nlmsghdr*>(buffer); NLMSG_OK(header, length); header = NLMSG_NEXT(header, length)) { switch (header->nlmsg_type) { @@ -244,10 +254,20 @@ void AddressTrackerLinux::HandleMessage(const char* buffer, } return; case RTM_NEWADDR: { IPAddressNumber address; - if (GetAddress(header, &address)) { + bool really_deprecated; + if (GetAddress(header, &address, &really_deprecated)) { base::AutoLock lock(address_map_lock_); - const struct ifaddrmsg* msg = + struct ifaddrmsg* msg = reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); + // Routers may frequently (every few seconds) output the IPv6 ULA + // prefix which can cause the linux kernel to frequently output two + // back-to-back messages, one without the deprecated flag and one with + // the deprecated flag but both with preferred lifetimes of 0. Avoid + // interpretting this as an actual change by canonicalizing the two + // messages by setting the deprecated flag based on the preferred + // lifetime also. http://crbug.com/268042 + if (really_deprecated) + msg->ifa_flags |= IFA_F_DEPRECATED; // Only indicate change if the address is new or ifaddrmsg info has // changed. AddressMap::iterator it = address_map_.find(address); @@ -262,7 +282,7 @@ void AddressTrackerLinux::HandleMessage(const char* buffer, } break; case RTM_DELADDR: { IPAddressNumber address; - if (GetAddress(header, &address)) { + if (GetAddress(header, &address, NULL)) { base::AutoLock lock(address_map_lock_); if (address_map_.erase(address)) *address_changed = true; |