| Index: net/base/network_change_notifier_netlink_linux.cc
|
| diff --git a/net/base/network_change_notifier_netlink_linux.cc b/net/base/network_change_notifier_netlink_linux.cc
|
| index 5f71f45a96d217562ad99383b5578cf1eba9b196..493e17ae2c8eb8ac8d7a1d101eedbbe4d9b1f65e 100644
|
| --- a/net/base/network_change_notifier_netlink_linux.cc
|
| +++ b/net/base/network_change_notifier_netlink_linux.cc
|
| @@ -26,6 +26,35 @@ bool SetNonBlocking(int fd) {
|
| return fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0 ? true : false;
|
| }
|
|
|
| +bool IsIPv6Update(const struct nlmsghdr* netlink_message_header) {
|
| + const struct ifaddrmsg* address_message =
|
| + reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(netlink_message_header));
|
| + return address_message->ifa_family == AF_INET6;
|
| +}
|
| +
|
| +bool IsDuplicateIPv6AddressUpdate(
|
| + const struct nlmsghdr* netlink_message_header) {
|
| + const struct ifaddrmsg* address_message =
|
| + reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(netlink_message_header));
|
| + int address_message_length = IFA_PAYLOAD(netlink_message_header);
|
| + const struct rtattr* route_attribute =
|
| + reinterpret_cast<struct rtattr*>(IFA_RTA(address_message));
|
| + DCHECK_EQ(address_message->ifa_family, AF_INET6);
|
| +
|
| + // Look for a cacheinfo attribute, and ignore new address broadcasts
|
| + // where the updated time stamp is newer than the created time stamp.
|
| + while (RTA_OK(route_attribute, address_message_length)) {
|
| + if (route_attribute->rta_type == IFA_CACHEINFO) {
|
| + struct ifa_cacheinfo* cache_info =
|
| + reinterpret_cast<struct ifa_cacheinfo*>(RTA_DATA(route_attribute));
|
| + if (cache_info->cstamp != cache_info->tstamp)
|
| + return true;
|
| + }
|
| + route_attribute = RTA_NEXT(route_attribute, address_message_length);
|
| + }
|
| + return false;
|
| +}
|
| +
|
| } // namespace
|
|
|
| int InitializeNetlinkSocket() {
|
| @@ -46,7 +75,8 @@ int InitializeNetlinkSocket() {
|
| memset(&local_addr, 0, sizeof(local_addr));
|
| local_addr.nl_family = AF_NETLINK;
|
| local_addr.nl_pid = getpid();
|
| - local_addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_NOTIFY;
|
| + local_addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
|
| + RTMGRP_NOTIFY;
|
| int ret = bind(sock, reinterpret_cast<struct sockaddr*>(&local_addr),
|
| sizeof(local_addr));
|
| if (ret < 0) {
|
| @@ -79,6 +109,10 @@ bool HandleNetlinkMessage(char* buf, size_t len) {
|
| // may still end up notifying observers more than strictly necessary, but
|
| // if the primary interface goes down and back up, then this is necessary.
|
| case RTM_NEWADDR:
|
| + if (IsIPv6Update(netlink_message_header) &&
|
| + IsDuplicateIPv6AddressUpdate(netlink_message_header))
|
| + return false;
|
| + return true;
|
| case RTM_DELADDR:
|
| return true;
|
| case RTM_NEWLINK:
|
|
|