19ad3ddeac1f74bf2ed822cc5cee80684b124969
[platform/framework/web/crosswalk.git] / src / net / base / address_tracker_linux_unittest.cc
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 <linux/if.h>
8
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace net {
15 namespace internal {
16
17 typedef std::vector<char> Buffer;
18
19 void Noop() {}
20
21 class AddressTrackerLinuxTest : public testing::Test {
22  protected:
23   AddressTrackerLinuxTest() : tracker_(base::Bind(&Noop), base::Bind(&Noop)) {}
24
25   bool HandleAddressMessage(const Buffer& buf) {
26     Buffer writable_buf = buf;
27     bool address_changed = false;
28     bool link_changed = false;
29     tracker_.HandleMessage(&writable_buf[0], buf.size(),
30                            &address_changed, &link_changed);
31     EXPECT_FALSE(link_changed);
32     return address_changed;
33   }
34
35   bool HandleLinkMessage(const Buffer& buf) {
36     Buffer writable_buf = buf;
37     bool address_changed = false;
38     bool link_changed = false;
39     tracker_.HandleMessage(&writable_buf[0], buf.size(),
40                            &address_changed, &link_changed);
41     EXPECT_FALSE(address_changed);
42     return link_changed;
43   }
44
45   AddressTrackerLinux::AddressMap GetAddressMap() {
46     return tracker_.GetAddressMap();
47   }
48
49   const base::hash_set<int>* GetOnlineLinks() const {
50     return &tracker_.online_links_;
51   }
52
53   AddressTrackerLinux tracker_;
54 };
55
56 namespace {
57
58 class NetlinkMessage {
59  public:
60   explicit NetlinkMessage(uint16 type) : buffer_(NLMSG_HDRLEN) {
61     header()->nlmsg_type = type;
62     Align();
63   }
64
65   void AddPayload(const void* data, size_t length) {
66     CHECK_EQ(static_cast<size_t>(NLMSG_HDRLEN),
67              buffer_.size()) << "Payload must be added first";
68     Append(data, length);
69     Align();
70   }
71
72   void AddAttribute(uint16 type, const void* data, size_t length) {
73     struct nlattr attr;
74     attr.nla_len = NLA_HDRLEN + length;
75     attr.nla_type = type;
76     Append(&attr, sizeof(attr));
77     Align();
78     Append(data, length);
79     Align();
80   }
81
82   void AppendTo(Buffer* output) const {
83     CHECK_EQ(NLMSG_ALIGN(output->size()), output->size());
84     output->reserve(output->size() + NLMSG_LENGTH(buffer_.size()));
85     output->insert(output->end(), buffer_.begin(), buffer_.end());
86   }
87
88  private:
89   void Append(const void* data, size_t length) {
90     const char* chardata = reinterpret_cast<const char*>(data);
91     buffer_.insert(buffer_.end(), chardata, chardata + length);
92   }
93
94   void Align() {
95     header()->nlmsg_len = buffer_.size();
96     buffer_.insert(buffer_.end(), NLMSG_ALIGN(buffer_.size()) - buffer_.size(),
97                    0);
98     CHECK(NLMSG_OK(header(), buffer_.size()));
99   }
100
101   struct nlmsghdr* header() {
102     return reinterpret_cast<struct nlmsghdr*>(&buffer_[0]);
103   }
104
105   Buffer buffer_;
106 };
107
108 #define INFINITY_LIFE_TIME 0xFFFFFFFF
109
110 void MakeAddrMessageWithCacheInfo(uint16 type,
111                                   uint8 flags,
112                                   uint8 family,
113                                   const IPAddressNumber& address,
114                                   const IPAddressNumber& local,
115                                   uint32 preferred_lifetime,
116                                   Buffer* output) {
117   NetlinkMessage nlmsg(type);
118   struct ifaddrmsg msg = {};
119   msg.ifa_family = family;
120   msg.ifa_flags = flags;
121   nlmsg.AddPayload(&msg, sizeof(msg));
122   if (address.size())
123     nlmsg.AddAttribute(IFA_ADDRESS, &address[0], address.size());
124   if (local.size())
125     nlmsg.AddAttribute(IFA_LOCAL, &local[0], local.size());
126   struct ifa_cacheinfo cache_info = {};
127   cache_info.ifa_prefered = preferred_lifetime;
128   cache_info.ifa_valid = INFINITY_LIFE_TIME;
129   nlmsg.AddAttribute(IFA_CACHEINFO, &cache_info, sizeof(cache_info));
130   nlmsg.AppendTo(output);
131 }
132
133 void MakeAddrMessage(uint16 type,
134                      uint8 flags,
135                      uint8 family,
136                      const IPAddressNumber& address,
137                      const IPAddressNumber& local,
138                      Buffer* output) {
139   MakeAddrMessageWithCacheInfo(type, flags, family, address, local,
140                                INFINITY_LIFE_TIME, output);
141 }
142
143 void MakeLinkMessage(uint16 type, uint32 flags, uint32 index, Buffer* output) {
144   NetlinkMessage nlmsg(type);
145   struct ifinfomsg msg = {};
146   msg.ifi_index = index;
147   msg.ifi_flags = flags;
148   nlmsg.AddPayload(&msg, sizeof(msg));
149   output->clear();
150   nlmsg.AppendTo(output);
151 }
152
153 const unsigned char kAddress0[] = { 127, 0, 0, 1 };
154 const unsigned char kAddress1[] = { 10, 0, 0, 1 };
155 const unsigned char kAddress2[] = { 192, 168, 0, 1 };
156 const unsigned char kAddress3[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
157                                     0, 0, 0, 1 };
158
159 TEST_F(AddressTrackerLinuxTest, NewAddress) {
160   const IPAddressNumber kEmpty;
161   const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
162   const IPAddressNumber kAddr1(kAddress1, kAddress1 + arraysize(kAddress1));
163   const IPAddressNumber kAddr2(kAddress2, kAddress2 + arraysize(kAddress2));
164   const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3));
165
166   Buffer buffer;
167   MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty,
168                   &buffer);
169   EXPECT_TRUE(HandleAddressMessage(buffer));
170   AddressTrackerLinux::AddressMap map = GetAddressMap();
171   EXPECT_EQ(1u, map.size());
172   EXPECT_EQ(1u, map.count(kAddr0));
173   EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
174
175   buffer.clear();
176   MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr1, kAddr2,
177                   &buffer);
178   EXPECT_TRUE(HandleAddressMessage(buffer));
179   map = GetAddressMap();
180   EXPECT_EQ(2u, map.size());
181   EXPECT_EQ(1u, map.count(kAddr0));
182   EXPECT_EQ(1u, map.count(kAddr2));
183   EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr2].ifa_flags);
184
185   buffer.clear();
186   MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, &buffer);
187   EXPECT_TRUE(HandleAddressMessage(buffer));
188   map = GetAddressMap();
189   EXPECT_EQ(3u, map.size());
190   EXPECT_EQ(1u, map.count(kAddr3));
191 }
192
193 TEST_F(AddressTrackerLinuxTest, NewAddressChange) {
194   const IPAddressNumber kEmpty;
195   const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
196
197   Buffer buffer;
198   MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty,
199                   &buffer);
200   EXPECT_TRUE(HandleAddressMessage(buffer));
201   AddressTrackerLinux::AddressMap map = GetAddressMap();
202   EXPECT_EQ(1u, map.size());
203   EXPECT_EQ(1u, map.count(kAddr0));
204   EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
205
206   buffer.clear();
207   MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr0, kEmpty,
208                   &buffer);
209   EXPECT_TRUE(HandleAddressMessage(buffer));
210   map = GetAddressMap();
211   EXPECT_EQ(1u, map.size());
212   EXPECT_EQ(1u, map.count(kAddr0));
213   EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags);
214
215   // Both messages in one buffer.
216   buffer.clear();
217   MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kEmpty,
218                   &buffer);
219   MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kAddr0, kEmpty,
220                   &buffer);
221   EXPECT_TRUE(HandleAddressMessage(buffer));
222   map = GetAddressMap();
223   EXPECT_EQ(1u, map.size());
224   EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags);
225 }
226
227 TEST_F(AddressTrackerLinuxTest, NewAddressDuplicate) {
228   const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
229
230   Buffer buffer;
231   MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kAddr0, kAddr0,
232                   &buffer);
233   EXPECT_TRUE(HandleAddressMessage(buffer));
234   AddressTrackerLinux::AddressMap map = GetAddressMap();
235   EXPECT_EQ(1u, map.size());
236   EXPECT_EQ(1u, map.count(kAddr0));
237   EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
238
239   EXPECT_FALSE(HandleAddressMessage(buffer));
240   map = GetAddressMap();
241   EXPECT_EQ(1u, map.size());
242   EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
243 }
244
245 TEST_F(AddressTrackerLinuxTest, DeleteAddress) {
246   const IPAddressNumber kEmpty;
247   const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
248   const IPAddressNumber kAddr1(kAddress1, kAddress1 + arraysize(kAddress1));
249   const IPAddressNumber kAddr2(kAddress2, kAddress2 + arraysize(kAddress2));
250
251   Buffer buffer;
252   MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kAddr0, kEmpty, &buffer);
253   MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kAddr1, kAddr2, &buffer);
254   EXPECT_TRUE(HandleAddressMessage(buffer));
255   AddressTrackerLinux::AddressMap map = GetAddressMap();
256   EXPECT_EQ(2u, map.size());
257
258   buffer.clear();
259   MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kEmpty, kAddr0, &buffer);
260   EXPECT_TRUE(HandleAddressMessage(buffer));
261   map = GetAddressMap();
262   EXPECT_EQ(1u, map.size());
263   EXPECT_EQ(0u, map.count(kAddr0));
264   EXPECT_EQ(1u, map.count(kAddr2));
265
266   buffer.clear();
267   MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kAddr2, kAddr1, &buffer);
268   // kAddr1 does not exist in the map.
269   EXPECT_FALSE(HandleAddressMessage(buffer));
270   map = GetAddressMap();
271   EXPECT_EQ(1u, map.size());
272
273   buffer.clear();
274   MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kAddr2, kEmpty, &buffer);
275   EXPECT_TRUE(HandleAddressMessage(buffer));
276   map = GetAddressMap();
277   EXPECT_EQ(0u, map.size());
278 }
279
280 TEST_F(AddressTrackerLinuxTest, DeprecatedLifetime) {
281   const IPAddressNumber kEmpty;
282   const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3));
283
284   Buffer buffer;
285   MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, &buffer);
286   EXPECT_TRUE(HandleAddressMessage(buffer));
287   AddressTrackerLinux::AddressMap map = GetAddressMap();
288   EXPECT_EQ(1u, map.size());
289   EXPECT_EQ(1u, map.count(kAddr3));
290   EXPECT_EQ(0, map[kAddr3].ifa_flags);
291
292   // Verify 0 preferred lifetime implies deprecated.
293   buffer.clear();
294   MakeAddrMessageWithCacheInfo(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, 0,
295                                &buffer);
296   EXPECT_TRUE(HandleAddressMessage(buffer));
297   map = GetAddressMap();
298   EXPECT_EQ(1u, map.size());
299   EXPECT_EQ(IFA_F_DEPRECATED, map[kAddr3].ifa_flags);
300
301   // Verify properly flagged message doesn't imply change.
302   buffer.clear();
303   MakeAddrMessageWithCacheInfo(RTM_NEWADDR, IFA_F_DEPRECATED, AF_INET6, kEmpty,
304                                kAddr3, 0, &buffer);
305   EXPECT_FALSE(HandleAddressMessage(buffer));
306   map = GetAddressMap();
307   EXPECT_EQ(1u, map.size());
308   EXPECT_EQ(IFA_F_DEPRECATED, map[kAddr3].ifa_flags);
309
310   // Verify implied deprecated doesn't imply change.
311   buffer.clear();
312   MakeAddrMessageWithCacheInfo(RTM_NEWADDR, 0, AF_INET6, kEmpty, kAddr3, 0,
313                                &buffer);
314   EXPECT_FALSE(HandleAddressMessage(buffer));
315   map = GetAddressMap();
316   EXPECT_EQ(1u, map.size());
317   EXPECT_EQ(IFA_F_DEPRECATED, map[kAddr3].ifa_flags);
318 }
319
320 TEST_F(AddressTrackerLinuxTest, IgnoredMessage) {
321   const IPAddressNumber kEmpty;
322   const IPAddressNumber kAddr0(kAddress0, kAddress0 + arraysize(kAddress0));
323   const IPAddressNumber kAddr3(kAddress3, kAddress3 + arraysize(kAddress3));
324
325   Buffer buffer;
326   // Ignored family.
327   MakeAddrMessage(RTM_NEWADDR, 0, AF_UNSPEC, kAddr3, kAddr0, &buffer);
328   // No address.
329   MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kEmpty, kEmpty, &buffer);
330   // Ignored type.
331   MakeAddrMessage(RTM_DELROUTE, 0, AF_INET6, kAddr3, kEmpty, &buffer);
332   EXPECT_FALSE(HandleAddressMessage(buffer));
333   EXPECT_TRUE(GetAddressMap().empty());
334
335   // Valid message after ignored messages.
336   NetlinkMessage nlmsg(RTM_NEWADDR);
337   struct ifaddrmsg msg = {};
338   msg.ifa_family = AF_INET;
339   nlmsg.AddPayload(&msg, sizeof(msg));
340   // Ignored attribute.
341   struct ifa_cacheinfo cache_info = {};
342   nlmsg.AddAttribute(IFA_CACHEINFO, &cache_info, sizeof(cache_info));
343   nlmsg.AddAttribute(IFA_ADDRESS, &kAddr0[0], kAddr0.size());
344   nlmsg.AppendTo(&buffer);
345
346   EXPECT_TRUE(HandleAddressMessage(buffer));
347   EXPECT_EQ(1u, GetAddressMap().size());
348 }
349
350 TEST_F(AddressTrackerLinuxTest, AddInterface) {
351   Buffer buffer;
352
353   // Ignores loopback.
354   MakeLinkMessage(RTM_NEWLINK,
355                   IFF_LOOPBACK | IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
356                   0, &buffer);
357   EXPECT_FALSE(HandleLinkMessage(buffer));
358   EXPECT_TRUE(GetOnlineLinks()->empty());
359
360   // Ignores not IFF_LOWER_UP.
361   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer);
362   EXPECT_FALSE(HandleLinkMessage(buffer));
363   EXPECT_TRUE(GetOnlineLinks()->empty());
364
365   // Ignores deletion.
366   MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer);
367   EXPECT_FALSE(HandleLinkMessage(buffer));
368   EXPECT_TRUE(GetOnlineLinks()->empty());
369
370   // Verify success.
371   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer);
372   EXPECT_TRUE(HandleLinkMessage(buffer));
373   EXPECT_EQ(1u, GetOnlineLinks()->count(0));
374   EXPECT_EQ(1u, GetOnlineLinks()->size());
375
376   // Ignores redundant enables.
377   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer);
378   EXPECT_FALSE(HandleLinkMessage(buffer));
379   EXPECT_EQ(1u, GetOnlineLinks()->count(0));
380   EXPECT_EQ(1u, GetOnlineLinks()->size());
381
382   // Verify adding another online device (e.g. VPN) is considered a change.
383   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 1, &buffer);
384   EXPECT_TRUE(HandleLinkMessage(buffer));
385   EXPECT_EQ(1u, GetOnlineLinks()->count(0));
386   EXPECT_EQ(1u, GetOnlineLinks()->count(1));
387   EXPECT_EQ(2u, GetOnlineLinks()->size());
388 }
389
390 TEST_F(AddressTrackerLinuxTest, RemoveInterface) {
391   Buffer buffer;
392
393   // Should disappear when not IFF_LOWER_UP.
394   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer);
395   EXPECT_TRUE(HandleLinkMessage(buffer));
396   EXPECT_FALSE(GetOnlineLinks()->empty());
397   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer);
398   EXPECT_TRUE(HandleLinkMessage(buffer));
399   EXPECT_TRUE(GetOnlineLinks()->empty());
400
401   // Ignores redundant disables.
402   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, 0, &buffer);
403   EXPECT_FALSE(HandleLinkMessage(buffer));
404   EXPECT_TRUE(GetOnlineLinks()->empty());
405
406   // Ignores deleting down interfaces.
407   MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_RUNNING, 0, &buffer);
408   EXPECT_FALSE(HandleLinkMessage(buffer));
409   EXPECT_TRUE(GetOnlineLinks()->empty());
410
411   // Should disappear when deleted.
412   MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer);
413   EXPECT_TRUE(HandleLinkMessage(buffer));
414   EXPECT_FALSE(GetOnlineLinks()->empty());
415   MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 0, &buffer);
416   EXPECT_TRUE(HandleLinkMessage(buffer));
417   EXPECT_TRUE(GetOnlineLinks()->empty());
418 }
419
420 }  // namespace
421
422 }  // namespace internal
423 }  // namespace net