OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/base/address_tracker_linux.h" |
| 6 |
| 7 #include <vector> |
| 8 |
| 9 #include "base/bind.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" |
| 11 |
| 12 namespace net { |
| 13 namespace internal { |
| 14 |
| 15 void Noop() {} |
| 16 |
| 17 class AddressTrackerLinuxTest : public testing::Test { |
| 18 protected: |
| 19 AddressTrackerLinuxTest() : tracker_(base::Bind(&Noop)) {} |
| 20 |
| 21 bool HandleMessage(char* buf, size_t length) { |
| 22 return tracker_.HandleMessage(buf, length); |
| 23 } |
| 24 |
| 25 AddressTrackerLinux::AddressMap GetMap() { |
| 26 return tracker_.GetMap(); |
| 27 } |
| 28 |
| 29 AddressTrackerLinux tracker_; |
| 30 }; |
| 31 |
| 32 namespace { |
| 33 |
| 34 typedef std::vector<char> Buffer; |
| 35 |
| 36 class NetlinkMessage { |
| 37 public: |
| 38 explicit NetlinkMessage(uint16 type) : buffer_(NLMSG_HDRLEN) { |
| 39 header()->nlmsg_type = type; |
| 40 Align(); |
| 41 } |
| 42 |
| 43 void AddPayload(const void* data, size_t length) { |
| 44 CHECK_EQ(static_cast<size_t>(NLMSG_HDRLEN), |
| 45 buffer_.size()) << "Payload must be added first"; |
| 46 Append(data, length); |
| 47 Align(); |
| 48 } |
| 49 |
| 50 void AddAttribute(uint16 type, const void* data, size_t length) { |
| 51 struct nlattr attr; |
| 52 attr.nla_len = NLA_HDRLEN + length; |
| 53 attr.nla_type = type; |
| 54 Append(&attr, sizeof(attr)); |
| 55 Align(); |
| 56 Append(data, length); |
| 57 Align(); |
| 58 } |
| 59 |
| 60 void AppendTo(Buffer* output) const { |
| 61 CHECK_EQ(NLMSG_ALIGN(output->size()), output->size()); |
| 62 output->reserve(output->size() + NLMSG_LENGTH(buffer_.size())); |
| 63 output->insert(output->end(), buffer_.begin(), buffer_.end()); |
| 64 } |
| 65 |
| 66 private: |
| 67 void Append(const void* data, size_t length) { |
| 68 const char* chardata = reinterpret_cast<const char*>(data); |
| 69 buffer_.insert(buffer_.end(), chardata, chardata + length); |
| 70 } |
| 71 |
| 72 void Align() { |
| 73 header()->nlmsg_len = buffer_.size(); |
| 74 buffer_.insert(buffer_.end(), NLMSG_ALIGN(buffer_.size()) - buffer_.size(), |
| 75 0); |
| 76 CHECK(NLMSG_OK(header(), buffer_.size())); |
| 77 } |
| 78 |
| 79 struct nlmsghdr* header() { |
| 80 return reinterpret_cast<struct nlmsghdr*>(&buffer_[0]); |
| 81 } |
| 82 |
| 83 Buffer buffer_; |
| 84 }; |
| 85 |
| 86 void MakeMessage(uint16 type, |
| 87 uint8 flags, |
| 88 uint8 family, |
| 89 const IPAddressNumber& address, |
| 90 const IPAddressNumber& local, |
| 91 Buffer* output) { |
| 92 NetlinkMessage nlmsg(type); |
| 93 struct ifaddrmsg msg; |
| 94 msg.ifa_family = family; |
| 95 msg.ifa_flags = flags; |
| 96 nlmsg.AddPayload(&msg, sizeof(msg)); |
| 97 if (address.size()) |
| 98 nlmsg.AddAttribute(IFA_ADDRESS, &address[0], address.size()); |
| 99 if (local.size()) |
| 100 nlmsg.AddAttribute(IFA_LOCAL, &local[0], local.size()); |
| 101 nlmsg.AppendTo(output); |
| 102 } |
| 103 |
| 104 const unsigned char kAddress0[] = { 127, 0, 0, 1 }; |
| 105 const unsigned char kAddress1[] = { 10, 0, 0, 1 }; |
| 106 const unsigned char kAddress2[] = { 192, 168, 0, 1 }; |
| 107 const unsigned char kAddress3[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 108 0, 0, 0, 1 }; |
| 109 const unsigned char kAddress4[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, |
| 110 169, 254, 0, 1 }; |
| 111 |
| 112 TEST_F(AddressTrackerLinuxTest, NewAddress) { |
| 113 const IPAddressNumber kEmpty; |
| 114 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); |
| 115 const IPAddressNumber kAddr1(kAddress1, kAddress1 + arraysize(kAddress1)); |
| 116 const IPAddressNumber kAddr2(kAddress2, kAddress2 + arraysize(kAddress2)); |
| 117 const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3)); |
| 118 |
| 119 Buffer buffer; |
| 120 MakeMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, &buffer); |
| 121 EXPECT_TRUE(HandleMessage(&buffer[0], buffer.size())); |
| 122 AddressTrackerLinux::AddressMap map = GetMap(); |
| 123 EXPECT_EQ(1u, map.size()); |
| 124 EXPECT_TRUE(map.find(kAddr0) != map.end()); |
| 125 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); |
| 126 |
| 127 buffer.clear(); |
| 128 MakeMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr1, kAddr2, &buffer); |
| 129 EXPECT_TRUE(HandleMessage(&buffer[0], buffer.size())); |
| 130 map = GetMap(); |
| 131 EXPECT_EQ(2u, map.size()); |
| 132 EXPECT_TRUE(map.find(kAddr0) != map.end()); |
| 133 EXPECT_TRUE(map.find(kAddr2) != map.end()); |
| 134 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr2].ifa_flags); |
| 135 |
| 136 buffer.clear(); |
| 137 MakeMessage(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, &buffer); |
| 138 EXPECT_TRUE(HandleMessage(&buffer[0], buffer.size())); |
| 139 map = GetMap(); |
| 140 EXPECT_EQ(3u, map.size()); |
| 141 EXPECT_TRUE(map.find(kAddr3) != map.end()); |
| 142 } |
| 143 |
| 144 TEST_F(AddressTrackerLinuxTest, NewAddressChange) { |
| 145 const IPAddressNumber kEmpty; |
| 146 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); |
| 147 |
| 148 Buffer buffer; |
| 149 MakeMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, &buffer); |
| 150 EXPECT_TRUE(HandleMessage(&buffer[0], buffer.size())); |
| 151 AddressTrackerLinux::AddressMap map = GetMap(); |
| 152 EXPECT_EQ(1u, map.size()); |
| 153 EXPECT_TRUE(map.find(kAddr0) != map.end()); |
| 154 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); |
| 155 |
| 156 buffer.clear(); |
| 157 MakeMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr0, kEmpty, &buffer); |
| 158 EXPECT_TRUE(HandleMessage(&buffer[0], buffer.size())); |
| 159 map = GetMap(); |
| 160 EXPECT_EQ(1u, map.size()); |
| 161 EXPECT_TRUE(map.find(kAddr0) != map.end()); |
| 162 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags); |
| 163 |
| 164 // Both messages in one buffer. |
| 165 buffer.clear(); |
| 166 MakeMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty, &buffer); |
| 167 MakeMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr0, kEmpty, &buffer); |
| 168 EXPECT_TRUE(HandleMessage(&buffer[0], buffer.size())); |
| 169 map = GetMap(); |
| 170 EXPECT_EQ(1u, map.size()); |
| 171 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags); |
| 172 } |
| 173 |
| 174 TEST_F(AddressTrackerLinuxTest, NewAddressDuplicate) { |
| 175 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); |
| 176 |
| 177 Buffer buffer; |
| 178 MakeMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kAddr0, &buffer); |
| 179 EXPECT_TRUE(HandleMessage(&buffer[0], buffer.size())); |
| 180 AddressTrackerLinux::AddressMap map = GetMap(); |
| 181 EXPECT_EQ(1u, map.size()); |
| 182 EXPECT_TRUE(map.find(kAddr0) != map.end()); |
| 183 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); |
| 184 |
| 185 EXPECT_FALSE(HandleMessage(&buffer[0], buffer.size())); |
| 186 map = GetMap(); |
| 187 EXPECT_EQ(1u, map.size()); |
| 188 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags); |
| 189 } |
| 190 |
| 191 TEST_F(AddressTrackerLinuxTest, DeleteAddress) { |
| 192 const IPAddressNumber kEmpty; |
| 193 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); |
| 194 const IPAddressNumber kAddr1(kAddress1, kAddress1 + arraysize(kAddress1)); |
| 195 const IPAddressNumber kAddr2(kAddress2, kAddress2 + arraysize(kAddress2)); |
| 196 |
| 197 Buffer buffer; |
| 198 MakeMessage(RTM_NEWADDR, 0, AF_INET, kAddr0, kEmpty, &buffer); |
| 199 MakeMessage(RTM_NEWADDR, 0, AF_INET, kAddr1, kAddr2, &buffer); |
| 200 EXPECT_TRUE(HandleMessage(&buffer[0], buffer.size())); |
| 201 AddressTrackerLinux::AddressMap map = GetMap(); |
| 202 EXPECT_EQ(2u, map.size()); |
| 203 |
| 204 buffer.clear(); |
| 205 MakeMessage(RTM_DELADDR, 0, AF_INET, kEmpty, kAddr0, &buffer); |
| 206 EXPECT_TRUE(HandleMessage(&buffer[0], buffer.size())); |
| 207 map = GetMap(); |
| 208 EXPECT_EQ(1u, map.size()); |
| 209 EXPECT_TRUE(map.find(kAddr0) == map.end()); |
| 210 EXPECT_TRUE(map.find(kAddr2) != map.end()); |
| 211 |
| 212 buffer.clear(); |
| 213 MakeMessage(RTM_DELADDR, 0, AF_INET, kAddr2, kAddr1, &buffer); |
| 214 // kAddr1 does not exist in the map. |
| 215 EXPECT_FALSE(HandleMessage(&buffer[0], buffer.size())); |
| 216 map = GetMap(); |
| 217 EXPECT_EQ(1u, map.size()); |
| 218 |
| 219 buffer.clear(); |
| 220 MakeMessage(RTM_DELADDR, 0, AF_INET, kAddr2, kEmpty, &buffer); |
| 221 EXPECT_TRUE(HandleMessage(&buffer[0], buffer.size())); |
| 222 map = GetMap(); |
| 223 EXPECT_EQ(0u, map.size()); |
| 224 } |
| 225 |
| 226 TEST_F(AddressTrackerLinuxTest, IgnoredMessage) { |
| 227 const IPAddressNumber kEmpty; |
| 228 const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0)); |
| 229 const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3)); |
| 230 |
| 231 Buffer buffer; |
| 232 // Ignored family. |
| 233 MakeMessage(RTM_NEWADDR, 0, AF_UNSPEC, kAddr3, kAddr0, &buffer); |
| 234 // No address. |
| 235 MakeMessage(RTM_NEWADDR, 0, AF_INET, kEmpty, kEmpty, &buffer); |
| 236 // Ignored type. |
| 237 MakeMessage(RTM_DELROUTE, 0, AF_INET6, kAddr3, kEmpty, &buffer); |
| 238 EXPECT_FALSE(HandleMessage(&buffer[0], buffer.size())); |
| 239 EXPECT_EQ(0u, GetMap().size()); |
| 240 |
| 241 // Valid message after ignored messages. |
| 242 NetlinkMessage nlmsg(RTM_NEWADDR); |
| 243 struct ifaddrmsg msg = {}; |
| 244 msg.ifa_family = AF_INET; |
| 245 nlmsg.AddPayload(&msg, sizeof(msg)); |
| 246 // Ignored attribute. |
| 247 struct ifa_cacheinfo cache_info = {}; |
| 248 nlmsg.AddAttribute(IFA_CACHEINFO, &cache_info, sizeof(cache_info)); |
| 249 nlmsg.AddAttribute(IFA_ADDRESS, &kAddr0[0], kAddr0.size()); |
| 250 nlmsg.AppendTo(&buffer); |
| 251 |
| 252 EXPECT_TRUE(HandleMessage(&buffer[0], buffer.size())); |
| 253 EXPECT_EQ(1u, GetMap().size()); |
| 254 } |
| 255 |
| 256 } // namespace |
| 257 |
| 258 } // namespace internal |
| 259 } // namespace net |
OLD | NEW |