1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 // Original author: bcampen@mozilla.com
8 
9 extern "C" {
10 #include "stun_msg.h"  // for NR_STUN_MAX_MESSAGE_SIZE
11 #include "stun_util.h"
12 #include "nr_api.h"
13 #include "async_wait.h"
14 #include "nr_socket.h"
15 #include "nr_socket_local.h"
16 #include "stun_hint.h"
17 #include "local_addr.h"
18 #include "registry.h"
19 }
20 
21 #include "test_nr_socket.h"
22 
23 #include "nsCOMPtr.h"
24 #include "nsNetCID.h"
25 #include "nsServiceManagerUtils.h"
26 #include "runnable_utils.h"
27 
28 #include <vector>
29 
30 #define GTEST_HAS_RTTI 0
31 #include "gtest/gtest.h"
32 #include "gtest_utils.h"
33 
34 #define DATA_BUF_SIZE 1024
35 
36 namespace mozilla {
37 
38 class TestNrSocketTest : public MtransportTest {
39  public:
TestNrSocketTest()40   TestNrSocketTest()
41       : MtransportTest(),
42         wait_done_for_main_(false),
43         sts_(),
44         public_addrs_(),
45         private_addrs_(),
46         nats_() {}
47 
SetUp()48   void SetUp() override {
49     MtransportTest::SetUp();
50 
51     // Get the transport service as a dispatch target
52     nsresult rv;
53     sts_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
54     EXPECT_TRUE(NS_SUCCEEDED(rv)) << "Failed to get STS: " << (int)rv;
55   }
56 
TearDown()57   void TearDown() override {
58     sts_->Dispatch(WrapRunnable(this, &TestNrSocketTest::TearDown_s),
59                    NS_DISPATCH_SYNC);
60 
61     MtransportTest::TearDown();
62   }
63 
TearDown_s()64   void TearDown_s() {
65     public_addrs_.clear();
66     private_addrs_.clear();
67     nats_.clear();
68     sts_ = nullptr;
69   }
70 
CreateTestNrSocket_s(const char * ip_str,int proto,TestNat * nat)71   RefPtr<TestNrSocket> CreateTestNrSocket_s(const char* ip_str, int proto,
72                                             TestNat* nat) {
73     // If no nat is supplied, we create a default NAT which is disabled. This
74     // is how we simulate a non-natted socket.
75     RefPtr<TestNrSocket> sock(new TestNrSocket(nat ? nat : new TestNat));
76     nr_transport_addr address;
77     nr_str_port_to_transport_addr(ip_str, 0, proto, &address);
78     int r = sock->create(&address);
79     if (r) {
80       return nullptr;
81     }
82     return sock;
83   }
84 
CreatePublicAddrs(size_t count,const char * ip_str="127.0.0.1",int proto=IPPROTO_UDP)85   void CreatePublicAddrs(size_t count, const char* ip_str = "127.0.0.1",
86                          int proto = IPPROTO_UDP) {
87     sts_->Dispatch(WrapRunnable(this, &TestNrSocketTest::CreatePublicAddrs_s,
88                                 count, ip_str, proto),
89                    NS_DISPATCH_SYNC);
90   }
91 
CreatePublicAddrs_s(size_t count,const char * ip_str,int proto)92   void CreatePublicAddrs_s(size_t count, const char* ip_str, int proto) {
93     while (count--) {
94       auto sock = CreateTestNrSocket_s(ip_str, proto, nullptr);
95       ASSERT_TRUE(sock)
96       << "Failed to create socket";
97       public_addrs_.push_back(sock);
98     }
99   }
100 
CreatePrivateAddrs(size_t size,const char * ip_str="127.0.0.1",int proto=IPPROTO_UDP)101   RefPtr<TestNat> CreatePrivateAddrs(size_t size,
102                                      const char* ip_str = "127.0.0.1",
103                                      int proto = IPPROTO_UDP) {
104     RefPtr<TestNat> result;
105     sts_->Dispatch(
106         WrapRunnableRet(&result, this, &TestNrSocketTest::CreatePrivateAddrs_s,
107                         size, ip_str, proto),
108         NS_DISPATCH_SYNC);
109     return result;
110   }
111 
CreatePrivateAddrs_s(size_t count,const char * ip_str,int proto)112   RefPtr<TestNat> CreatePrivateAddrs_s(size_t count, const char* ip_str,
113                                        int proto) {
114     RefPtr<TestNat> nat(new TestNat);
115     while (count--) {
116       auto sock = CreateTestNrSocket_s(ip_str, proto, nat);
117       if (!sock) {
118         EXPECT_TRUE(false) << "Failed to create socket";
119         break;
120       }
121       private_addrs_.push_back(sock);
122     }
123     nat->enabled_ = true;
124     nats_.push_back(nat);
125     return nat;
126   }
127 
CheckConnectivityVia(TestNrSocket * from,TestNrSocket * to,const nr_transport_addr & via,nr_transport_addr * sender_external_address=nullptr)128   bool CheckConnectivityVia(
129       TestNrSocket* from, TestNrSocket* to, const nr_transport_addr& via,
130       nr_transport_addr* sender_external_address = nullptr) {
131     MOZ_ASSERT(from);
132 
133     if (!WaitForWriteable(from)) {
134       return false;
135     }
136 
137     int result = 0;
138     sts_->Dispatch(WrapRunnableRet(&result, this, &TestNrSocketTest::SendData_s,
139                                    from, via),
140                    NS_DISPATCH_SYNC);
141     if (result) {
142       return false;
143     }
144 
145     if (!WaitForReadable(to)) {
146       return false;
147     }
148 
149     nr_transport_addr dummy_outparam;
150     if (!sender_external_address) {
151       sender_external_address = &dummy_outparam;
152     }
153 
154     MOZ_ASSERT(to);
155     sts_->Dispatch(WrapRunnableRet(&result, this, &TestNrSocketTest::RecvData_s,
156                                    to, sender_external_address),
157                    NS_DISPATCH_SYNC);
158 
159     return !result;
160   }
161 
CheckConnectivity(TestNrSocket * from,TestNrSocket * to,nr_transport_addr * sender_external_address=nullptr)162   bool CheckConnectivity(TestNrSocket* from, TestNrSocket* to,
163                          nr_transport_addr* sender_external_address = nullptr) {
164     nr_transport_addr destination_address;
165     int r = GetAddress(to, &destination_address);
166     if (r) {
167       return false;
168     }
169 
170     return CheckConnectivityVia(from, to, destination_address,
171                                 sender_external_address);
172   }
173 
CheckTcpConnectivity(TestNrSocket * from,TestNrSocket * to)174   bool CheckTcpConnectivity(TestNrSocket* from, TestNrSocket* to) {
175     NrSocketBase* accepted_sock;
176     if (!Connect(from, to, &accepted_sock)) {
177       std::cerr << "Connect failed" << std::endl;
178       return false;
179     }
180 
181     // write on |from|, recv on |accepted_sock|
182     if (!WaitForWriteable(from)) {
183       std::cerr << __LINE__ << "WaitForWriteable (1) failed" << std::endl;
184       return false;
185     }
186 
187     int r;
188     sts_->Dispatch(
189         WrapRunnableRet(&r, this, &TestNrSocketTest::SendDataTcp_s, from),
190         NS_DISPATCH_SYNC);
191     if (r) {
192       std::cerr << "SendDataTcp_s (1) failed" << std::endl;
193       return false;
194     }
195 
196     if (!WaitForReadable(accepted_sock)) {
197       std::cerr << __LINE__ << "WaitForReadable (1) failed" << std::endl;
198       return false;
199     }
200 
201     sts_->Dispatch(WrapRunnableRet(&r, this, &TestNrSocketTest::RecvDataTcp_s,
202                                    accepted_sock),
203                    NS_DISPATCH_SYNC);
204     if (r) {
205       std::cerr << "RecvDataTcp_s (1) failed" << std::endl;
206       return false;
207     }
208 
209     if (!WaitForWriteable(accepted_sock)) {
210       std::cerr << __LINE__ << "WaitForWriteable (2) failed" << std::endl;
211       return false;
212     }
213 
214     sts_->Dispatch(WrapRunnableRet(&r, this, &TestNrSocketTest::SendDataTcp_s,
215                                    accepted_sock),
216                    NS_DISPATCH_SYNC);
217     if (r) {
218       std::cerr << "SendDataTcp_s (2) failed" << std::endl;
219       return false;
220     }
221 
222     if (!WaitForReadable(from)) {
223       std::cerr << __LINE__ << "WaitForReadable (2) failed" << std::endl;
224       return false;
225     }
226 
227     sts_->Dispatch(
228         WrapRunnableRet(&r, this, &TestNrSocketTest::RecvDataTcp_s, from),
229         NS_DISPATCH_SYNC);
230     if (r) {
231       std::cerr << "RecvDataTcp_s (2) failed" << std::endl;
232       return false;
233     }
234 
235     return true;
236   }
237 
GetAddress(TestNrSocket * sock,nr_transport_addr_ * address)238   int GetAddress(TestNrSocket* sock, nr_transport_addr_* address) {
239     MOZ_ASSERT(sock);
240     MOZ_ASSERT(address);
241     int r;
242     sts_->Dispatch(WrapRunnableRet(&r, this, &TestNrSocketTest::GetAddress_s,
243                                    sock, address),
244                    NS_DISPATCH_SYNC);
245     return r;
246   }
247 
GetAddress_s(TestNrSocket * sock,nr_transport_addr * address)248   int GetAddress_s(TestNrSocket* sock, nr_transport_addr* address) {
249     return sock->getaddr(address);
250   }
251 
SendData_s(TestNrSocket * from,const nr_transport_addr & to)252   int SendData_s(TestNrSocket* from, const nr_transport_addr& to) {
253     // It is up to caller to ensure that |from| is writeable.
254     const char buf[] = "foobajooba";
255     return from->sendto(
256         buf, sizeof(buf), 0,
257         // TODO(bug 1170299): Remove const_cast when no longer necessary
258         const_cast<nr_transport_addr*>(&to));
259   }
260 
SendDataTcp_s(NrSocketBase * from)261   int SendDataTcp_s(NrSocketBase* from) {
262     // It is up to caller to ensure that |from| is writeable.
263     const char buf[] = "foobajooba";
264     size_t written;
265     return from->write(buf, sizeof(buf), &written);
266   }
267 
RecvData_s(TestNrSocket * to,nr_transport_addr * from)268   int RecvData_s(TestNrSocket* to, nr_transport_addr* from) {
269     // It is up to caller to ensure that |to| is readable
270     char buf[DATA_BUF_SIZE];
271     size_t len;
272     // Maybe check that data matches?
273     int r = to->recvfrom(buf, sizeof(buf), &len, 0, from);
274     if (!r && (len == 0)) {
275       r = R_INTERNAL;
276     }
277     return r;
278   }
279 
RecvDataTcp_s(NrSocketBase * to)280   int RecvDataTcp_s(NrSocketBase* to) {
281     // It is up to caller to ensure that |to| is readable
282     char buf[DATA_BUF_SIZE];
283     size_t len;
284     // Maybe check that data matches?
285     int r = to->read(buf, sizeof(buf), &len);
286     if (!r && (len == 0)) {
287       r = R_INTERNAL;
288     }
289     return r;
290   }
291 
Listen_s(TestNrSocket * to)292   int Listen_s(TestNrSocket* to) {
293     // listen on |to|
294     int r = to->listen(1);
295     if (r) {
296       return r;
297     }
298     return 0;
299   }
300 
Connect_s(TestNrSocket * from,TestNrSocket * to)301   int Connect_s(TestNrSocket* from, TestNrSocket* to) {
302     // connect on |from|
303     nr_transport_addr destination_address;
304     int r = to->getaddr(&destination_address);
305     if (r) {
306       return r;
307     }
308 
309     r = from->connect(&destination_address);
310     if (r) {
311       return r;
312     }
313 
314     return 0;
315   }
316 
Accept_s(TestNrSocket * to,NrSocketBase ** accepted_sock)317   int Accept_s(TestNrSocket* to, NrSocketBase** accepted_sock) {
318     nr_socket* sock;
319     nr_transport_addr source_address;
320     int r = to->accept(&source_address, &sock);
321     if (r) {
322       return r;
323     }
324 
325     *accepted_sock = reinterpret_cast<NrSocketBase*>(sock->obj);
326     return 0;
327   }
328 
Connect(TestNrSocket * from,TestNrSocket * to,NrSocketBase ** accepted_sock)329   bool Connect(TestNrSocket* from, TestNrSocket* to,
330                NrSocketBase** accepted_sock) {
331     int r;
332     sts_->Dispatch(WrapRunnableRet(&r, this, &TestNrSocketTest::Listen_s, to),
333                    NS_DISPATCH_SYNC);
334     if (r) {
335       std::cerr << "Listen_s failed: " << r << std::endl;
336       return false;
337     }
338 
339     sts_->Dispatch(
340         WrapRunnableRet(&r, this, &TestNrSocketTest::Connect_s, from, to),
341         NS_DISPATCH_SYNC);
342     if (r && r != R_WOULDBLOCK) {
343       std::cerr << "Connect_s failed: " << r << std::endl;
344       return false;
345     }
346 
347     if (!WaitForReadable(to)) {
348       std::cerr << "WaitForReadable failed" << std::endl;
349       return false;
350     }
351 
352     sts_->Dispatch(WrapRunnableRet(&r, this, &TestNrSocketTest::Accept_s, to,
353                                    accepted_sock),
354                    NS_DISPATCH_SYNC);
355 
356     if (r) {
357       std::cerr << "Accept_s failed: " << r << std::endl;
358       return false;
359     }
360     return true;
361   }
362 
WaitForSocketState(NrSocketBase * sock,int state)363   bool WaitForSocketState(NrSocketBase* sock, int state) {
364     MOZ_ASSERT(sock);
365     sts_->Dispatch(WrapRunnable(this, &TestNrSocketTest::WaitForSocketState_s,
366                                 sock, state),
367                    NS_DISPATCH_SYNC);
368 
369     bool res;
370     WAIT_(wait_done_for_main_, 500, res);
371     wait_done_for_main_ = false;
372 
373     if (!res) {
374       sts_->Dispatch(
375           WrapRunnable(this, &TestNrSocketTest::CancelWait_s, sock, state),
376           NS_DISPATCH_SYNC);
377     }
378 
379     return res;
380   }
381 
WaitForSocketState_s(NrSocketBase * sock,int state)382   void WaitForSocketState_s(NrSocketBase* sock, int state) {
383     NR_ASYNC_WAIT(sock, state, &WaitDone, this);
384   }
385 
CancelWait_s(NrSocketBase * sock,int state)386   void CancelWait_s(NrSocketBase* sock, int state) { sock->cancel(state); }
387 
WaitForReadable(NrSocketBase * sock)388   bool WaitForReadable(NrSocketBase* sock) {
389     return WaitForSocketState(sock, NR_ASYNC_WAIT_READ);
390   }
391 
WaitForWriteable(NrSocketBase * sock)392   bool WaitForWriteable(NrSocketBase* sock) {
393     return WaitForSocketState(sock, NR_ASYNC_WAIT_WRITE);
394   }
395 
WaitDone(void * sock,int how,void * test_fixture)396   static void WaitDone(void* sock, int how, void* test_fixture) {
397     TestNrSocketTest* test = static_cast<TestNrSocketTest*>(test_fixture);
398     test->wait_done_for_main_ = true;
399   }
400 
401   // Simple busywait boolean for the test cases to spin on.
402   Atomic<bool> wait_done_for_main_;
403 
404   nsCOMPtr<nsIEventTarget> sts_;
405   std::vector<RefPtr<TestNrSocket>> public_addrs_;
406   std::vector<RefPtr<TestNrSocket>> private_addrs_;
407   std::vector<RefPtr<TestNat>> nats_;
408 };
409 
410 }  // namespace mozilla
411 
412 using mozilla::NrSocketBase;
413 using mozilla::TestNat;
414 using mozilla::TestNrSocketTest;
415 
TEST_F(TestNrSocketTest,UnsafePortRejectedUDP)416 TEST_F(TestNrSocketTest, UnsafePortRejectedUDP) {
417   nr_transport_addr address;
418   ASSERT_FALSE(nr_str_port_to_transport_addr("127.0.0.1",
419                                              // ssh
420                                              22, IPPROTO_UDP, &address));
421   ASSERT_TRUE(NrSocketBase::IsForbiddenAddress(&address));
422 }
423 
TEST_F(TestNrSocketTest,UnsafePortRejectedTCP)424 TEST_F(TestNrSocketTest, UnsafePortRejectedTCP) {
425   nr_transport_addr address;
426   ASSERT_FALSE(nr_str_port_to_transport_addr("127.0.0.1",
427                                              // ssh
428                                              22, IPPROTO_TCP, &address));
429   ASSERT_TRUE(NrSocketBase::IsForbiddenAddress(&address));
430 }
431 
TEST_F(TestNrSocketTest,SafePortAcceptedUDP)432 TEST_F(TestNrSocketTest, SafePortAcceptedUDP) {
433   nr_transport_addr address;
434   ASSERT_FALSE(nr_str_port_to_transport_addr("127.0.0.1",
435                                              // stuns
436                                              5349, IPPROTO_UDP, &address));
437   ASSERT_FALSE(NrSocketBase::IsForbiddenAddress(&address));
438 }
439 
TEST_F(TestNrSocketTest,SafePortAcceptedTCP)440 TEST_F(TestNrSocketTest, SafePortAcceptedTCP) {
441   nr_transport_addr address;
442   ASSERT_FALSE(nr_str_port_to_transport_addr("127.0.0.1",
443                                              // turns
444                                              5349, IPPROTO_TCP, &address));
445   ASSERT_FALSE(NrSocketBase::IsForbiddenAddress(&address));
446 }
447 
TEST_F(TestNrSocketTest,PublicConnectivity)448 TEST_F(TestNrSocketTest, PublicConnectivity) {
449   CreatePublicAddrs(2);
450 
451   ASSERT_TRUE(CheckConnectivity(public_addrs_[0], public_addrs_[1]));
452   ASSERT_TRUE(CheckConnectivity(public_addrs_[1], public_addrs_[0]));
453   ASSERT_TRUE(CheckConnectivity(public_addrs_[0], public_addrs_[0]));
454   ASSERT_TRUE(CheckConnectivity(public_addrs_[1], public_addrs_[1]));
455 }
456 
TEST_F(TestNrSocketTest,PrivateConnectivity)457 TEST_F(TestNrSocketTest, PrivateConnectivity) {
458   RefPtr<TestNat> nat(CreatePrivateAddrs(2));
459   nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
460   nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
461 
462   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], private_addrs_[1]));
463   ASSERT_TRUE(CheckConnectivity(private_addrs_[1], private_addrs_[0]));
464   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], private_addrs_[0]));
465   ASSERT_TRUE(CheckConnectivity(private_addrs_[1], private_addrs_[1]));
466 }
467 
TEST_F(TestNrSocketTest,NoConnectivityWithoutPinhole)468 TEST_F(TestNrSocketTest, NoConnectivityWithoutPinhole) {
469   RefPtr<TestNat> nat(CreatePrivateAddrs(1));
470   nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
471   nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
472   CreatePublicAddrs(1);
473 
474   ASSERT_FALSE(CheckConnectivity(public_addrs_[0], private_addrs_[0]));
475 }
476 
TEST_F(TestNrSocketTest,NoConnectivityBetweenSubnets)477 TEST_F(TestNrSocketTest, NoConnectivityBetweenSubnets) {
478   RefPtr<TestNat> nat1(CreatePrivateAddrs(1));
479   nat1->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
480   nat1->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
481   RefPtr<TestNat> nat2(CreatePrivateAddrs(1));
482   nat2->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
483   nat2->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
484 
485   ASSERT_FALSE(CheckConnectivity(private_addrs_[0], private_addrs_[1]));
486   ASSERT_FALSE(CheckConnectivity(private_addrs_[1], private_addrs_[0]));
487   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], private_addrs_[0]));
488   ASSERT_TRUE(CheckConnectivity(private_addrs_[1], private_addrs_[1]));
489 }
490 
TEST_F(TestNrSocketTest,FullConeAcceptIngress)491 TEST_F(TestNrSocketTest, FullConeAcceptIngress) {
492   RefPtr<TestNat> nat(CreatePrivateAddrs(1));
493   nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
494   nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
495   CreatePublicAddrs(2);
496 
497   nr_transport_addr sender_external_address;
498   // Open pinhole to public IP 0
499   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[0],
500                                 &sender_external_address));
501 
502   // Verify that return traffic works
503   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0], private_addrs_[0],
504                                    sender_external_address));
505 
506   // Verify that other public IP can use the pinhole
507   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1], private_addrs_[0],
508                                    sender_external_address));
509 }
510 
TEST_F(TestNrSocketTest,FullConeOnePinhole)511 TEST_F(TestNrSocketTest, FullConeOnePinhole) {
512   RefPtr<TestNat> nat(CreatePrivateAddrs(1));
513   nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
514   nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
515   CreatePublicAddrs(2);
516 
517   nr_transport_addr sender_external_address;
518   // Open pinhole to public IP 0
519   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[0],
520                                 &sender_external_address));
521 
522   // Verify that return traffic works
523   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0], private_addrs_[0],
524                                    sender_external_address));
525 
526   // Send traffic to other public IP, verify that it uses the same pinhole
527   nr_transport_addr sender_external_address2;
528   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[1],
529                                 &sender_external_address2));
530   ASSERT_FALSE(nr_transport_addr_cmp(&sender_external_address,
531                                      &sender_external_address2,
532                                      NR_TRANSPORT_ADDR_CMP_MODE_ALL))
533   << "addr1: " << sender_external_address.as_string
534   << " addr2: " << sender_external_address2.as_string;
535 }
536 
537 // OS 10.6 doesn't seem to allow us to open ports on 127.0.0.2, and while linux
538 // does allow this, it has other behavior (see below) that prevents this test
539 // from working.
TEST_F(TestNrSocketTest,DISABLED_AddressRestrictedCone)540 TEST_F(TestNrSocketTest, DISABLED_AddressRestrictedCone) {
541   RefPtr<TestNat> nat(CreatePrivateAddrs(1));
542   nat->filtering_type_ = TestNat::ADDRESS_DEPENDENT;
543   nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
544   CreatePublicAddrs(2, "127.0.0.1");
545   CreatePublicAddrs(1, "127.0.0.2");
546 
547   nr_transport_addr sender_external_address;
548   // Open pinhole to public IP 0
549   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[0],
550                                 &sender_external_address));
551 
552   // Verify that return traffic works
553   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0], private_addrs_[0],
554                                    sender_external_address));
555 
556   // Verify that another address on the same host can use the pinhole
557   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1], private_addrs_[0],
558                                    sender_external_address));
559 
560   // Linux has a tendency to monkey around with source addresses, doing
561   // stuff like substituting 127.0.0.1 for packets sent by 127.0.0.2, and even
562   // going as far as substituting localhost for a packet sent from a real IP
563   // address when the destination is localhost. The only way to make this test
564   // work on linux is to have two real IP addresses.
565 #ifndef __linux__
566   // Verify that an address on a different host can't use the pinhole
567   ASSERT_FALSE(CheckConnectivityVia(public_addrs_[2], private_addrs_[0],
568                                     sender_external_address));
569 #endif
570 
571   // Send traffic to other public IP, verify that it uses the same pinhole
572   nr_transport_addr sender_external_address2;
573   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[1],
574                                 &sender_external_address2));
575   ASSERT_FALSE(nr_transport_addr_cmp(&sender_external_address,
576                                      &sender_external_address2,
577                                      NR_TRANSPORT_ADDR_CMP_MODE_ALL))
578   << "addr1: " << sender_external_address.as_string
579   << " addr2: " << sender_external_address2.as_string;
580 
581   // Verify that the other public IP can now use the pinhole
582   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1], private_addrs_[0],
583                                    sender_external_address2));
584 
585   // Send traffic to other public IP, verify that it uses the same pinhole
586   nr_transport_addr sender_external_address3;
587   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[2],
588                                 &sender_external_address3));
589   ASSERT_FALSE(nr_transport_addr_cmp(&sender_external_address,
590                                      &sender_external_address3,
591                                      NR_TRANSPORT_ADDR_CMP_MODE_ALL))
592   << "addr1: " << sender_external_address.as_string
593   << " addr2: " << sender_external_address3.as_string;
594 
595   // Verify that the other public IP can now use the pinhole
596   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[2], private_addrs_[0],
597                                    sender_external_address3));
598 }
599 
TEST_F(TestNrSocketTest,RestrictedCone)600 TEST_F(TestNrSocketTest, RestrictedCone) {
601   RefPtr<TestNat> nat(CreatePrivateAddrs(1));
602   nat->filtering_type_ = TestNat::PORT_DEPENDENT;
603   nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
604   CreatePublicAddrs(2);
605 
606   nr_transport_addr sender_external_address;
607   // Open pinhole to public IP 0
608   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[0],
609                                 &sender_external_address));
610 
611   // Verify that return traffic works
612   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0], private_addrs_[0],
613                                    sender_external_address));
614 
615   // Verify that other public IP cannot use the pinhole
616   ASSERT_FALSE(CheckConnectivityVia(public_addrs_[1], private_addrs_[0],
617                                     sender_external_address));
618 
619   // Send traffic to other public IP, verify that it uses the same pinhole
620   nr_transport_addr sender_external_address2;
621   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[1],
622                                 &sender_external_address2));
623   ASSERT_FALSE(nr_transport_addr_cmp(&sender_external_address,
624                                      &sender_external_address2,
625                                      NR_TRANSPORT_ADDR_CMP_MODE_ALL))
626   << "addr1: " << sender_external_address.as_string
627   << " addr2: " << sender_external_address2.as_string;
628 
629   // Verify that the other public IP can now use the pinhole
630   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1], private_addrs_[0],
631                                    sender_external_address2));
632 }
633 
TEST_F(TestNrSocketTest,PortDependentMappingFullCone)634 TEST_F(TestNrSocketTest, PortDependentMappingFullCone) {
635   RefPtr<TestNat> nat(CreatePrivateAddrs(1));
636   nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
637   nat->mapping_type_ = TestNat::PORT_DEPENDENT;
638   CreatePublicAddrs(2);
639 
640   nr_transport_addr sender_external_address0;
641   // Open pinhole to public IP 0
642   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[0],
643                                 &sender_external_address0));
644 
645   // Verify that return traffic works
646   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0], private_addrs_[0],
647                                    sender_external_address0));
648 
649   // Verify that other public IP can use the pinhole
650   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1], private_addrs_[0],
651                                    sender_external_address0));
652 
653   // Send traffic to other public IP, verify that it uses a different pinhole
654   nr_transport_addr sender_external_address1;
655   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[1],
656                                 &sender_external_address1));
657   ASSERT_TRUE(nr_transport_addr_cmp(&sender_external_address0,
658                                     &sender_external_address1,
659                                     NR_TRANSPORT_ADDR_CMP_MODE_ALL))
660   << "addr1: " << sender_external_address0.as_string
661   << " addr2: " << sender_external_address1.as_string;
662 
663   // Verify that return traffic works
664   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1], private_addrs_[0],
665                                    sender_external_address1));
666 
667   // Verify that other public IP can use the original pinhole
668   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0], private_addrs_[0],
669                                    sender_external_address1));
670 }
671 
TEST_F(TestNrSocketTest,Symmetric)672 TEST_F(TestNrSocketTest, Symmetric) {
673   RefPtr<TestNat> nat(CreatePrivateAddrs(1));
674   nat->filtering_type_ = TestNat::PORT_DEPENDENT;
675   nat->mapping_type_ = TestNat::PORT_DEPENDENT;
676   CreatePublicAddrs(2);
677 
678   nr_transport_addr sender_external_address;
679   // Open pinhole to public IP 0
680   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[0],
681                                 &sender_external_address));
682 
683   // Verify that return traffic works
684   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0], private_addrs_[0],
685                                    sender_external_address));
686 
687   // Verify that other public IP cannot use the pinhole
688   ASSERT_FALSE(CheckConnectivityVia(public_addrs_[1], private_addrs_[0],
689                                     sender_external_address));
690 
691   // Send traffic to other public IP, verify that it uses a new pinhole
692   nr_transport_addr sender_external_address2;
693   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[1],
694                                 &sender_external_address2));
695   ASSERT_TRUE(nr_transport_addr_cmp(&sender_external_address,
696                                     &sender_external_address2,
697                                     NR_TRANSPORT_ADDR_CMP_MODE_ALL));
698 
699   // Verify that the other public IP can use the new pinhole
700   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1], private_addrs_[0],
701                                    sender_external_address2));
702 }
703 
TEST_F(TestNrSocketTest,BlockUdp)704 TEST_F(TestNrSocketTest, BlockUdp) {
705   RefPtr<TestNat> nat(CreatePrivateAddrs(2));
706   nat->block_udp_ = true;
707   CreatePublicAddrs(1);
708 
709   nr_transport_addr sender_external_address;
710   ASSERT_FALSE(CheckConnectivity(private_addrs_[0], public_addrs_[0],
711                                  &sender_external_address));
712 
713   // Make sure UDP behind the NAT still works
714   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], private_addrs_[1]));
715   ASSERT_TRUE(CheckConnectivity(private_addrs_[1], private_addrs_[0]));
716 }
717 
TEST_F(TestNrSocketTest,DenyHairpinning)718 TEST_F(TestNrSocketTest, DenyHairpinning) {
719   RefPtr<TestNat> nat(CreatePrivateAddrs(2));
720   nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
721   nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
722   CreatePublicAddrs(1);
723 
724   nr_transport_addr sender_external_address;
725   // Open pinhole to public IP 0
726   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[0],
727                                 &sender_external_address));
728 
729   // Verify that hairpinning is disallowed
730   ASSERT_FALSE(CheckConnectivityVia(private_addrs_[1], private_addrs_[0],
731                                     sender_external_address));
732 }
733 
TEST_F(TestNrSocketTest,AllowHairpinning)734 TEST_F(TestNrSocketTest, AllowHairpinning) {
735   RefPtr<TestNat> nat(CreatePrivateAddrs(2));
736   nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
737   nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
738   nat->mapping_timeout_ = 30000;
739   nat->allow_hairpinning_ = true;
740   CreatePublicAddrs(1);
741 
742   nr_transport_addr sender_external_address;
743   // Open pinhole to public IP 0, obtain external address
744   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[0],
745                                 &sender_external_address));
746 
747   // Verify that hairpinning is allowed
748   ASSERT_TRUE(CheckConnectivityVia(private_addrs_[1], private_addrs_[0],
749                                    sender_external_address));
750 }
751 
TEST_F(TestNrSocketTest,FullConeTimeout)752 TEST_F(TestNrSocketTest, FullConeTimeout) {
753   RefPtr<TestNat> nat(CreatePrivateAddrs(1));
754   nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
755   nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
756   nat->mapping_timeout_ = 200;
757   CreatePublicAddrs(2);
758 
759   nr_transport_addr sender_external_address;
760   // Open pinhole to public IP 0
761   ASSERT_TRUE(CheckConnectivity(private_addrs_[0], public_addrs_[0],
762                                 &sender_external_address));
763 
764   // Verify that return traffic works
765   ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0], private_addrs_[0],
766                                    sender_external_address));
767 
768   PR_Sleep(201);
769 
770   // Verify that return traffic does not work
771   ASSERT_FALSE(CheckConnectivityVia(public_addrs_[0], private_addrs_[0],
772                                     sender_external_address));
773 }
774 
TEST_F(TestNrSocketTest,PublicConnectivityTcp)775 TEST_F(TestNrSocketTest, PublicConnectivityTcp) {
776   CreatePublicAddrs(2, "127.0.0.1", IPPROTO_TCP);
777 
778   ASSERT_TRUE(CheckTcpConnectivity(public_addrs_[0], public_addrs_[1]));
779 }
780 
TEST_F(TestNrSocketTest,PrivateConnectivityTcp)781 TEST_F(TestNrSocketTest, PrivateConnectivityTcp) {
782   RefPtr<TestNat> nat(CreatePrivateAddrs(2, "127.0.0.1", IPPROTO_TCP));
783   nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
784   nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
785 
786   ASSERT_TRUE(CheckTcpConnectivity(private_addrs_[0], private_addrs_[1]));
787 }
788 
TEST_F(TestNrSocketTest,PrivateToPublicConnectivityTcp)789 TEST_F(TestNrSocketTest, PrivateToPublicConnectivityTcp) {
790   RefPtr<TestNat> nat(CreatePrivateAddrs(1, "127.0.0.1", IPPROTO_TCP));
791   nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
792   nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
793   CreatePublicAddrs(1, "127.0.0.1", IPPROTO_TCP);
794 
795   ASSERT_TRUE(CheckTcpConnectivity(private_addrs_[0], public_addrs_[0]));
796 }
797 
TEST_F(TestNrSocketTest,NoConnectivityBetweenSubnetsTcp)798 TEST_F(TestNrSocketTest, NoConnectivityBetweenSubnetsTcp) {
799   RefPtr<TestNat> nat1(CreatePrivateAddrs(1, "127.0.0.1", IPPROTO_TCP));
800   nat1->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
801   nat1->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
802   RefPtr<TestNat> nat2(CreatePrivateAddrs(1, "127.0.0.1", IPPROTO_TCP));
803   nat2->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
804   nat2->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
805 
806   ASSERT_FALSE(CheckTcpConnectivity(private_addrs_[0], private_addrs_[1]));
807 }
808 
TEST_F(TestNrSocketTest,NoConnectivityPublicToPrivateTcp)809 TEST_F(TestNrSocketTest, NoConnectivityPublicToPrivateTcp) {
810   RefPtr<TestNat> nat(CreatePrivateAddrs(1, "127.0.0.1", IPPROTO_TCP));
811   nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
812   nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
813   CreatePublicAddrs(1, "127.0.0.1", IPPROTO_TCP);
814 
815   ASSERT_FALSE(CheckTcpConnectivity(public_addrs_[0], private_addrs_[0]));
816 }
817