1 // Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
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
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7 #include <config.h>
8
9 #include <asiolink/io_address.h>
10 #include <dhcp/dhcp4.h>
11 #include <dhcp/iface_mgr.h>
12 #include <dhcp/option.h>
13 #include <dhcp/pkt6.h>
14 #include <dhcp/pkt_filter.h>
15 #include <dhcp/tests/iface_mgr_test_config.h>
16 #include <dhcp/tests/pkt_filter6_test_utils.h>
17 #include <dhcp/tests/packet_queue_testutils.h>
18 #include <testutils/gtest_utils.h>
19
20 #include <boost/foreach.hpp>
21 #include <boost/scoped_ptr.hpp>
22 #include <gtest/gtest.h>
23
24 #include <fcntl.h>
25 #include <fstream>
26 #include <functional>
27 #include <iostream>
28 #include <sstream>
29
30 #include <arpa/inet.h>
31 #include <unistd.h>
32
33 using namespace std;
34 using namespace isc;
35 using namespace isc::asiolink;
36 using namespace isc::dhcp;
37 using namespace isc::dhcp::test;
38 using boost::scoped_ptr;
39 namespace ph = std::placeholders;
40
41 namespace {
42
43 // Note this is for the *real* loopback interface, *not* the fake one.
44 // So in tests using it you have LOOPBACK_NAME, LOOPBACK_INDEX and
45 // no "eth0" nor "eth1". In tests not using it you can have "lo", LO_INDEX,
46 // "eth0" or "eth1".
47 // Name of loopback interface detection.
48 const size_t BUF_SIZE = 32;
49 // Can be overwritten to "lo0" for instance on BSD systems.
50 char LOOPBACK_NAME[BUF_SIZE] = "lo";
51 // In fact is never 0, 1 is by far the most likely.
52 uint32_t LOOPBACK_INDEX = 0;
53
54 // Ports used during testing
55 const uint16_t PORT1 = 10547; // V6 socket
56 const uint16_t PORT2 = 10548; // V4 socket
57
58 // On some systems measured duration of receive6() and receive4() appears to be
59 // shorter than select() timeout. This may be the case if different time
60 // resolutions are used by these functions. For such cases we set the
61 // tolerance to 0.01s.
62 const uint32_t TIMEOUT_TOLERANCE = 10000;
63
64 // Macro for making select wait time arguments for receive functions
65 #define RECEIVE_WAIT_MS(m) 0,(m*1000)
66
67 /// This test verifies that the socket read buffer can be used to
68 /// receive the data and that the data can be read from it.
TEST(IfaceTest,readBuffer)69 TEST(IfaceTest, readBuffer) {
70 // Create fake interface object.
71 Iface iface("em0", 0);
72 // The size of read buffer should initially be 0 and the returned
73 // pointer should be NULL.
74 ASSERT_EQ(0, iface.getReadBufferSize());
75 EXPECT_EQ(NULL, iface.getReadBuffer());
76
77 // Let's resize the buffer.
78 iface.resizeReadBuffer(256);
79 // Check that the buffer has expected size.
80 ASSERT_EQ(256, iface.getReadBufferSize());
81 // The returned pointer should now be non-NULL.
82 uint8_t* buf_ptr = iface.getReadBuffer();
83 ASSERT_FALSE(buf_ptr == NULL);
84
85 // Use the pointer to set some data.
86 for (size_t i = 0; i < iface.getReadBufferSize(); ++i) {
87 buf_ptr[i] = i;
88 }
89
90 // Get the pointer again and validate the data.
91 buf_ptr = iface.getReadBuffer();
92 ASSERT_EQ(256, iface.getReadBufferSize());
93 for (size_t i = 0; i < iface.getReadBufferSize(); ++i) {
94 // Use assert so as it fails on the first failure, no need
95 // to continue further checks.
96 ASSERT_EQ(i, buf_ptr[i]);
97 }
98 }
99
100 // Check that counting the number of active addresses on the interface
101 // works as expected.
TEST(IfaceTest,countActive4)102 TEST(IfaceTest, countActive4) {
103 Iface iface("eth0", 0);
104 ASSERT_EQ(0, iface.countActive4());
105
106 iface.addAddress(IOAddress("192.168.0.2"));
107 ASSERT_EQ(1, iface.countActive4());
108
109 iface.addAddress(IOAddress("2001:db8:1::1"));
110 ASSERT_EQ(1, iface.countActive4());
111
112 iface.addAddress(IOAddress("192.168.0.3"));
113 ASSERT_EQ(2, iface.countActive4());
114
115 ASSERT_NO_THROW(iface.setActive(IOAddress("192.168.0.2"), false));
116 ASSERT_EQ(1, iface.countActive4());
117
118 ASSERT_NO_THROW(iface.setActive(IOAddress("192.168.0.3"), false));
119 ASSERT_EQ(0, iface.countActive4());
120 }
121
122 /// Mock object implementing PktFilter class. It is used by
123 /// IfaceMgrTest::setPacketFilter to verify that IfaceMgr::setPacketFilter
124 /// sets this object as a handler for opening sockets. This dummy
125 /// class simply records that openSocket function was called by
126 /// the IfaceMgr as expected.
127 ///
128 /// @todo This class currently doesn't verify that send/receive functions
129 /// were called. In order to test it, there is a need to supply dummy
130 /// function performing select() on certain sockets. The system select()
131 /// call will fail when dummy socket descriptor is provided and thus
132 /// TestPktFilter::receive will never be called. The appropriate extension
133 /// to IfaceMgr is planned along with implementation of other "Packet
134 /// Filters" such as these supporting Linux Packet Filtering and
135 /// Berkeley Packet Filtering.
136 class TestPktFilter : public PktFilter {
137 public:
138
139 /// Constructor
TestPktFilter()140 TestPktFilter()
141 : open_socket_called_(false) {
142 }
143
isDirectResponseSupported() const144 virtual bool isDirectResponseSupported() const {
145 return (false);
146 }
147
148 /// @brief Pretend to open a socket.
149 ///
150 /// This function doesn't open a real socket. It always returns the
151 /// same fake socket descriptor. It also records the fact that it has
152 /// been called in the public open_socket_called_ member.
153 /// As in the case of opening a real socket, this function will check
154 /// if there is another fake socket "bound" to the same address and port.
155 /// If there is, it will throw an exception. This allows to simulate the
156 /// conditions when one of the sockets can't be open because there is
157 /// a socket already open and test how IfaceMgr will handle it.
158 ///
159 /// @param iface An interface on which the socket is to be opened.
160 /// @param addr An address to which the socket is to be bound.
161 /// @param port A port to which the socket is to be bound.
openSocket(Iface & iface,const isc::asiolink::IOAddress & addr,const uint16_t port,const bool join_multicast,const bool)162 virtual SocketInfo openSocket(Iface& iface,
163 const isc::asiolink::IOAddress& addr,
164 const uint16_t port,
165 const bool join_multicast,
166 const bool) {
167 // Check if there is any other socket bound to the specified address
168 // and port on this interface.
169 const Iface::SocketCollection& sockets = iface.getSockets();
170 for (Iface::SocketCollection::const_iterator socket = sockets.begin();
171 socket != sockets.end(); ++socket) {
172 if (((socket->addr_ == addr) ||
173 ((socket->addr_ == IOAddress("::")) && join_multicast)) &&
174 socket->port_ == port) {
175 isc_throw(SocketConfigError, "test socket bind error");
176 }
177 }
178 open_socket_called_ = true;
179 return (SocketInfo(addr, port, 255));
180 }
181
182 /// Does nothing
receive(Iface &,const SocketInfo &)183 virtual Pkt4Ptr receive(Iface&, const SocketInfo&) {
184 return (Pkt4Ptr());
185 }
186
187 /// Does nothing
send(const Iface &,uint16_t,const Pkt4Ptr &)188 virtual int send(const Iface&, uint16_t, const Pkt4Ptr&) {
189 return (0);
190 }
191
192 /// Holds the information whether openSocket was called on this
193 /// object after its creation.
194 bool open_socket_called_;
195 };
196
197 class NakedIfaceMgr: public IfaceMgr {
198 // "Naked" Interface Manager, exposes internal fields
199 public:
200
201 /// @brief Constructor.
NakedIfaceMgr()202 NakedIfaceMgr() {
203 loDetect();
204 }
205
206 /// @brief detects name of the loopback interface
207 ///
208 /// This method detects name of the loopback interface.
loDetect()209 static void loDetect() {
210 // Poor man's interface detection. It will go away as soon as proper
211 // interface detection is implemented
212 if (if_nametoindex("lo") > 0) {
213 snprintf(LOOPBACK_NAME, BUF_SIZE - 1, "lo");
214 } else if (if_nametoindex("lo0") > 0) {
215 snprintf(LOOPBACK_NAME, BUF_SIZE - 1, "lo0");
216 } else {
217 cout << "Failed to detect loopback interface. Neither "
218 << "lo nor lo0 worked. I give up." << endl;
219 FAIL();
220 }
221 LOOPBACK_INDEX = if_nametoindex(LOOPBACK_NAME);
222 }
223
224 /// @brief Returns the collection of existing interfaces.
getIfacesLst()225 IfaceCollection& getIfacesLst() { return (ifaces_); }
226
227 /// @brief This function creates fictitious interfaces with fictitious
228 /// addresses.
229 ///
230 /// These interfaces can be used in tests that don't actually try
231 /// to open the sockets on these interfaces. Some tests use mock
232 /// objects to mimic sockets being open. These interfaces are
233 /// suitable for such tests.
createIfaces()234 void createIfaces() {
235
236 ifaces_.clear();
237
238 // local loopback
239 IfacePtr lo = createIface("lo", LO_INDEX);
240 lo->addAddress(IOAddress("127.0.0.1"));
241 lo->addAddress(IOAddress("::1"));
242 ifaces_.push_back(lo);
243 // eth0
244 IfacePtr eth0 = createIface("eth0", ETH0_INDEX);
245 eth0->addAddress(IOAddress("10.0.0.1"));
246 eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
247 eth0->addAddress(IOAddress("2001:db8:1::1"));
248 ifaces_.push_back(eth0);
249 // eth1
250 IfacePtr eth1 = createIface("eth1", ETH1_INDEX);
251 eth1->addAddress(IOAddress("192.0.2.3"));
252 eth1->addAddress(IOAddress("fe80::3a60:77ff:fed5:abcd"));
253 ifaces_.push_back(eth1);
254 }
255
256 /// @brief Create an object representing interface.
257 ///
258 /// Apart from creating an interface, this function also sets the
259 /// interface flags:
260 /// - loopback flag if interface name is "lo"
261 /// - up always true
262 /// - running always true
263 /// - inactive always to false
264 /// - multicast always to true
265 /// - broadcast always to false
266 ///
267 /// If one needs to modify the default flag settings, the setIfaceFlags
268 /// function should be used.
269 ///
270 /// @param name A name of the interface to be created.
271 /// @param ifindex An index of the interface to be created.
272 ///
273 /// @return An object representing interface.
createIface(const std::string & name,const int ifindex)274 static IfacePtr createIface(const std::string& name, const int ifindex) {
275 IfacePtr iface(new Iface(name, ifindex));
276 if (name == "lo") {
277 iface->flag_loopback_ = true;
278 // Don't open sockets on loopback interface.
279 iface->inactive4_ = true;
280 iface->inactive6_ = true;
281 } else {
282 iface->inactive4_ = false;
283 iface->inactive6_ = false;
284 }
285 iface->flag_multicast_ = true;
286 // On BSD systems, the SO_BINDTODEVICE option is not supported.
287 // Therefore the IfaceMgr will throw an exception on attempt to
288 // open sockets on more than one broadcast-capable interface at
289 // the same time. In order to prevent this error, we mark all
290 // interfaces broadcast-incapable for unit testing.
291 iface->flag_broadcast_ = false;
292 iface->flag_up_ = true;
293 iface->flag_running_ = true;
294 return (iface);
295 }
296
297 /// @brief Checks if the specified interface has a socket bound to a
298 /// specified address.
299 ///
300 /// @param iface_name A name of the interface.
301 /// @param addr An address to be checked for binding.
302 ///
303 /// @return true if there is a socket bound to the specified address.
isBound(const std::string & iface_name,const std::string & addr)304 bool isBound(const std::string& iface_name, const std::string& addr) {
305 IfacePtr iface = getIface(iface_name);
306 if (!iface) {
307 ADD_FAILURE() << "the interface " << iface_name << " doesn't exist";
308 return (false);
309 }
310 const Iface::SocketCollection& sockets = iface->getSockets();
311 for (Iface::SocketCollection::const_iterator sock = sockets.begin();
312 sock != sockets.end(); ++sock) {
313 if (sock->addr_ == IOAddress(addr)) {
314 return (true);
315
316 } else if ((sock->addr_ == IOAddress("::")) &&
317 (IOAddress(addr).isV6LinkLocal())) {
318 BOOST_FOREACH(Iface::Address a, iface->getAddresses()) {
319 if (a.get() == IOAddress(addr)) {
320 return (true);
321 }
322 }
323 }
324 }
325 return (false);
326 }
327
328 /// @brief Modify flags on the interface.
329 ///
330 /// @param name A name of the interface.
331 /// @param loopback A new value of the loopback flag.
332 /// @param up A new value of the up flag.
333 /// @param running A new value of the running flag.
334 /// @param inactive A new value of the inactive flag.
setIfaceFlags(const std::string & name,const bool loopback,const bool up,const bool running,const bool inactive4,const bool inactive6)335 void setIfaceFlags(const std::string& name, const bool loopback,
336 const bool up, const bool running,
337 const bool inactive4,
338 const bool inactive6) {
339 for (IfacePtr iface : ifaces_) {
340 if (iface->getName() == name) {
341 iface->flag_loopback_ = loopback;
342 iface->flag_up_ = up;
343 iface->flag_running_ = running;
344 iface->inactive4_ = inactive4;
345 iface->inactive6_ = inactive6;
346 }
347 }
348 }
349 };
350
351 /// @brief A test fixture class for IfaceMgr.
352 ///
353 /// @todo Sockets being opened by IfaceMgr tests should be managed by
354 /// the test fixture. In particular, the class should close sockets after
355 /// each test. Current approach where test cases are responsible for
356 /// closing sockets is resource leak prone, especially in case of the
357 /// test failure path.
358 class IfaceMgrTest : public ::testing::Test {
359 public:
360 /// @brief Constructor.
IfaceMgrTest()361 IfaceMgrTest()
362 : errors_count_(0) {
363 }
364
~IfaceMgrTest()365 ~IfaceMgrTest() {
366 }
367
368 /// @brief Tests the number of IPv6 sockets on interface
369 ///
370 /// This function checks the expected number of open IPv6 sockets on the
371 /// specified interface. On non-Linux systems, sockets are bound to a
372 /// link-local address and the number of unicast addresses specified.
373 /// On Linux systems, there is one more socket bound to a ff02::1:2
374 /// multicast address.
375 ///
376 /// @param iface An interface on which sockets are open.
377 /// @param unicast_num A number of unicast addresses bound.
378 /// @param link_local_num A number of link local addresses bound.
checkSocketsCount6(const Iface & iface,const int unicast_num,const int link_local_num=1)379 void checkSocketsCount6(const Iface& iface, const int unicast_num,
380 const int link_local_num = 1) {
381 // On local-loopback interface, there should be no sockets.
382 if (iface.flag_loopback_) {
383 ASSERT_TRUE(iface.getSockets().empty())
384 << "expected empty socket set on loopback interface "
385 << iface.getName();
386 return;
387 }
388 #if defined OS_LINUX
389 // On Linux, for each link-local address there may be an
390 // additional socket opened and bound to ff02::1:2. This socket
391 // is only opened if the interface is multicast-capable.
392 ASSERT_EQ(unicast_num + (iface.flag_multicast_ ? link_local_num : 0)
393 + link_local_num, iface.getSockets().size())
394 << "invalid number of sockets on interface "
395 << iface.getName();
396 #else
397 // On non-Linux, there is no additional socket.
398 ASSERT_EQ(unicast_num + link_local_num, iface.getSockets().size())
399 << "invalid number of sockets on interface "
400 << iface.getName();
401
402 #endif
403 }
404
405 // Get the number of IPv4 or IPv6 sockets on the loopback interface
getOpenSocketsCount(const Iface & iface,uint16_t family) const406 int getOpenSocketsCount(const Iface& iface, uint16_t family) const {
407 // Get all sockets.
408 Iface::SocketCollection sockets = iface.getSockets();
409
410 // Loop through sockets and try to find the ones which match the
411 // specified type.
412 int sockets_count = 0;
413 for (Iface::SocketCollection::const_iterator sock = sockets.begin();
414 sock != sockets.end(); ++sock) {
415 // Match found, increase the counter.
416 if (sock->family_ == family) {
417 ++sockets_count;
418 }
419 }
420 return (sockets_count);
421 }
422
423 /// @brief returns socket bound to a specific address (or NULL)
424 ///
425 /// A helper function, used to pick a socketinfo that is bound to a given
426 /// address.
427 ///
428 /// @param sockets sockets collection
429 /// @param addr address the socket is bound to
430 ///
431 /// @return socket info structure (or NULL)
432 const isc::dhcp::SocketInfo*
getSocketByAddr(const isc::dhcp::Iface::SocketCollection & sockets,const IOAddress & addr)433 getSocketByAddr(const isc::dhcp::Iface::SocketCollection& sockets,
434 const IOAddress& addr) {
435 for (isc::dhcp::Iface::SocketCollection::const_iterator s =
436 sockets.begin(); s != sockets.end(); ++s) {
437 if (s->addr_ == addr) {
438 return (&(*s));
439 }
440 }
441 return (NULL);
442 }
443
444 /// @brief Implements an IfaceMgr error handler.
445 ///
446 /// This function can be installed as an error handler for the
447 /// IfaceMgr::openSockets4 function. The error handler is invoked
448 /// when an attempt to open a particular socket fails for any reason.
449 /// Typically, the error handler will log a warning. When the error
450 /// handler returns, the openSockets4 function should continue opening
451 /// sockets on other interfaces.
452 ///
453 /// @param errmsg An error string indicating the reason for failure.
ifaceMgrErrorHandler(const std::string &)454 void ifaceMgrErrorHandler(const std::string&) {
455 // Increase the counter of invocations to this function. By checking
456 // this number, a test may check if the expected number of errors
457 // has occurred.
458 ++errors_count_;
459 }
460
461 /// @brief Tests the ability to send and receive DHCPv6 packets
462 ///
463 /// This test calls @r IfaceMgr::configureDHCPPacketQueue, passing in the
464 /// given queue configuration. It then calls IfaceMgr::startDHCPReceiver
465 /// and verifies whether or not the receive thread has been started as
466 /// expected. Next it creates a generic DHCPv6 packet and sends it over
467 /// the loop back interface. It invokes IfaceMgr::receive6 to receive the
468 /// packet sent, and compares to the packets for equality.
469 ///
470 /// @param dhcp_queue_control dhcp-queue-control contents to use for the test
471 /// @param exp_queue_enabled flag that indicates if packet queuing is expected
472 /// to be enabled.
sendReceive6Test(data::ConstElementPtr dhcp_queue_control,bool exp_queue_enabled)473 void sendReceive6Test(data::ConstElementPtr dhcp_queue_control, bool exp_queue_enabled) {
474 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
475
476 // Testing socket operation in a portable way is tricky
477 // without interface detection implemented
478 // let's assume that every supported OS have lo interface
479 IOAddress lo_addr("::1");
480 int socket1 = 0, socket2 = 0;
481 EXPECT_NO_THROW(
482 socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10547);
483 socket2 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10546);
484 );
485
486 EXPECT_GE(socket1, 0);
487 EXPECT_GE(socket2, 0);
488
489 // Configure packet queueing as desired.
490 bool queue_enabled = false;
491 ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, dhcp_queue_control));
492
493 // Verify that we have a queue only if we expected one.
494 ASSERT_EQ(exp_queue_enabled, queue_enabled);
495
496 // Thread should only start when there is a packet queue.
497 ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET6));
498 ASSERT_TRUE(queue_enabled == ifacemgr->isDHCPReceiverRunning());
499
500 // If the thread is already running, trying to start it again should fail.
501 if (queue_enabled) {
502 ASSERT_THROW(ifacemgr->startDHCPReceiver(AF_INET6), InvalidOperation);
503 // Should still have one running.
504 ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
505 }
506
507 // Let's build our DHCPv6 packet.
508 // prepare dummy payload
509 uint8_t data[128];
510 for (uint8_t i = 0; i < 128; i++) {
511 data[i] = i;
512 }
513
514 Pkt6Ptr sendPkt = Pkt6Ptr(new Pkt6(data, 128));
515 sendPkt->repack();
516 sendPkt->setRemotePort(10547);
517 sendPkt->setRemoteAddr(IOAddress("::1"));
518 sendPkt->setIndex(LOOPBACK_INDEX);
519 sendPkt->setIface(LOOPBACK_NAME);
520
521 // Send the packet.
522 EXPECT_EQ(true, ifacemgr->send(sendPkt));
523
524 // Now, let's try and receive it.
525 Pkt6Ptr rcvPkt;
526 rcvPkt = ifacemgr->receive6(10);
527 ASSERT_TRUE(rcvPkt); // received our own packet
528
529 // let's check that we received what was sent
530 ASSERT_EQ(sendPkt->data_.size(), rcvPkt->data_.size());
531 EXPECT_EQ(0, memcmp(&sendPkt->data_[0], &rcvPkt->data_[0],
532 rcvPkt->data_.size()));
533
534 EXPECT_EQ(sendPkt->getRemoteAddr(), rcvPkt->getRemoteAddr());
535
536 // since we opened 2 sockets on the same interface and none of them is multicast,
537 // none is preferred over the other for sending data, so we really should not
538 // assume the one or the other will always be chosen for sending data. Therefore
539 // we should accept both values as source ports.
540 EXPECT_TRUE((rcvPkt->getRemotePort() == 10546) || (rcvPkt->getRemotePort() == 10547));
541
542 // Stop the thread. This should be no harm/no foul if we're not
543 // queueuing. Either way, we should not have a thread afterwards.
544 ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
545 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
546 }
547
548 /// @brief Tests the ability to send and receive DHCPv4 packets
549 ///
550 /// This test calls @r IfaceMgr::configureDHCPPacketQueue, passing in the
551 /// given queue configuration. It then calls IfaceMgr::startDHCPReceiver
552 /// and verifies whether or not the receive thread has been started as
553 /// expected. Next it creates a DISCOVER packet and sends it over
554 /// the loop back interface. It invokes IfaceMgr::receive4 to receive the
555 /// packet sent, and compares to the packets for equality.
556 ///
557 /// @param dhcp_queue_control dhcp-queue-control contents to use for the test
558 /// @param exp_queue_enabled flag that indicates if packet queuing is expected
559 /// to be enabled.
sendReceive4Test(data::ConstElementPtr dhcp_queue_control,bool exp_queue_enabled)560 void sendReceive4Test(data::ConstElementPtr dhcp_queue_control, bool exp_queue_enabled) {
561 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
562
563 // Testing socket operation in a portable way is tricky
564 // without interface detection implemented.
565 // Let's assume that every supported OS has lo interface
566 IOAddress lo_addr("127.0.0.1");
567 int socket1 = 0;
568 EXPECT_NO_THROW(
569 socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr,
570 DHCP4_SERVER_PORT + 10000);
571 );
572
573 EXPECT_GE(socket1, 0);
574
575 // Configure packet queueing as desired.
576 bool queue_enabled = false;
577 ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, dhcp_queue_control));
578
579 // Verify that we have a queue only if we expected one.
580 ASSERT_EQ(exp_queue_enabled, queue_enabled);
581
582 // Thread should only start when there is a packet queue.
583 ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));
584 ASSERT_TRUE(queue_enabled == ifacemgr->isDHCPReceiverRunning());
585
586 // If the thread is already running, trying to start it again should fail.
587 if (queue_enabled) {
588 ASSERT_THROW(ifacemgr->startDHCPReceiver(AF_INET), InvalidOperation);
589 // Should still have one running.
590 ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
591 }
592
593 // Let's construct the packet to send.
594 boost::shared_ptr<Pkt4> sendPkt(new Pkt4(DHCPDISCOVER, 1234) );
595 sendPkt->setLocalAddr(IOAddress("127.0.0.1"));
596 sendPkt->setLocalPort(DHCP4_SERVER_PORT + 10000 + 1);
597 sendPkt->setRemotePort(DHCP4_SERVER_PORT + 10000);
598 sendPkt->setRemoteAddr(IOAddress("127.0.0.1"));
599 sendPkt->setIndex(LOOPBACK_INDEX);
600 sendPkt->setIface(string(LOOPBACK_NAME));
601 sendPkt->setHops(6);
602 sendPkt->setSecs(42);
603 sendPkt->setCiaddr(IOAddress("192.0.2.1"));
604 sendPkt->setSiaddr(IOAddress("192.0.2.2"));
605 sendPkt->setYiaddr(IOAddress("192.0.2.3"));
606 sendPkt->setGiaddr(IOAddress("192.0.2.4"));
607
608 // Unpack() now checks if mandatory DHCP_MESSAGE_TYPE is present.
609 // Workarounds (creating DHCP Message Type Option by hand) are no longer
610 // needed as setDhcpType() is called in constructor.
611
612 uint8_t sname[] = "That's just a string that will act as SNAME";
613 sendPkt->setSname(sname, strlen((const char*)sname));
614 uint8_t file[] = "/another/string/that/acts/as/a/file_name.txt";
615 sendPkt->setFile(file, strlen((const char*)file));
616
617 ASSERT_NO_THROW(
618 sendPkt->pack();
619 );
620
621 // OK, Send the PACKET!
622 bool result = false;
623 EXPECT_NO_THROW(result = ifacemgr->send(sendPkt));
624 EXPECT_TRUE(result);
625
626 // Now let's try and receive it.
627 boost::shared_ptr<Pkt4> rcvPkt;
628 ASSERT_NO_THROW(rcvPkt = ifacemgr->receive4(10));
629 ASSERT_TRUE(rcvPkt); // received our own packet
630 ASSERT_NO_THROW(
631 rcvPkt->unpack();
632 );
633
634 // let's check that we received what was sent
635 EXPECT_EQ(sendPkt->len(), rcvPkt->len());
636 EXPECT_EQ("127.0.0.1", rcvPkt->getRemoteAddr().toText());
637 EXPECT_EQ(sendPkt->getRemotePort(), rcvPkt->getLocalPort());
638 EXPECT_EQ(sendPkt->getHops(), rcvPkt->getHops());
639 EXPECT_EQ(sendPkt->getOp(), rcvPkt->getOp());
640 EXPECT_EQ(sendPkt->getSecs(), rcvPkt->getSecs());
641 EXPECT_EQ(sendPkt->getFlags(), rcvPkt->getFlags());
642 EXPECT_EQ(sendPkt->getCiaddr(), rcvPkt->getCiaddr());
643 EXPECT_EQ(sendPkt->getSiaddr(), rcvPkt->getSiaddr());
644 EXPECT_EQ(sendPkt->getYiaddr(), rcvPkt->getYiaddr());
645 EXPECT_EQ(sendPkt->getGiaddr(), rcvPkt->getGiaddr());
646 EXPECT_EQ(sendPkt->getTransid(), rcvPkt->getTransid());
647 EXPECT_TRUE(sendPkt->getSname() == rcvPkt->getSname());
648 EXPECT_TRUE(sendPkt->getFile() == rcvPkt->getFile());
649 EXPECT_EQ(sendPkt->getHtype(), rcvPkt->getHtype());
650 EXPECT_EQ(sendPkt->getHlen(), rcvPkt->getHlen());
651
652 // since we opened 2 sockets on the same interface and none of them is multicast,
653 // none is preferred over the other for sending data, so we really should not
654 // assume the one or the other will always be chosen for sending data. We should
655 // skip checking source port of sent address.
656
657 // Close the socket. Further we will test if errors are reported
658 // properly on attempt to use closed socket.
659 close(socket1);
660
661 // @todo Closing the socket does NOT cause a read error out of the
662 // receiveDHCP<X>Packets() select. Apparently this is because the
663 // thread is already inside the select when the socket is closed,
664 // and (at least under Centos 7.5), this does not interrupt the
665 // select. For now, we'll only test this for direct receive.
666 if (!queue_enabled) {
667 EXPECT_THROW(ifacemgr->receive4(10), SocketReadError);
668 }
669
670 // Verify write fails.
671 EXPECT_THROW(ifacemgr->send(sendPkt), SocketWriteError);
672
673 // Stop the thread. This should be no harm/no foul if we're not
674 // queueuing. Either way, we should not have a thread afterwards.
675 ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
676 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
677 }
678
679 /// @brief Verifies that IfaceMgr DHCPv4 receive calls detect and
680 /// purge external sockets that have gone bad without affecting
681 /// affecting normal operations. It can be run with or without
682 /// packet queuing.
683 ///
684 /// @param use_queue determines if packet queuing is used or not.
purgeExternalSockets4Test(bool use_queue=false)685 void purgeExternalSockets4Test(bool use_queue = false) {
686 bool callback_ok = false;
687 bool callback2_ok = false;
688
689 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
690
691 if (use_queue) {
692 bool queue_enabled = false;
693 data::ConstElementPtr config = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500);
694 ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, config));
695 ASSERT_TRUE(queue_enabled);
696
697 // Thread should only start when there is a packet queue.
698 ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));
699 ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
700 }
701
702 // Create first pipe and register it as extra socket
703 int pipefd[2];
704 EXPECT_TRUE(pipe(pipefd) == 0);
705 EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0],
706 [&callback_ok, &pipefd](int fd) {
707 callback_ok = (pipefd[0] == fd);
708 }));
709
710
711 // Let's create a second pipe and register it as well
712 int secondpipe[2];
713 EXPECT_TRUE(pipe(secondpipe) == 0);
714 EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0],
715 [&callback2_ok, &secondpipe](int fd) {
716 callback2_ok = (secondpipe[0] == fd);
717 }));
718
719 // Verify a call with no data and normal external sockets works ok.
720 Pkt4Ptr pkt4;
721 ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(RECEIVE_WAIT_MS(10)));
722
723 // No callback invocations and no DHCPv4 pkt.
724 EXPECT_FALSE(callback_ok);
725 EXPECT_FALSE(callback2_ok);
726 EXPECT_FALSE(pkt4);
727
728 // Now close the first pipe. This should make it's external socket invalid.
729 close(pipefd[1]);
730 close(pipefd[0]);
731
732 // We call receive4() which should detect and remove the invalid socket.
733 try {
734 pkt4 = ifacemgr->receive4(RECEIVE_WAIT_MS(10));
735 ADD_FAILURE() << "receive4 should have failed";
736 } catch (const SocketReadError& ex) {
737 EXPECT_EQ(std::string("SELECT interrupted by one invalid sockets,"
738 " purged 1 socket descriptors"),
739 std::string(ex.what()));
740 } catch (const std::exception& ex) {
741 ADD_FAILURE() << "wrong exception thrown: " << ex.what();
742 }
743
744 // No callback invocations and no DHCPv4 pkt.
745 EXPECT_FALSE(callback_ok);
746 EXPECT_FALSE(callback2_ok);
747 EXPECT_FALSE(pkt4);
748
749 // Now check whether the second callback is still functional
750 EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));
751
752 // Call receive4 again, this should work.
753 ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(RECEIVE_WAIT_MS(10)));
754
755 // Should have callback2 data only.
756 EXPECT_FALSE(callback_ok);
757 EXPECT_TRUE(callback2_ok);
758 EXPECT_FALSE(pkt4);
759
760 // Stop the thread. This should be no harm/no foul if we're not
761 // queueuing. Either way, we should not have a thread afterwards.
762 ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
763 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
764 }
765
766 /// @brief Verifies that IfaceMgr DHCPv6 receive calls detect and
767 /// purge external sockets that have gone bad without affecting
768 /// affecting normal operations. It can be run with or without
769 /// packet queuing.
770 ///
771 /// @param use_queue determines if packet queuing is used or not.
purgeExternalSockets6Test(bool use_queue=false)772 void purgeExternalSockets6Test(bool use_queue = false) {
773 bool callback_ok = false;
774 bool callback2_ok = false;
775
776 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
777
778 if (use_queue) {
779 bool queue_enabled = false;
780 data::ConstElementPtr config = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500);
781 ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, config));
782 ASSERT_TRUE(queue_enabled);
783
784 // Thread should only start when there is a packet queue.
785 ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET6));
786 ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
787 }
788
789 // Create first pipe and register it as extra socket
790 int pipefd[2];
791 EXPECT_TRUE(pipe(pipefd) == 0);
792 EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0],
793 [&callback_ok, &pipefd](int fd) {
794 callback_ok = (pipefd[0] == fd);
795 }));
796
797
798 // Let's create a second pipe and register it as well
799 int secondpipe[2];
800 EXPECT_TRUE(pipe(secondpipe) == 0);
801 EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0],
802 [&callback2_ok, &secondpipe](int fd) {
803 callback2_ok = (secondpipe[0] == fd);
804 }));
805
806 // Verify a call with no data and normal external sockets works ok.
807 Pkt6Ptr pkt6;
808 ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(RECEIVE_WAIT_MS(10)));
809
810 // No callback invocations and no DHCPv6 pkt.
811 EXPECT_FALSE(callback_ok);
812 EXPECT_FALSE(callback2_ok);
813 EXPECT_FALSE(pkt6);
814
815 // Now close the first pipe. This should make it's external socket invalid.
816 close(pipefd[1]);
817 close(pipefd[0]);
818
819 // We call receive6() which should detect and remove the invalid socket.
820 try {
821 pkt6 = ifacemgr->receive6(RECEIVE_WAIT_MS(10));
822 ADD_FAILURE() << "receive6 should have failed";
823 } catch (const SocketReadError& ex) {
824 EXPECT_EQ(std::string("SELECT interrupted by one invalid sockets,"
825 " purged 1 socket descriptors"),
826 std::string(ex.what()));
827 } catch (const std::exception& ex) {
828 ADD_FAILURE() << "wrong exception thrown: " << ex.what();
829 }
830
831 // No callback invocations and no DHCPv6 pkt.
832 EXPECT_FALSE(callback_ok);
833 EXPECT_FALSE(callback2_ok);
834 EXPECT_FALSE(pkt6);
835
836 // Now check whether the second callback is still functional
837 EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));
838
839 // Call receive6 again, this should work.
840 ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(RECEIVE_WAIT_MS(10)));
841
842 // Should have callback2 data only.
843 EXPECT_FALSE(callback_ok);
844 EXPECT_TRUE(callback2_ok);
845 EXPECT_FALSE(pkt6);
846
847 // Stop the thread. This should be no harm/no foul if we're not
848 // queueuing. Either way, we should not have a thread afterwards.
849 ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
850 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
851 }
852
853 /// Holds the invocation counter for ifaceMgrErrorHandler.
854 int errors_count_;
855 };
856
857 // We need some known interface to work reliably. Loopback interface is named
858 // lo on Linux and lo0 on BSD boxes. We need to find out which is available.
859 // This is not a real test, but rather a workaround that will go away when
860 // interface detection is implemented on all OSes.
TEST_F(IfaceMgrTest,loDetect)861 TEST_F(IfaceMgrTest, loDetect) {
862 NakedIfaceMgr::loDetect();
863 }
864
865 // Uncomment this test to create packet writer. It will
866 // write incoming DHCPv6 packets as C arrays. That is useful
867 // for generating test sequences based on actual traffic
868 //
869 // TODO: this potentially should be moved to a separate tool
870 //
871
872 #if 0
873 TEST_F(IfaceMgrTest, dhcp6Sniffer) {
874 // Testing socket operation in a portable way is tricky
875 // without interface detection implemented
876
877 static_cast<void>(remove("interfaces.txt"));
878
879 ofstream interfaces("interfaces.txt", ios::ate);
880 interfaces << "eth0 fe80::21e:8cff:fe9b:7349";
881 interfaces.close();
882
883 boost::scoped_ptr<NakedIfaceMgr> ifacemgr = new NakedIfaceMgr();
884
885 Pkt6Ptr pkt;
886 int cnt = 0;
887 cout << "---8X-----------------------------------------" << endl;
888 while (true) {
889 pkt.reset(ifacemgr->receive());
890
891 cout << "// this code is autogenerated. Do NOT edit." << endl;
892 cout << "// Received " << pkt->data_len_ << " bytes packet:" << endl;
893 cout << "Pkt6 *capture" << cnt++ << "() {" << endl;
894 cout << " Pkt6* pkt;" << endl;
895 cout << " pkt = new Pkt6(" << pkt->data_len_ << ");" << endl;
896 cout << " pkt->remote_port_ = " << pkt-> remote_port_ << ";" << endl;
897 cout << " pkt->remote_addr_ = IOAddress(\""
898 << pkt->remote_addr_ << "\");" << endl;
899 cout << " pkt->local_port_ = " << pkt-> local_port_ << ";" << endl;
900 cout << " pkt->local_addr_ = IOAddress(\""
901 << pkt->local_addr_ << "\");" << endl;
902 cout << " pkt->ifindex_ = " << pkt->ifindex_ << ";" << endl;
903 cout << " pkt->iface_ = \"" << pkt->iface_ << "\";" << endl;
904
905 // TODO it is better to declare statically initialize the array
906 // and then memcpy it to packet.
907 for (int i=0; i< pkt->data_len_; i++) {
908 cout << " pkt->data_[" << i << "]="
909 << (int)(unsigned char)pkt->data_[i] << "; ";
910 if (!(i%4))
911 cout << endl;
912 }
913 cout << endl;
914 cout << " return (pkt);" << endl;
915 cout << "}" << endl << endl;
916
917 pkt.reset();
918 }
919 cout << "---8X-----------------------------------------" << endl;
920
921 // Never happens. Infinite loop is infinite
922 }
923 #endif
924
925 // This test verifies that creation of the IfaceMgr instance doesn't
926 // cause an exception.
TEST_F(IfaceMgrTest,instance)927 TEST_F(IfaceMgrTest, instance) {
928 EXPECT_NO_THROW(IfaceMgr::instance());
929 }
930
931 // Basic tests for Iface inner class.
TEST_F(IfaceMgrTest,ifaceClass)932 TEST_F(IfaceMgrTest, ifaceClass) {
933
934 IfacePtr iface(new Iface("eth5", 7));
935 EXPECT_STREQ("eth5/7", iface->getFullName().c_str());
936
937 EXPECT_THROW_MSG(iface.reset(new Iface("", 10)), BadValue,
938 "Interface name must not be empty");
939
940 EXPECT_NO_THROW(iface.reset(new Iface("big-index", 66666)));
941 EXPECT_EQ(66666, iface->getIndex());
942 }
943
944 // This test checks the getIface by packet method.
TEST_F(IfaceMgrTest,getIfaceByPkt)945 TEST_F(IfaceMgrTest, getIfaceByPkt) {
946 NakedIfaceMgr ifacemgr;
947 // Create a set of fake interfaces. At the same time, remove the actual
948 // interfaces that have been detected by the IfaceMgr.
949 ifacemgr.createIfaces();
950
951 // Try IPv4 packet by name.
952 Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 1234));
953 IfacePtr iface = ifacemgr.getIface(pkt4);
954 EXPECT_FALSE(iface);
955 pkt4->setIface("eth0");
956 iface = ifacemgr.getIface(pkt4);
957 EXPECT_TRUE(iface);
958 EXPECT_FALSE(pkt4->indexSet());
959
960 // Try IPv6 packet by index.
961 Pkt6Ptr pkt6(new Pkt6(DHCPV6_REPLY, 123456));
962 iface = ifacemgr.getIface(pkt6);
963 EXPECT_FALSE(iface);
964 ASSERT_TRUE(ifacemgr.getIface("eth0"));
965 pkt6->setIndex(ifacemgr.getIface("eth0")->getIndex() + 1);
966 iface = ifacemgr.getIface(pkt6);
967 ASSERT_TRUE(iface);
968 EXPECT_TRUE(pkt6->indexSet());
969
970 // Index has precedence when both name and index are available.
971 EXPECT_EQ("eth1", iface->getName());
972 pkt6->setIface("eth0");
973 iface = ifacemgr.getIface(pkt6);
974 ASSERT_TRUE(iface);
975 EXPECT_EQ("eth1", iface->getName());
976
977 // Not existing name fails.
978 pkt4->setIface("eth2");
979 iface = ifacemgr.getIface(pkt4);
980 EXPECT_FALSE(iface);
981
982 // Not existing index fails.
983 pkt6->setIndex(3);
984 iface = ifacemgr.getIface(pkt6);
985 ASSERT_FALSE(iface);
986
987 // Test that resetting the index is verifiable.
988 pkt4->resetIndex();
989 EXPECT_FALSE(pkt4->indexSet());
990 pkt6->resetIndex();
991 EXPECT_FALSE(pkt6->indexSet());
992
993 // Test that you can also reset the index via setIndex().
994 pkt4->setIndex(-1);
995 EXPECT_FALSE(pkt4->indexSet());
996 pkt6->setIndex(-1);
997 EXPECT_FALSE(pkt6->indexSet());
998 }
999
1000 // Test that the IPv4 address can be retrieved for the interface.
TEST_F(IfaceMgrTest,ifaceGetAddress)1001 TEST_F(IfaceMgrTest, ifaceGetAddress) {
1002 Iface iface("eth0", 0);
1003
1004 IOAddress addr("::1");
1005 // Initially, the Iface has no addresses assigned.
1006 EXPECT_FALSE(iface.getAddress4(addr));
1007 // Add some addresses with IPv4 address in the middle.
1008 iface.addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
1009 iface.addAddress(IOAddress("10.1.2.3"));
1010 iface.addAddress(IOAddress("2001:db8:1::2"));
1011 // The v4 address should be returned.
1012 EXPECT_TRUE(iface.getAddress4(addr));
1013 EXPECT_EQ("10.1.2.3", addr.toText());
1014 // Delete the IPv4 address and leave only two IPv6 addresses.
1015 ASSERT_NO_THROW(iface.delAddress(IOAddress("10.1.2.3")));
1016 // The IPv4 address should not be returned.
1017 EXPECT_FALSE(iface.getAddress4(addr));
1018 // Add a different IPv4 address at the end of the list.
1019 iface.addAddress(IOAddress("192.0.2.3"));
1020 // This new address should now be returned.
1021 EXPECT_TRUE(iface.getAddress4(addr));
1022 EXPECT_EQ("192.0.2.3", addr.toText());
1023 }
1024
1025 // This test checks if it is possible to check that the specific address is
1026 // assigned to the interface.
TEST_F(IfaceMgrTest,ifaceHasAddress)1027 TEST_F(IfaceMgrTest, ifaceHasAddress) {
1028 IfaceMgrTestConfig config(true);
1029
1030 IfacePtr iface = IfaceMgr::instance().getIface("eth0");
1031 ASSERT_TRUE(iface);
1032 EXPECT_TRUE(iface->hasAddress(IOAddress("10.0.0.1")));
1033 EXPECT_FALSE(iface->hasAddress(IOAddress("10.0.0.2")));
1034 EXPECT_TRUE(iface->hasAddress(IOAddress("fe80::3a60:77ff:fed5:cdef")));
1035 EXPECT_TRUE(iface->hasAddress(IOAddress("2001:db8:1::1")));
1036 EXPECT_FALSE(iface->hasAddress(IOAddress("2001:db8:1::2")));
1037 }
1038
1039 // This test checks it is not allowed to add duplicate interfaces.
TEST_F(IfaceMgrTest,addInterface)1040 TEST_F(IfaceMgrTest, addInterface) {
1041 IfaceMgrTestConfig config(true);
1042
1043 IfacePtr dup_name(new Iface("eth1", 123));
1044 EXPECT_THROW_MSG(IfaceMgr::instance().addInterface(dup_name), Unexpected,
1045 "Can't add eth1/123 when eth1/2 already exists.");
1046 IfacePtr dup_index(new Iface("eth2", 2));
1047 EXPECT_THROW_MSG(IfaceMgr::instance().addInterface(dup_index), Unexpected,
1048 "Can't add eth2/2 when eth1/2 already exists.");
1049
1050 IfacePtr eth2(new Iface("eth2", 3));
1051 EXPECT_NO_THROW(IfaceMgr::instance().addInterface(eth2));
1052 }
1053
1054 // TODO: Implement getPlainMac() test as soon as interface detection
1055 // is implemented.
TEST_F(IfaceMgrTest,getIface)1056 TEST_F(IfaceMgrTest, getIface) {
1057
1058 cout << "Interface checks. Please ignore socket binding errors." << endl;
1059 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
1060
1061 // Interface name, ifindex
1062 IfacePtr iface1(new Iface("lo1", 100));
1063 IfacePtr iface2(new Iface("eth9", 101));
1064 IfacePtr iface3(new Iface("en99", 102));
1065 IfacePtr iface4(new Iface("e1000g4", 103));
1066 cout << "This test assumes that there are less than 100 network interfaces"
1067 << " in the tested system and there are no lo1, eth9, en99, e1000g4"
1068 << " or wifi15 interfaces present." << endl;
1069
1070 // Note: real interfaces may be detected as well
1071 ifacemgr->getIfacesLst().push_back(iface1);
1072 ifacemgr->getIfacesLst().push_back(iface2);
1073 ifacemgr->getIfacesLst().push_back(iface3);
1074 ifacemgr->getIfacesLst().push_back(iface4);
1075
1076 cout << "There are " << ifacemgr->getIfacesLst().size()
1077 << " interfaces." << endl;
1078 for (IfacePtr iface : ifacemgr->getIfacesLst()) {
1079 cout << " " << iface->getFullName() << endl;
1080 }
1081
1082 // Check that interface can be retrieved by ifindex
1083 IfacePtr tmp = ifacemgr->getIface(102);
1084 ASSERT_TRUE(tmp);
1085
1086 EXPECT_EQ("en99", tmp->getName());
1087 EXPECT_EQ(102, tmp->getIndex());
1088
1089 // Check that interface can be retrieved by name
1090 tmp = ifacemgr->getIface("lo1");
1091 ASSERT_TRUE(tmp);
1092
1093 EXPECT_EQ("lo1", tmp->getName());
1094 EXPECT_EQ(100, tmp->getIndex());
1095
1096 // Check that non-existing interfaces are not returned
1097 EXPECT_FALSE(ifacemgr->getIface("wifi15") );
1098 }
1099
TEST_F(IfaceMgrTest,clearIfaces)1100 TEST_F(IfaceMgrTest, clearIfaces) {
1101 NakedIfaceMgr ifacemgr;
1102 // Create a set of fake interfaces. At the same time, remove the actual
1103 // interfaces that have been detected by the IfaceMgr.
1104 ifacemgr.createIfaces();
1105
1106 ASSERT_GT(ifacemgr.countIfaces(), 0);
1107
1108 boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
1109 ASSERT_TRUE(custom_packet_filter);
1110 ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));
1111
1112 ASSERT_NO_THROW(ifacemgr.openSockets4());
1113
1114 ifacemgr.clearIfaces();
1115
1116 EXPECT_EQ(0, ifacemgr.countIfaces());
1117 }
1118
1119 // Verify that we have the expected default DHCPv4 packet queue.
TEST_F(IfaceMgrTest,packetQueue4)1120 TEST_F(IfaceMgrTest, packetQueue4) {
1121 NakedIfaceMgr ifacemgr;
1122
1123 // Should not have a queue at start up.
1124 ASSERT_FALSE(ifacemgr.getPacketQueue4());
1125
1126 // Verify that we can create a queue with default factory.
1127 data::ConstElementPtr config = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 2000);
1128 ASSERT_NO_THROW(ifacemgr.getPacketQueueMgr4()->createPacketQueue(config));
1129 CHECK_QUEUE_INFO(ifacemgr.getPacketQueue4(), "{ \"capacity\": 2000, \"queue-type\": \""
1130 << PacketQueueMgr4::DEFAULT_QUEUE_TYPE4 << "\", \"size\": 0 }");
1131 }
1132
1133 // Verify that we have the expected default DHCPv6 packet queue.
TEST_F(IfaceMgrTest,packetQueue6)1134 TEST_F(IfaceMgrTest, packetQueue6) {
1135 NakedIfaceMgr ifacemgr;
1136
1137 // Should not have a queue at start up.
1138 ASSERT_FALSE(ifacemgr.getPacketQueue6());
1139
1140 // Verify that we can create a queue with default factory.
1141 data::ConstElementPtr config = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 2000);
1142 ASSERT_NO_THROW(ifacemgr.getPacketQueueMgr6()->createPacketQueue(config));
1143 CHECK_QUEUE_INFO(ifacemgr.getPacketQueue6(), "{ \"capacity\": 2000, \"queue-type\": \""
1144 << PacketQueueMgr6::DEFAULT_QUEUE_TYPE6 << "\", \"size\": 0 }");
1145 }
1146
TEST_F(IfaceMgrTest,receiveTimeout6)1147 TEST_F(IfaceMgrTest, receiveTimeout6) {
1148 using namespace boost::posix_time;
1149 std::cout << "Testing DHCPv6 packet reception timeouts."
1150 << " Test will block for a few seconds when waiting"
1151 << " for timeout to occur." << std::endl;
1152
1153 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
1154 // Open socket on the lo interface.
1155 IOAddress lo_addr("::1");
1156 int socket1 = 0;
1157 ASSERT_NO_THROW(
1158 socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10547)
1159 );
1160 // Socket is open if result is non-negative.
1161 ASSERT_GE(socket1, 0);
1162 // Start receiver.
1163 ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET6));
1164
1165 // Remember when we call receive6().
1166 ptime start_time = microsec_clock::universal_time();
1167 // Call receive with timeout of 1s + 400000us = 1.4s.
1168 Pkt6Ptr pkt;
1169 ASSERT_NO_THROW(pkt = ifacemgr->receive6(1, 400000));
1170 // Remember when call to receive6() ended.
1171 ptime stop_time = microsec_clock::universal_time();
1172 // We did not send a packet to lo interface so we expect that
1173 // nothing has been received and timeout has been reached.
1174 ASSERT_FALSE(pkt);
1175 // Calculate duration of call to receive6().
1176 time_duration duration = stop_time - start_time;
1177 // We stop the clock when the call completes so it does not
1178 // precisely reflect the receive timeout. However the
1179 // uncertainty should be low enough to expect that measured
1180 // value is in the range <1.4s; 1.7s>.
1181 EXPECT_GE(duration.total_microseconds(),
1182 1400000 - TIMEOUT_TOLERANCE);
1183 EXPECT_LE(duration.total_microseconds(), 1700000);
1184
1185 // Test timeout shorter than 1s.
1186 start_time = microsec_clock::universal_time();
1187 ASSERT_NO_THROW(pkt = ifacemgr->receive6(0, 500000));
1188 stop_time = microsec_clock::universal_time();
1189 ASSERT_FALSE(pkt);
1190 duration = stop_time - start_time;
1191 // Check if measured duration is within <0.5s; 0.8s>.
1192 EXPECT_GE(duration.total_microseconds(),
1193 500000 - TIMEOUT_TOLERANCE);
1194 EXPECT_LE(duration.total_microseconds(), 800000);
1195
1196 // Test with invalid fractional timeout values.
1197 EXPECT_THROW(ifacemgr->receive6(0, 1000000), isc::BadValue);
1198 EXPECT_THROW(ifacemgr->receive6(1, 1000010), isc::BadValue);
1199
1200 // Stop receiver.
1201 EXPECT_NO_THROW(ifacemgr->stopDHCPReceiver());
1202 }
1203
TEST_F(IfaceMgrTest,receiveTimeout4)1204 TEST_F(IfaceMgrTest, receiveTimeout4) {
1205 using namespace boost::posix_time;
1206 std::cout << "Testing DHCPv4 packet reception timeouts."
1207 << " Test will block for a few seconds when waiting"
1208 << " for timeout to occur." << std::endl;
1209
1210 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
1211 // Open socket on the lo interface.
1212 IOAddress lo_addr("127.0.0.1");
1213 int socket1 = 0;
1214 ASSERT_NO_THROW(
1215 socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10067)
1216 );
1217 // Socket is open if returned value is non-negative.
1218 ASSERT_GE(socket1, 0);
1219
1220 // Start receiver.
1221 ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));
1222
1223 Pkt4Ptr pkt;
1224 // Remember when we call receive4().
1225 ptime start_time = microsec_clock::universal_time();
1226 // Call receive with timeout of 2s + 300000us = 2.3s.
1227 ASSERT_NO_THROW(pkt = ifacemgr->receive4(2, 300000));
1228 // Remember when call to receive4() ended.
1229 ptime stop_time = microsec_clock::universal_time();
1230 // We did not send a packet to lo interface so we expect that
1231 // nothing has been received and timeout has been reached.
1232 ASSERT_FALSE(pkt);
1233 // Calculate duration of call to receive4().
1234 time_duration duration = stop_time - start_time;
1235 // We stop the clock when the call completes so it does not
1236 // precisely reflect the receive timeout. However the
1237 // uncertainty should be low enough to expect that measured
1238 // value is in the range <2.3s; 2.6s>.
1239 EXPECT_GE(duration.total_microseconds(),
1240 2300000 - TIMEOUT_TOLERANCE);
1241 EXPECT_LE(duration.total_microseconds(), 2600000);
1242
1243 // Test timeout shorter than 1s.
1244 start_time = microsec_clock::universal_time();
1245 ASSERT_NO_THROW(pkt = ifacemgr->receive4(0, 400000));
1246 stop_time = microsec_clock::universal_time();
1247 ASSERT_FALSE(pkt);
1248 duration = stop_time - start_time;
1249 // Check if measured duration is within <0.4s; 0.7s>.
1250 EXPECT_GE(duration.total_microseconds(),
1251 400000 - TIMEOUT_TOLERANCE);
1252 EXPECT_LE(duration.total_microseconds(), 700000);
1253
1254 // Test with invalid fractional timeout values.
1255 EXPECT_THROW(ifacemgr->receive4(0, 1000000), isc::BadValue);
1256 EXPECT_THROW(ifacemgr->receive4(2, 1000005), isc::BadValue);
1257
1258 // Stop receiver.
1259 EXPECT_NO_THROW(ifacemgr->stopDHCPReceiver());
1260 }
1261
TEST_F(IfaceMgrTest,multipleSockets)1262 TEST_F(IfaceMgrTest, multipleSockets) {
1263 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
1264
1265 // Container for initialized socket descriptors
1266 std::list<uint16_t> init_sockets;
1267
1268 // Create socket #1
1269 int socket1 = 0;
1270 ASSERT_NO_THROW(
1271 socket1 = ifacemgr->openSocketFromIface(LOOPBACK_NAME, PORT1, AF_INET);
1272 );
1273 ASSERT_GE(socket1, 0);
1274 init_sockets.push_back(socket1);
1275
1276 // Create socket #2
1277 IOAddress lo_addr("127.0.0.1");
1278 int socket2 = 0;
1279 ASSERT_NO_THROW(
1280 socket2 = ifacemgr->openSocketFromRemoteAddress(lo_addr, PORT2);
1281 );
1282 ASSERT_GE(socket2, 0);
1283 init_sockets.push_back(socket2);
1284
1285 // Get loopback interface. If we don't find one we are unable to run
1286 // this test but we don't want to fail.
1287 IfacePtr iface_ptr = ifacemgr->getIface(LOOPBACK_NAME);
1288 if (iface_ptr == NULL) {
1289 cout << "Local loopback interface not found. Skipping test. " << endl;
1290 return;
1291 }
1292 ASSERT_EQ(LOOPBACK_INDEX, iface_ptr->getIndex());
1293 // Once sockets have been successfully opened, they are supposed to
1294 // be on the list. Here we start to test if all expected sockets
1295 // are on the list and no other (unexpected) socket is there.
1296 Iface::SocketCollection sockets = iface_ptr->getSockets();
1297 int matched_sockets = 0;
1298 for (std::list<uint16_t>::iterator init_sockets_it =
1299 init_sockets.begin();
1300 init_sockets_it != init_sockets.end(); ++init_sockets_it) {
1301 // Set socket descriptors non blocking in order to be able
1302 // to call recv() on them without hang.
1303 int flags = fcntl(*init_sockets_it, F_GETFL, 0);
1304 ASSERT_GE(flags, 0);
1305 ASSERT_GE(fcntl(*init_sockets_it, F_SETFL, flags | O_NONBLOCK), 0);
1306 // recv() is expected to result in EWOULDBLOCK error on non-blocking
1307 // socket in case socket is valid but simply no data are coming in.
1308 char buf;
1309 recv(*init_sockets_it, &buf, 1, MSG_PEEK);
1310 EXPECT_EQ(EWOULDBLOCK, errno);
1311 // Apart from the ability to use the socket we want to make
1312 // sure that socket on the list is the one that we created.
1313 for (Iface::SocketCollection::const_iterator socket_it =
1314 sockets.begin(); socket_it != sockets.end(); ++socket_it) {
1315 if (*init_sockets_it == socket_it->sockfd_) {
1316 // This socket is the one that we created.
1317 ++matched_sockets;
1318 break;
1319 }
1320 }
1321 }
1322 // All created sockets have been matched if this condition works.
1323 EXPECT_EQ(sockets.size(), matched_sockets);
1324
1325 // closeSockets() is the other function that we want to test. It
1326 // is supposed to close all sockets so as we will not be able to use
1327 // them anymore communication.
1328 ifacemgr->closeSockets();
1329
1330 // Closed sockets are supposed to be removed from the list
1331 sockets = iface_ptr->getSockets();
1332 ASSERT_EQ(0, sockets.size());
1333
1334 // We are still in possession of socket descriptors that we created
1335 // on the beginning of this test. We can use them to check whether
1336 // closeSockets() only removed them from the list or they have been
1337 // really closed.
1338 for (std::list<uint16_t>::const_iterator init_sockets_it =
1339 init_sockets.begin();
1340 init_sockets_it != init_sockets.end(); ++init_sockets_it) {
1341 // recv() must result in error when using invalid socket.
1342 char buf;
1343 static_cast<void>(recv(*init_sockets_it, &buf, 1, MSG_PEEK));
1344 // EWOULDBLOCK would mean that socket is valid/open but
1345 // simply no data is received so we have to check for
1346 // other errors.
1347 EXPECT_NE(EWOULDBLOCK, errno);
1348 }
1349 }
1350
TEST_F(IfaceMgrTest,sockets6)1351 TEST_F(IfaceMgrTest, sockets6) {
1352 // Testing socket operation in a portable way is tricky
1353 // without interface detection implemented.
1354
1355 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
1356
1357 IOAddress lo_addr("::1");
1358
1359 Pkt6Ptr pkt6(new Pkt6(DHCPV6_SOLICIT, 123));
1360 pkt6->setIface(LOOPBACK_NAME);
1361
1362 // Bind multicast socket to port 10547
1363 int socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10547);
1364 EXPECT_GE(socket1, 0); // socket >= 0
1365
1366 EXPECT_EQ(socket1, ifacemgr->getSocket(pkt6));
1367
1368 // Bind unicast socket to port 10548
1369 int socket2 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10548);
1370 EXPECT_GE(socket2, 0);
1371
1372 // Removed code for binding socket twice to the same address/port
1373 // as it caused problems on some platforms (e.g. Mac OS X)
1374
1375 // Close sockets here because the following tests will want to
1376 // open sockets on the same ports.
1377 ifacemgr->closeSockets();
1378
1379 // Use address that is not assigned to LOOPBACK iface.
1380 IOAddress invalidAddr("::2");
1381 EXPECT_THROW(
1382 ifacemgr->openSocket(LOOPBACK_NAME, invalidAddr, 10547),
1383 SocketConfigError
1384 );
1385
1386 // Use non-existing interface name.
1387 EXPECT_THROW(
1388 ifacemgr->openSocket("non_existing_interface", lo_addr, 10548),
1389 BadValue
1390 );
1391
1392 // Do not call closeSockets() because it is called by IfaceMgr's
1393 // virtual destructor.
1394 }
1395
TEST_F(IfaceMgrTest,socketsFromIface)1396 TEST_F(IfaceMgrTest, socketsFromIface) {
1397 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
1398
1399 // Open v6 socket on loopback interface and bind to port
1400 int socket1 = 0;
1401 EXPECT_NO_THROW(
1402 socket1 = ifacemgr->openSocketFromIface(LOOPBACK_NAME, PORT1, AF_INET6);
1403 );
1404 // Socket descriptor must be non-negative integer
1405 EXPECT_GE(socket1, 0);
1406 close(socket1);
1407
1408 // Open v4 socket on loopback interface and bind to different port
1409 int socket2 = 0;
1410 EXPECT_NO_THROW(
1411 socket2 = ifacemgr->openSocketFromIface(LOOPBACK_NAME, PORT2, AF_INET);
1412 );
1413 // socket descriptor must be non-negative integer
1414 EXPECT_GE(socket2, 0);
1415 close(socket2);
1416
1417 // Close sockets here because the following tests will want to
1418 // open sockets on the same ports.
1419 ifacemgr->closeSockets();
1420
1421 // Use invalid interface name.
1422 EXPECT_THROW(
1423 ifacemgr->openSocketFromIface("non_existing_interface", PORT1, AF_INET),
1424 BadValue
1425 );
1426
1427 // Do not call closeSockets() because it is called by IfaceMgr's
1428 // virtual destructor.
1429 }
1430
1431
TEST_F(IfaceMgrTest,socketsFromAddress)1432 TEST_F(IfaceMgrTest, socketsFromAddress) {
1433 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
1434
1435 // Open v6 socket on loopback interface and bind to port
1436 int socket1 = 0;
1437 IOAddress lo_addr6("::1");
1438 EXPECT_NO_THROW(
1439 socket1 = ifacemgr->openSocketFromAddress(lo_addr6, PORT1);
1440 );
1441 // socket descriptor must be non-negative integer
1442 EXPECT_GE(socket1, 0);
1443
1444 // Open v4 socket on loopback interface and bind to different port
1445 int socket2 = 0;
1446 IOAddress lo_addr("127.0.0.1");
1447 EXPECT_NO_THROW(
1448 socket2 = ifacemgr->openSocketFromAddress(lo_addr, PORT2);
1449 );
1450 // socket descriptor must be positive integer
1451 EXPECT_GE(socket2, 0);
1452
1453 // Close sockets here because the following tests will want to
1454 // open sockets on the same ports.
1455 ifacemgr->closeSockets();
1456
1457 // Use non-existing address.
1458 IOAddress invalidAddr("1.2.3.4");
1459 EXPECT_THROW(
1460 ifacemgr->openSocketFromAddress(invalidAddr, PORT1), BadValue
1461 );
1462
1463 // Do not call closeSockets() because it is called by IfaceMgr's
1464 // virtual destructor.
1465 }
1466
TEST_F(IfaceMgrTest,socketsFromRemoteAddress)1467 TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
1468 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
1469
1470 // Open v6 socket to connect to remote address.
1471 // Loopback address is the only one that we know
1472 // so let's treat it as remote address.
1473 int socket1 = 0;
1474 IOAddress lo_addr6("::1");
1475 EXPECT_NO_THROW(
1476 socket1 = ifacemgr->openSocketFromRemoteAddress(lo_addr6, PORT1);
1477 );
1478 EXPECT_GE(socket1, 0);
1479
1480 // Open v4 socket to connect to remote address.
1481 int socket2 = 0;
1482 IOAddress lo_addr("127.0.0.1");
1483 EXPECT_NO_THROW(
1484 socket2 = ifacemgr->openSocketFromRemoteAddress(lo_addr, PORT2);
1485 );
1486 EXPECT_GE(socket2, 0);
1487
1488 // Close sockets here because the following tests will want to
1489 // open sockets on the same ports.
1490 ifacemgr->closeSockets();
1491
1492 // There used to be a check here that verified the ability to open
1493 // suitable socket for sending broadcast request. However,
1494 // there is no guarantee for such test to work on all systems
1495 // because some systems may have no broadcast capable interfaces at all.
1496 // Thus, this check has been removed.
1497
1498 // Do not call closeSockets() because it is called by IfaceMgr's
1499 // virtual destructor.
1500 }
1501
1502 // TODO: disabled due to other naming on various systems
1503 // (lo in Linux, lo0 in BSD systems)
TEST_F(IfaceMgrTest,DISABLED_sockets6Mcast)1504 TEST_F(IfaceMgrTest, DISABLED_sockets6Mcast) {
1505 // testing socket operation in a portable way is tricky
1506 // without interface detection implemented
1507
1508 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
1509
1510 IOAddress lo_addr("::1");
1511 IOAddress mcastAddr("ff02::1:2");
1512
1513 // bind multicast socket to port 10547
1514 int socket1 = ifacemgr->openSocket(LOOPBACK_NAME, mcastAddr, 10547);
1515 EXPECT_GE(socket1, 0); // socket > 0
1516
1517 // expect success. This address/port is already bound, but
1518 // we are using SO_REUSEADDR, so we can bind it twice
1519 int socket2 = ifacemgr->openSocket(LOOPBACK_NAME, mcastAddr, 10547);
1520 EXPECT_GE(socket2, 0);
1521
1522 // there's no good way to test negative case here.
1523 // we would need non-multicast interface. We will be able
1524 // to iterate thru available interfaces and check if there
1525 // are interfaces without multicast-capable flag.
1526
1527 close(socket1);
1528 close(socket2);
1529 }
1530
1531 // Verifies that basic DHPCv6 packet send and receive operates
1532 // in either direct or indirect mode.
TEST_F(IfaceMgrTest,sendReceive6)1533 TEST_F(IfaceMgrTest, sendReceive6) {
1534 data::ElementPtr queue_control;
1535
1536 // Given an empty pointer, queueing should be disabled.
1537 // This should do direct reception.
1538 sendReceive6Test(queue_control, false);
1539
1540 // Now let's populate queue control.
1541 queue_control = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500, false);
1542 // With queueing disabled, we should use direct reception.
1543 sendReceive6Test(queue_control, false);
1544
1545 // Queuing enabled, indirection reception should work.
1546 queue_control = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500, true);
1547 sendReceive6Test(queue_control, true);
1548 }
1549
1550 // Verifies that basic DHPCv4 packet send and receive operates
1551 // in either direct or indirect mode.
TEST_F(IfaceMgrTest,sendReceive4)1552 TEST_F(IfaceMgrTest, sendReceive4) {
1553 data::ElementPtr queue_control;
1554
1555 // Given an empty pointer, queueing should be disabled.
1556 // This should do direct reception.
1557 sendReceive4Test(queue_control, false);
1558
1559 // Now let's populate queue control.
1560 queue_control = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500, false);
1561 // With queueing disabled, we should use direct reception.
1562 sendReceive4Test(queue_control, false);
1563
1564 // Queuing enabled, indirection reception should work.
1565 queue_control = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500, true);
1566 sendReceive4Test(queue_control, true);
1567 }
1568
1569 // Verifies that it is possible to set custom packet filter object
1570 // to handle sockets opening and send/receive operation.
TEST_F(IfaceMgrTest,setPacketFilter)1571 TEST_F(IfaceMgrTest, setPacketFilter) {
1572
1573 // Create an instance of IfaceMgr.
1574 boost::scoped_ptr<NakedIfaceMgr> iface_mgr(new NakedIfaceMgr());
1575 ASSERT_TRUE(iface_mgr);
1576
1577 // Try to set NULL packet filter object and make sure it is rejected.
1578 boost::shared_ptr<TestPktFilter> custom_packet_filter;
1579 EXPECT_THROW(iface_mgr->setPacketFilter(custom_packet_filter),
1580 isc::dhcp::InvalidPacketFilter);
1581
1582 // Create valid object and check if it can be set.
1583 custom_packet_filter.reset(new TestPktFilter());
1584 ASSERT_TRUE(custom_packet_filter);
1585 ASSERT_NO_THROW(iface_mgr->setPacketFilter(custom_packet_filter));
1586
1587 // Try to open socket using IfaceMgr. It should call the openSocket() function
1588 // on the packet filter object we have set.
1589 IOAddress lo_addr("127.0.0.1");
1590 int socket1 = 0;
1591 EXPECT_NO_THROW(
1592 socket1 = iface_mgr->openSocket(LOOPBACK_NAME, lo_addr,
1593 DHCP4_SERVER_PORT + 10000);
1594 );
1595
1596 // Check that openSocket function was called.
1597 EXPECT_TRUE(custom_packet_filter->open_socket_called_);
1598 // This function always returns fake socket descriptor equal to 255.
1599 EXPECT_EQ(255, socket1);
1600
1601 // Replacing current packet filter object while there are IPv4
1602 // sockets open is not allowed!
1603 EXPECT_THROW(iface_mgr->setPacketFilter(custom_packet_filter),
1604 PacketFilterChangeDenied);
1605
1606 // So, let's close the open sockets and retry. Now it should succeed.
1607 iface_mgr->closeSockets();
1608 EXPECT_NO_THROW(iface_mgr->setPacketFilter(custom_packet_filter));
1609 }
1610
1611 // This test checks that the default packet filter for DHCPv6 can be replaced
1612 // with the custom one.
TEST_F(IfaceMgrTest,setPacketFilter6)1613 TEST_F(IfaceMgrTest, setPacketFilter6) {
1614 // Create an instance of IfaceMgr.
1615 boost::scoped_ptr<NakedIfaceMgr> iface_mgr(new NakedIfaceMgr());
1616 ASSERT_TRUE(iface_mgr);
1617
1618 // Try to set NULL packet filter object and make sure it is rejected.
1619 boost::shared_ptr<PktFilter6Stub> custom_packet_filter;
1620 EXPECT_THROW(iface_mgr->setPacketFilter(custom_packet_filter),
1621 isc::dhcp::InvalidPacketFilter);
1622
1623 // Create valid object and check if it can be set.
1624 custom_packet_filter.reset(new PktFilter6Stub());
1625 ASSERT_TRUE(custom_packet_filter);
1626 ASSERT_NO_THROW(iface_mgr->setPacketFilter(custom_packet_filter));
1627
1628 // Try to open socket using IfaceMgr. It should call the openSocket()
1629 // function on the packet filter object we have set.
1630 IOAddress lo_addr("::1");
1631 int socket1 = 0;
1632 EXPECT_NO_THROW(
1633 socket1 = iface_mgr->openSocket(LOOPBACK_NAME, lo_addr,
1634 DHCP6_SERVER_PORT + 10000);
1635 );
1636 // Check that openSocket function has been actually called on the packet
1637 // filter object.
1638 EXPECT_EQ(1, custom_packet_filter->open_socket_count_);
1639 // Also check that the returned socket descriptor has an expected value.
1640 EXPECT_EQ(0, socket1);
1641
1642 // Replacing current packet filter object, while there are sockets open,
1643 // is not allowed!
1644 EXPECT_THROW(iface_mgr->setPacketFilter(custom_packet_filter),
1645 PacketFilterChangeDenied);
1646
1647 // So, let's close the sockets and retry. Now it should succeed.
1648 iface_mgr->closeSockets();
1649 EXPECT_NO_THROW(iface_mgr->setPacketFilter(custom_packet_filter));
1650 }
1651
1652 #if defined OS_LINUX || OS_BSD
1653
1654 // This test is only supported on Linux and BSD systems. It checks
1655 // if it is possible to use the IfaceMgr to select the packet filter
1656 // object which can be used to send direct responses to the host
1657 // which doesn't have an address yet.
TEST_F(IfaceMgrTest,setMatchingPacketFilter)1658 TEST_F(IfaceMgrTest, setMatchingPacketFilter) {
1659
1660 // Create an instance of IfaceMgr.
1661 boost::scoped_ptr<NakedIfaceMgr> iface_mgr(new NakedIfaceMgr());
1662 ASSERT_TRUE(iface_mgr);
1663
1664 // Let IfaceMgr figure out which Packet Filter to use when
1665 // direct response capability is not desired. It should pick
1666 // PktFilterInet on Linux.
1667 EXPECT_NO_THROW(iface_mgr->setMatchingPacketFilter(false));
1668 // The PktFilterInet is supposed to report lack of direct
1669 // response capability.
1670 EXPECT_FALSE(iface_mgr->isDirectResponseSupported());
1671
1672 // There is working implementation of direct responses on Linux
1673 // and BSD (using PktFilterLPF and PktFilterBPF. When direct
1674 // responses are desired the object of this class should be set.
1675 EXPECT_NO_THROW(iface_mgr->setMatchingPacketFilter(true));
1676 // This object should report that direct responses are supported.
1677 EXPECT_TRUE(iface_mgr->isDirectResponseSupported());
1678 }
1679
1680 // This test checks that it is not possible to open two sockets: IP/UDP
1681 // and raw socket and bind to the same address and port. The
1682 // raw socket should be opened together with the fallback IP/UDP socket.
1683 // The fallback socket should fail to open when there is another IP/UDP
1684 // socket bound to the same address and port. Failing to open the fallback
1685 // socket should preclude the raw socket from being open.
TEST_F(IfaceMgrTest,checkPacketFilterRawSocket)1686 TEST_F(IfaceMgrTest, checkPacketFilterRawSocket) {
1687 IOAddress lo_addr("127.0.0.1");
1688 int socket1 = -1, socket2 = -1;
1689 // Create two instances of IfaceMgr.
1690 boost::scoped_ptr<NakedIfaceMgr> iface_mgr1(new NakedIfaceMgr());
1691 ASSERT_TRUE(iface_mgr1);
1692 boost::scoped_ptr<NakedIfaceMgr> iface_mgr2(new NakedIfaceMgr());
1693 ASSERT_TRUE(iface_mgr2);
1694
1695 // Let IfaceMgr figure out which Packet Filter to use when
1696 // direct response capability is not desired. It should pick
1697 // PktFilterInet.
1698 EXPECT_NO_THROW(iface_mgr1->setMatchingPacketFilter(false));
1699 // Let's open a loopback socket with handy unpriviliged port number
1700 socket1 = iface_mgr1->openSocket(LOOPBACK_NAME, lo_addr,
1701 DHCP4_SERVER_PORT + 10000);
1702
1703 EXPECT_GE(socket1, 0);
1704
1705 // Then the second use PkFilterLPF mode
1706 EXPECT_NO_THROW(iface_mgr2->setMatchingPacketFilter(true));
1707
1708 // The socket is open and bound. Another attempt to open socket and
1709 // bind to the same address and port should result in an exception.
1710 EXPECT_THROW(
1711 socket2 = iface_mgr2->openSocket(LOOPBACK_NAME, lo_addr,
1712 DHCP4_SERVER_PORT + 10000),
1713 isc::dhcp::SocketConfigError
1714 );
1715 // Surprisingly we managed to open another socket. We have to close it
1716 // to prevent resource leak.
1717 if (socket2 >= 0) {
1718 close(socket2);
1719 ADD_FAILURE() << "Two sockets opened and bound to the same IP"
1720 " address and UDP port";
1721 }
1722
1723 if (socket1 >= 0) {
1724 close(socket1);
1725 }
1726 }
1727
1728 #else
1729
1730 // Note: This test will only run on non-Linux and non-BSD systems.
1731 // This test checks whether it is possible to use IfaceMgr to figure
1732 // out which Packet Filter object should be used when direct responses
1733 // to hosts, having no address assigned are desired or not desired.
1734 // Since direct responses aren't supported on systems other than Linux
1735 // and BSD the function under test should always set object of
1736 // PktFilterInet type as current Packet Filter. This object does not
1737 //support direct responses. Once implementation is added on systems
1738 // other than BSD and Linux the OS specific version of the test will
1739 // be removed.
TEST_F(IfaceMgrTest,setMatchingPacketFilter)1740 TEST_F(IfaceMgrTest, setMatchingPacketFilter) {
1741
1742 // Create an instance of IfaceMgr.
1743 boost::scoped_ptr<NakedIfaceMgr> iface_mgr(new NakedIfaceMgr());
1744 ASSERT_TRUE(iface_mgr);
1745
1746 // Let IfaceMgr figure out which Packet Filter to use when
1747 // direct response capability is not desired. It should pick
1748 // PktFilterInet.
1749 EXPECT_NO_THROW(iface_mgr->setMatchingPacketFilter(false));
1750 // The PktFilterInet is supposed to report lack of direct
1751 // response capability.
1752 EXPECT_FALSE(iface_mgr->isDirectResponseSupported());
1753
1754 // On non-Linux systems, we are missing the direct traffic
1755 // implementation. Therefore, we expect that PktFilterInet
1756 // object will be set.
1757 EXPECT_NO_THROW(iface_mgr->setMatchingPacketFilter(true));
1758 // This object should report lack of direct response capability.
1759 EXPECT_FALSE(iface_mgr->isDirectResponseSupported());
1760 }
1761
1762 #endif
1763
TEST_F(IfaceMgrTest,socket4)1764 TEST_F(IfaceMgrTest, socket4) {
1765
1766 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
1767
1768 // Let's assume that every supported OS have lo interface.
1769 IOAddress lo_addr("127.0.0.1");
1770 // Use unprivileged port (it's convenient for running tests as non-root).
1771 int socket1 = 0;
1772
1773 EXPECT_NO_THROW(
1774 socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr,
1775 DHCP4_SERVER_PORT + 10000);
1776 );
1777
1778 EXPECT_GE(socket1, 0);
1779
1780 Pkt4Ptr pkt(new Pkt4(DHCPDISCOVER, 1234));
1781 pkt->setIface(LOOPBACK_NAME);
1782 pkt->setIndex(LOOPBACK_INDEX);
1783
1784 // Expect that we get the socket that we just opened.
1785 EXPECT_EQ(socket1, ifacemgr->getSocket(pkt).sockfd_);
1786
1787 close(socket1);
1788 }
1789
1790 // This test verifies that IPv4 sockets are open on all interfaces (except
1791 // loopback), when interfaces are up, running and active (not disabled from
1792 // the DHCP configuration).
TEST_F(IfaceMgrTest,openSockets4)1793 TEST_F(IfaceMgrTest, openSockets4) {
1794 NakedIfaceMgr ifacemgr;
1795
1796 // Remove all real interfaces and create a set of dummy interfaces.
1797 ifacemgr.createIfaces();
1798
1799 // Use the custom packet filter object. This object mimics the socket
1800 // opening operation - the real socket is not open.
1801 boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
1802 ASSERT_TRUE(custom_packet_filter);
1803 ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));
1804
1805 // Simulate opening sockets using the dummy packet filter.
1806 ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0));
1807
1808 // Expect that the sockets are open on both eth0 and eth1.
1809 EXPECT_EQ(1, ifacemgr.getIface("eth0")->getSockets().size());
1810 EXPECT_EQ(1, ifacemgr.getIface(ETH0_INDEX)->getSockets().size());
1811 EXPECT_EQ(1, ifacemgr.getIface("eth1")->getSockets().size());
1812 EXPECT_EQ(1, ifacemgr.getIface(ETH1_INDEX)->getSockets().size());
1813 // Socket shouldn't have been opened on loopback.
1814 EXPECT_TRUE(ifacemgr.getIface("lo")->getSockets().empty());
1815 EXPECT_TRUE(ifacemgr.getIface(LO_INDEX)->getSockets().empty());
1816 }
1817
1818 // This test verifies that IPv4 sockets are open on the loopback interface
1819 // when the loopback is active and allowed.
TEST_F(IfaceMgrTest,openSockets4Loopback)1820 TEST_F(IfaceMgrTest, openSockets4Loopback) {
1821 NakedIfaceMgr ifacemgr;
1822
1823 // Remove all real interfaces and create a set of dummy interfaces.
1824 ifacemgr.createIfaces();
1825
1826 // Allow the loopback interface.
1827 ifacemgr.setAllowLoopBack(true);
1828
1829 // Make the loopback interface active.
1830 ifacemgr.getIface("lo")->inactive4_ = false;
1831
1832 // Use the custom packet filter object. This object mimics the socket
1833 // opening operation - the real socket is not open.
1834 boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
1835 ASSERT_TRUE(custom_packet_filter);
1836 ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));
1837
1838 // Simulate opening sockets using the dummy packet filter.
1839 ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0));
1840
1841 // Expect that the sockets are open on all interfaces.
1842 EXPECT_EQ(1, ifacemgr.getIface("eth0")->getSockets().size());
1843 EXPECT_EQ(1, ifacemgr.getIface(ETH0_INDEX)->getSockets().size());
1844 EXPECT_EQ(1, ifacemgr.getIface("eth1")->getSockets().size());
1845 EXPECT_EQ(1, ifacemgr.getIface(ETH1_INDEX)->getSockets().size());
1846 EXPECT_EQ(1, ifacemgr.getIface("lo")->getSockets().size());
1847 EXPECT_EQ(1, ifacemgr.getIface(LO_INDEX)->getSockets().size());
1848 }
1849
1850 // This test verifies that the socket is not open on the interface which is
1851 // down, but sockets are open on all other non-loopback interfaces.
TEST_F(IfaceMgrTest,openSockets4IfaceDown)1852 TEST_F(IfaceMgrTest, openSockets4IfaceDown) {
1853 IfaceMgrTestConfig config(true);
1854
1855 // Boolean parameters specify that eth0 is:
1856 // - not a loopback
1857 // - is "down" (not up)
1858 // - is not running
1859 // - is active (is not inactive)
1860 config.setIfaceFlags("eth0", FlagLoopback(false), FlagUp(false),
1861 FlagRunning(false), FlagInactive4(false),
1862 FlagInactive6(false));
1863 ASSERT_FALSE(IfaceMgr::instance().getIface("eth0")->flag_up_);
1864 ASSERT_FALSE(IfaceMgr::instance().getIface(ETH0_INDEX)->flag_up_);
1865
1866 // Install an error handler before trying to open sockets. This handler
1867 // should be called when the IfaceMgr fails to open socket on an interface
1868 // on which the server is configured to listen.
1869 isc::dhcp::IfaceMgrErrorMsgCallback error_handler =
1870 std::bind(&IfaceMgrTest::ifaceMgrErrorHandler, this, ph::_1);
1871
1872 ASSERT_NO_THROW(IfaceMgr::instance().openSockets4(DHCP4_SERVER_PORT, true,
1873 error_handler));
1874 // Since the interface is down, an attempt to open a socket should result
1875 // in error.
1876 EXPECT_EQ(1, errors_count_);
1877
1878 // There should be no socket on eth0 open, because interface was down.
1879 EXPECT_TRUE(IfaceMgr::instance().getIface("eth0")->getSockets().empty());
1880 EXPECT_TRUE(IfaceMgr::instance().getIface(ETH0_INDEX)->getSockets().empty());
1881
1882 // Expecting that the socket is open on eth1 because it was up, running
1883 // and active.
1884 EXPECT_EQ(2, IfaceMgr::instance().getIface("eth1")->getSockets().size());
1885 EXPECT_EQ(2, IfaceMgr::instance().getIface(ETH1_INDEX)->getSockets().size());
1886 // Same for eth1961.
1887 EXPECT_EQ(1, IfaceMgr::instance().getIface("eth1961")->getSockets().size());
1888 EXPECT_EQ(1, IfaceMgr::instance().getIface(ETH1961_INDEX)->getSockets().size());
1889 // Never open socket on loopback interface.
1890 EXPECT_TRUE(IfaceMgr::instance().getIface("lo")->getSockets().empty());
1891 EXPECT_TRUE(IfaceMgr::instance().getIface(LO_INDEX)->getSockets().empty());
1892 }
1893
1894 // This test verifies that the socket is not open on the interface which is
1895 // disabled from the DHCP configuration, but sockets are open on all other
1896 // non-loopback interfaces.
TEST_F(IfaceMgrTest,openSockets4IfaceInactive)1897 TEST_F(IfaceMgrTest, openSockets4IfaceInactive) {
1898 NakedIfaceMgr ifacemgr;
1899
1900 // Remove all real interfaces and create a set of dummy interfaces.
1901 ifacemgr.createIfaces();
1902
1903 boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
1904 ASSERT_TRUE(custom_packet_filter);
1905 ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));
1906
1907 // Boolean parameters specify that eth1 is:
1908 // - not a loopback
1909 // - is up
1910 // - is running
1911 // - is inactive
1912 ifacemgr.setIfaceFlags("eth1", false, true, true, true, false);
1913 ASSERT_TRUE(ifacemgr.getIface("eth1")->inactive4_);
1914 ASSERT_TRUE(ifacemgr.getIface(ETH1_INDEX)->inactive4_);
1915 ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0));
1916
1917 // The socket on eth0 should be open because interface is up, running and
1918 // active (not disabled through DHCP configuration, for example).
1919 EXPECT_EQ(1, ifacemgr.getIface("eth0")->getSockets().size());
1920 EXPECT_EQ(1, ifacemgr.getIface(ETH0_INDEX)->getSockets().size());
1921 // There should be no socket open on eth1 because it was marked inactive.
1922 EXPECT_TRUE(ifacemgr.getIface("eth1")->getSockets().empty());
1923 EXPECT_TRUE(ifacemgr.getIface(ETH1_INDEX)->getSockets().empty());
1924 // Sockets are not open on loopback interfaces too.
1925 EXPECT_TRUE(ifacemgr.getIface("lo")->getSockets().empty());
1926 EXPECT_TRUE(ifacemgr.getIface(LO_INDEX)->getSockets().empty());
1927 }
1928
1929 // Test that exception is thrown when trying to bind a new socket to the port
1930 // and address which is already in use by another socket.
TEST_F(IfaceMgrTest,openSockets4NoErrorHandler)1931 TEST_F(IfaceMgrTest, openSockets4NoErrorHandler) {
1932 NakedIfaceMgr ifacemgr;
1933
1934 // Remove all real interfaces and create a set of dummy interfaces.
1935 ifacemgr.createIfaces();
1936
1937 boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
1938 ASSERT_TRUE(custom_packet_filter);
1939 ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));
1940
1941 // Open socket on eth1. The openSockets4 should detect that this
1942 // socket has been already open and an attempt to open another socket
1943 // and bind to this address and port should fail.
1944 ASSERT_NO_THROW(ifacemgr.openSocket("eth1", IOAddress("192.0.2.3"),
1945 DHCP4_SERVER_PORT));
1946
1947 // The function throws an exception when it tries to open a socket
1948 // and bind it to the address in use.
1949 EXPECT_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0),
1950 isc::dhcp::SocketConfigError);
1951 }
1952
1953 // Test that the external error handler is called when trying to bind a new
1954 // socket to the address and port being in use. The sockets on the other
1955 // interfaces should open just fine.
TEST_F(IfaceMgrTest,openSocket4ErrorHandler)1956 TEST_F(IfaceMgrTest, openSocket4ErrorHandler) {
1957 NakedIfaceMgr ifacemgr;
1958
1959 // Remove all real interfaces and create a set of dummy interfaces.
1960 ifacemgr.createIfaces();
1961
1962 boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
1963 ASSERT_TRUE(custom_packet_filter);
1964 ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));
1965
1966 // Open socket on eth0.
1967 ASSERT_NO_THROW(ifacemgr.openSocket("eth0", IOAddress("10.0.0.1"),
1968 DHCP4_SERVER_PORT));
1969
1970 // Install an error handler before trying to open sockets. This handler
1971 // should be called when the IfaceMgr fails to open socket on eth0.
1972 isc::dhcp::IfaceMgrErrorMsgCallback error_handler =
1973 std::bind(&IfaceMgrTest::ifaceMgrErrorHandler, this, ph::_1);
1974 // The openSockets4 should detect that there is another socket already
1975 // open and bound to the same address and port. An attempt to open
1976 // another socket and bind to this address and port should fail.
1977 ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, error_handler));
1978 // We expect that an error occurred when we tried to open a socket on
1979 // eth0, but the socket on eth1 should open just fine.
1980 EXPECT_EQ(1, errors_count_);
1981
1982 // Reset errors count.
1983 errors_count_ = 0;
1984
1985 // Now that we have two sockets open, we can try this again but this time
1986 // we should get two errors: one when opening a socket on eth0, another one
1987 // when opening a socket on eth1.
1988 ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, error_handler));
1989 EXPECT_EQ(2, errors_count_);
1990 }
1991
1992 // This test verifies that the function correctly checks that the v4 socket is
1993 // open and bound to a specific address.
TEST_F(IfaceMgrTest,hasOpenSocketForAddress4)1994 TEST_F(IfaceMgrTest, hasOpenSocketForAddress4) {
1995 NakedIfaceMgr ifacemgr;
1996
1997 // Remove all real interfaces and create a set of dummy interfaces.
1998 ifacemgr.createIfaces();
1999
2000 // Use the custom packet filter object. This object mimics the socket
2001 // opening operation - the real socket is not open.
2002 boost::shared_ptr<TestPktFilter> custom_packet_filter(new TestPktFilter());
2003 ASSERT_TRUE(custom_packet_filter);
2004 ASSERT_NO_THROW(ifacemgr.setPacketFilter(custom_packet_filter));
2005
2006 // Simulate opening sockets using the dummy packet filter.
2007 ASSERT_NO_THROW(ifacemgr.openSockets4(DHCP4_SERVER_PORT, true, 0));
2008
2009 // Expect that the sockets are open on both eth0 and eth1.
2010 ASSERT_EQ(1, ifacemgr.getIface("eth0")->getSockets().size());
2011 ASSERT_EQ(1, ifacemgr.getIface(ETH0_INDEX)->getSockets().size());
2012 ASSERT_EQ(1, ifacemgr.getIface("eth1")->getSockets().size());
2013 ASSERT_EQ(1, ifacemgr.getIface(ETH1_INDEX)->getSockets().size());
2014 // Socket shouldn't have been opened on loopback.
2015 ASSERT_TRUE(ifacemgr.getIface("lo")->getSockets().empty());
2016 ASSERT_TRUE(ifacemgr.getIface(LO_INDEX)->getSockets().empty());
2017
2018 // Check that there are sockets bound to addresses that we have
2019 // set for interfaces.
2020 EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("192.0.2.3")));
2021 EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("10.0.0.1")));
2022 // Check that there is no socket for the address which is not
2023 // configured on any interface.
2024 EXPECT_FALSE(ifacemgr.hasOpenSocket(IOAddress("10.1.1.1")));
2025
2026 // Check that v4 sockets are open, but no v6 socket is open.
2027 EXPECT_TRUE(ifacemgr.hasOpenSocket(AF_INET));
2028 EXPECT_FALSE(ifacemgr.hasOpenSocket(AF_INET6));
2029 }
2030
2031 // This test checks that the sockets are open and bound to link local addresses
2032 // only, if unicast addresses are not specified.
TEST_F(IfaceMgrTest,openSockets6LinkLocal)2033 TEST_F(IfaceMgrTest, openSockets6LinkLocal) {
2034 NakedIfaceMgr ifacemgr;
2035
2036 // Remove all real interfaces and create a set of dummy interfaces.
2037 ifacemgr.createIfaces();
2038
2039 boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
2040 ASSERT_TRUE(filter);
2041 ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
2042
2043 // Simulate opening sockets using the dummy packet filter.
2044 bool success = false;
2045 ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
2046 EXPECT_TRUE(success);
2047
2048 // Check that the number of sockets is correct on each interface.
2049 checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
2050 checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
2051 checkSocketsCount6(*ifacemgr.getIface("eth0"), 0);
2052 checkSocketsCount6(*ifacemgr.getIface(ETH0_INDEX), 0);
2053 checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
2054 checkSocketsCount6(*ifacemgr.getIface(ETH1_INDEX), 0);
2055
2056 // Sockets on eth0 should be bound to link-local and should not be bound
2057 // to global unicast address, even though this address is configured on
2058 // the eth0.
2059 EXPECT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
2060 EXPECT_FALSE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
2061 // Socket on eth1 should be bound to link local only.
2062 EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
2063
2064 // If we are on Linux, there is one more socket bound to ff02::1:2
2065 #if defined OS_LINUX
2066 EXPECT_TRUE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2067 EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2068 #endif
2069 }
2070
2071 // This test checks that the sockets are open on the loopback interface
2072 // when the loopback is active and allowed.
TEST_F(IfaceMgrTest,openSockets6Loopback)2073 TEST_F(IfaceMgrTest, openSockets6Loopback) {
2074 NakedIfaceMgr ifacemgr;
2075
2076 // Remove all real interfaces and create a set of dummy interfaces.
2077 ifacemgr.createIfaces();
2078
2079 // Allow the loopback interface.
2080 ifacemgr.setAllowLoopBack(true);
2081
2082 // Make the loopback interface active.
2083 ifacemgr.getIface("lo")->inactive6_ = false;
2084
2085 // The loopback interface has no link-local (as for Linux but not BSD)
2086 // so add one.
2087 ifacemgr.getIface("lo")->addUnicast(IOAddress("::1"));
2088
2089 boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
2090 ASSERT_TRUE(filter);
2091 ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
2092
2093 // Simulate opening sockets using the dummy packet filter.
2094 bool success = false;
2095 ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
2096 EXPECT_TRUE(success);
2097
2098 // Check that the loopback interface has at least an open socket.
2099 EXPECT_EQ(1, ifacemgr.getIface("lo")->getSockets().size());
2100 EXPECT_EQ(1, ifacemgr.getIface(LO_INDEX)->getSockets().size());
2101
2102 // This socket should be bound to ::1
2103 EXPECT_TRUE(ifacemgr.isBound("lo", "::1"));
2104 }
2105
2106 // This test checks that socket is not open on the interface which doesn't
2107 // have a link-local address.
TEST_F(IfaceMgrTest,openSockets6NoLinkLocal)2108 TEST_F(IfaceMgrTest, openSockets6NoLinkLocal) {
2109 NakedIfaceMgr ifacemgr;
2110
2111 // Remove all real interfaces and create a set of dummy interfaces.
2112 ifacemgr.createIfaces();
2113
2114 boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
2115 ASSERT_TRUE(filter);
2116 ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
2117
2118 // Remove a link local address from eth0. If there is no link-local
2119 // address, the socket should not open.
2120 ASSERT_TRUE(ifacemgr.getIface("eth0")->
2121 delAddress(IOAddress("fe80::3a60:77ff:fed5:cdef")));
2122
2123 // Simulate opening sockets using the dummy packet filter.
2124 bool success = false;
2125 ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
2126 EXPECT_TRUE(success);
2127
2128 // Check that the number of sockets is correct on each interface.
2129 checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
2130 checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
2131 // The third parameter specifies that the number of link-local
2132 // addresses for eth0 is equal to 0.
2133 checkSocketsCount6(*ifacemgr.getIface("eth0"), 0, 0);
2134 checkSocketsCount6(*ifacemgr.getIface(ETH0_INDEX), 0, 0);
2135 checkSocketsCount6(*ifacemgr.getIface("eth1"), 0, 1);
2136 checkSocketsCount6(*ifacemgr.getIface(ETH1_INDEX), 0, 1);
2137
2138 // There should be no sockets open on eth0 because it neither has
2139 // link-local nor global unicast addresses.
2140 EXPECT_FALSE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
2141 EXPECT_FALSE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
2142 // Socket on eth1 should be bound to link local only.
2143 EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
2144
2145 // If we are on Linux, there is one more socket bound to ff02::1:2
2146 #if defined OS_LINUX
2147 EXPECT_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2148 #endif
2149 }
2150
2151 // This test checks that socket is open on the non-multicast-capable
2152 // interface. This socket simply doesn't join multicast group.
TEST_F(IfaceMgrTest,openSockets6NotMulticast)2153 TEST_F(IfaceMgrTest, openSockets6NotMulticast) {
2154 NakedIfaceMgr ifacemgr;
2155
2156 // Remove all real interfaces and create a set of dummy interfaces.
2157 ifacemgr.createIfaces();
2158
2159 boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
2160 ASSERT_TRUE(filter);
2161 ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
2162
2163 // Make eth0 multicast-incapable.
2164 ifacemgr.getIface("eth0")->flag_multicast_ = false;
2165
2166 // Simulate opening sockets using the dummy packet filter.
2167 bool success = false;
2168 ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
2169 EXPECT_TRUE(success);
2170
2171 // Check that the number of sockets is correct on each interface.
2172 checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
2173 checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
2174 checkSocketsCount6(*ifacemgr.getIface("eth0"), 0);
2175 checkSocketsCount6(*ifacemgr.getIface(ETH0_INDEX), 0);
2176 checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
2177 checkSocketsCount6(*ifacemgr.getIface(ETH1_INDEX), 0);
2178
2179 // Sockets on eth0 should be bound to link-local and should not be bound
2180 // to global unicast address, even though this address is configured on
2181 // the eth0.
2182 EXPECT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
2183 EXPECT_FALSE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
2184 // The eth0 is not a multicast-capable interface, so the socket should
2185 // not be bound to the multicast address.
2186 EXPECT_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2187 // Socket on eth1 should be bound to link local only.
2188 EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
2189
2190 // If we are on Linux, there is one more socket bound to ff02::1:2
2191 // on eth1.
2192 #if defined OS_LINUX
2193 EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2194 #endif
2195 }
2196
2197 // This test checks that the sockets are opened and bound to link local
2198 // and unicast addresses which have been explicitly specified.
TEST_F(IfaceMgrTest,openSockets6Unicast)2199 TEST_F(IfaceMgrTest, openSockets6Unicast) {
2200 NakedIfaceMgr ifacemgr;
2201
2202 // Remove all real interfaces and create a set of dummy interfaces.
2203 ifacemgr.createIfaces();
2204
2205 boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
2206 ASSERT_TRUE(filter);
2207 ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
2208
2209 // Configure the eth0 to open socket on the unicast address, apart
2210 // from link-local address.
2211 ifacemgr.getIface("eth0")->addUnicast(IOAddress("2001:db8:1::1"));
2212
2213 // Simulate opening sockets using the dummy packet filter.
2214 bool success = false;
2215 ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
2216 EXPECT_TRUE(success);
2217
2218 // Check that we have correct number of sockets on each interface.
2219 checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
2220 checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
2221 checkSocketsCount6(*ifacemgr.getIface("eth0"), 1); // one unicast address.
2222 checkSocketsCount6(*ifacemgr.getIface(ETH0_INDEX), 1);
2223 checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
2224 checkSocketsCount6(*ifacemgr.getIface(ETH1_INDEX), 0);
2225
2226 // eth0 should have two sockets, one bound to link-local, another one
2227 // bound to unicast address.
2228 EXPECT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
2229 EXPECT_TRUE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
2230 // eth1 should have one socket, bound to link-local address.
2231 EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
2232
2233 // If we are on Linux, there is one more socket bound to ff02::1:2
2234 #if defined OS_LINUX
2235 EXPECT_TRUE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2236 EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2237 #endif
2238 }
2239
2240 // This test checks that the socket is open and bound to a global unicast
2241 // address if the link-local address does not exist for the particular
2242 // interface.
TEST_F(IfaceMgrTest,openSockets6UnicastOnly)2243 TEST_F(IfaceMgrTest, openSockets6UnicastOnly) {
2244 NakedIfaceMgr ifacemgr;
2245
2246 // Remove all real interfaces and create a set of dummy interfaces.
2247 ifacemgr.createIfaces();
2248
2249 boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
2250 ASSERT_TRUE(filter);
2251 ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
2252
2253 // Configure the eth0 to open socket on the unicast address, apart
2254 // from link-local address.
2255 ifacemgr.getIface("eth0")->addUnicast(IOAddress("2001:db8:1::1"));
2256 // Explicitly remove the link-local address from eth0.
2257 ASSERT_TRUE(ifacemgr.getIface("eth0")->
2258 delAddress(IOAddress("fe80::3a60:77ff:fed5:cdef")));
2259
2260 // Simulate opening sockets using the dummy packet filter.
2261 bool success = false;
2262 ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
2263 EXPECT_TRUE(success);
2264
2265 // Check that we have correct number of sockets on each interface.
2266 checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
2267 checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
2268 checkSocketsCount6(*ifacemgr.getIface("eth0"), 1, 0);
2269 checkSocketsCount6(*ifacemgr.getIface(ETH0_INDEX), 1, 0);
2270 checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
2271 checkSocketsCount6(*ifacemgr.getIface(ETH1_INDEX), 0);
2272
2273 // The link-local address is not present on eth0. Therefore, no socket
2274 // must be bound to this address, nor to multicast address.
2275 EXPECT_FALSE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
2276 EXPECT_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2277 // There should be one socket bound to unicast address.
2278 EXPECT_TRUE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
2279 // eth1 should have one socket, bound to link-local address.
2280 EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
2281
2282 // If we are on Linux, there is one more socket bound to ff02::1:2
2283 #if defined OS_LINUX
2284 EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2285 #endif
2286 }
2287
2288 // This test checks that no sockets are open for the interface which is down.
TEST_F(IfaceMgrTest,openSockets6IfaceDown)2289 TEST_F(IfaceMgrTest, openSockets6IfaceDown) {
2290 NakedIfaceMgr ifacemgr;
2291
2292 // Remove all real interfaces and create a set of dummy interfaces.
2293 ifacemgr.createIfaces();
2294
2295 boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
2296 ASSERT_TRUE(filter);
2297 ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
2298
2299 // Configure the eth0 to open socket on the unicast address, apart
2300 // from link-local address.
2301 ifacemgr.getIface("eth0")->addUnicast(IOAddress("2001:db8:1::1"));
2302
2303 // Boolean parameters specify that eth0 is:
2304 // - not a loopback
2305 // - is "down" (not up)
2306 // - is not running
2307 // - is active for both v4 and v6
2308 ifacemgr.setIfaceFlags("eth0", false, false, false, false, false);
2309
2310 // Install an error handler before trying to open sockets. This handler
2311 // should be called when the IfaceMgr fails to open socket on eth0.
2312 isc::dhcp::IfaceMgrErrorMsgCallback error_handler =
2313 std::bind(&IfaceMgrTest::ifaceMgrErrorHandler, this, ph::_1);
2314
2315 // Simulate opening sockets using the dummy packet filter.
2316 bool success = false;
2317 ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT,
2318 error_handler));
2319 EXPECT_TRUE(success);
2320
2321 // Opening socket on the interface which is not configured, should
2322 // result in error.
2323 EXPECT_EQ(1, errors_count_);
2324
2325 // Check that we have correct number of sockets on each interface.
2326 checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
2327 checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
2328 // There should be no sockets on eth0 because interface is down.
2329 ASSERT_TRUE(ifacemgr.getIface("eth0")->getSockets().empty());
2330 ASSERT_TRUE(ifacemgr.getIface(ETH0_INDEX)->getSockets().empty());
2331 checkSocketsCount6(*ifacemgr.getIface("eth1"), 0);
2332 checkSocketsCount6(*ifacemgr.getIface(ETH1_INDEX), 0);
2333
2334 // eth0 should have no sockets because the interface is down.
2335 EXPECT_FALSE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
2336 EXPECT_FALSE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
2337 EXPECT_FALSE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2338 // eth1 should have one socket, bound to link-local address.
2339 EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
2340
2341 // If we are on Linux, there is one more socket bound to ff02::1:2
2342 #if defined OS_LINUX
2343 EXPECT_TRUE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2344 #endif
2345 }
2346
2347 // This test checks that no sockets are open for the interface which is
2348 // inactive.
TEST_F(IfaceMgrTest,openSockets6IfaceInactive)2349 TEST_F(IfaceMgrTest, openSockets6IfaceInactive) {
2350 NakedIfaceMgr ifacemgr;
2351
2352 // Remove all real interfaces and create a set of dummy interfaces.
2353 ifacemgr.createIfaces();
2354
2355 boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
2356 ASSERT_TRUE(filter);
2357 ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
2358
2359 // Configure the eth0 to open socket on the unicast address, apart
2360 // from link-local address.
2361 ifacemgr.getIface("eth0")->addUnicast(IOAddress("2001:db8:1::1"));
2362
2363 // Boolean parameters specify that eth1 is:
2364 // - not a loopback
2365 // - is up
2366 // - is running
2367 // - is active for v4
2368 // - is inactive for v6
2369 ifacemgr.setIfaceFlags("eth1", false, true, true, false, true);
2370
2371 // Simulate opening sockets using the dummy packet filter.
2372 bool success = false;
2373 ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
2374 EXPECT_TRUE(success);
2375
2376 // Check that we have correct number of sockets on each interface.
2377 checkSocketsCount6(*ifacemgr.getIface("lo"), 0);
2378 checkSocketsCount6(*ifacemgr.getIface(LO_INDEX), 0);
2379 checkSocketsCount6(*ifacemgr.getIface("eth0"), 1); // one unicast address
2380 checkSocketsCount6(*ifacemgr.getIface(ETH0_INDEX), 1);
2381 // There should be no sockets on eth1 because interface is inactive
2382 ASSERT_TRUE(ifacemgr.getIface("eth1")->getSockets().empty());
2383 ASSERT_TRUE(ifacemgr.getIface(ETH1_INDEX)->getSockets().empty());
2384
2385 // eth0 should have one socket bound to a link-local address, another one
2386 // bound to unicast address.
2387 EXPECT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
2388 EXPECT_TRUE(ifacemgr.isBound("eth0", "2001:db8:1::1"));
2389
2390 // eth1 shouldn't have a socket bound to link local address because
2391 // interface is inactive.
2392 EXPECT_FALSE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
2393 EXPECT_FALSE(ifacemgr.isBound("eth1", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2394
2395 // If we are on Linux, there is one more socket bound to ff02::1:2
2396 #if defined OS_LINUX
2397 EXPECT_TRUE(ifacemgr.isBound("eth0", ALL_DHCP_RELAY_AGENTS_AND_SERVERS));
2398 #endif
2399 }
2400
2401 // Test that the openSockets6 function does not throw if there are no interfaces
2402 // detected. This function is expected to return false.
TEST_F(IfaceMgrTest,openSockets6NoIfaces)2403 TEST_F(IfaceMgrTest, openSockets6NoIfaces) {
2404 NakedIfaceMgr ifacemgr;
2405 // Remove existing interfaces.
2406 ifacemgr.getIfacesLst().clear();
2407
2408 boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
2409 ASSERT_TRUE(filter);
2410 ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
2411
2412 // This value indicates if at least one socket opens. There are no
2413 // interfaces, so it should be set to false.
2414 bool socket_open = false;
2415 ASSERT_NO_THROW(socket_open = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
2416 EXPECT_FALSE(socket_open);
2417 }
2418
2419 // Test that the external error handler is called when trying to bind a new
2420 // socket to the address and port being in use. The sockets on the other
2421 // interfaces should open just fine.
TEST_F(IfaceMgrTest,openSocket6ErrorHandler)2422 TEST_F(IfaceMgrTest, openSocket6ErrorHandler) {
2423 NakedIfaceMgr ifacemgr;
2424
2425 // Remove all real interfaces and create a set of dummy interfaces.
2426 ifacemgr.createIfaces();
2427
2428 boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
2429 ASSERT_TRUE(filter);
2430 ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
2431
2432 // Open multicast socket on eth0.
2433 ASSERT_NO_THROW(ifacemgr.openSocket("eth0",
2434 IOAddress("fe80::3a60:77ff:fed5:cdef"),
2435 DHCP6_SERVER_PORT, true));
2436
2437 // Install an error handler before trying to open sockets. This handler
2438 // should be called when the IfaceMgr fails to open socket on eth0.
2439 isc::dhcp::IfaceMgrErrorMsgCallback error_handler =
2440 std::bind(&IfaceMgrTest::ifaceMgrErrorHandler, this, ph::_1);
2441 // The openSockets6 should detect that a socket has been already
2442 // opened on eth0 and an attempt to open another socket and bind to
2443 // the same address and port should fail.
2444 ASSERT_NO_THROW(ifacemgr.openSockets6(DHCP6_SERVER_PORT, error_handler));
2445 // We expect that an error occurred when we tried to open a socket on
2446 // eth0, but the socket on eth1 should open just fine.
2447 EXPECT_EQ(1, errors_count_);
2448
2449 // Reset errors count.
2450 errors_count_ = 0;
2451
2452 // Now that we have two sockets open, we can try this again but this time
2453 // we should get two errors: one when opening a socket on eth0, another one
2454 // when opening a socket on eth1.
2455 ASSERT_NO_THROW(ifacemgr.openSockets6(DHCP6_SERVER_PORT, error_handler));
2456 EXPECT_EQ(2, errors_count_);
2457 }
2458
2459 // This test verifies that the function correctly checks that the v6 socket is
2460 // open and bound to a specific address.
TEST_F(IfaceMgrTest,hasOpenSocketForAddress6)2461 TEST_F(IfaceMgrTest, hasOpenSocketForAddress6) {
2462 NakedIfaceMgr ifacemgr;
2463
2464 // Remove all real interfaces and create a set of dummy interfaces.
2465 ifacemgr.createIfaces();
2466
2467 boost::shared_ptr<PktFilter6Stub> filter(new PktFilter6Stub());
2468 ASSERT_TRUE(filter);
2469 ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
2470
2471 // Simulate opening sockets using the dummy packet filter.
2472 bool success = false;
2473 ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
2474 EXPECT_TRUE(success);
2475
2476 // Make sure that the sockets are bound as expected.
2477 ASSERT_TRUE(ifacemgr.isBound("eth0", "fe80::3a60:77ff:fed5:cdef"));
2478 EXPECT_TRUE(ifacemgr.isBound("eth1", "fe80::3a60:77ff:fed5:abcd"));
2479
2480 // There should be v6 sockets only, no v4 sockets.
2481 EXPECT_TRUE(ifacemgr.hasOpenSocket(AF_INET6));
2482 EXPECT_FALSE(ifacemgr.hasOpenSocket(AF_INET));
2483
2484 // Check that there are sockets bound to the addresses we have configured
2485 // for interfaces.
2486 EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:fed5:cdef")));
2487 EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:fed5:abcd")));
2488 // Check that there is no socket bound to the address which hasn't been
2489 // configured on any interface.
2490 EXPECT_FALSE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:feed:1")));
2491 }
2492
2493 // Test the Iface structure itself
TEST_F(IfaceMgrTest,iface)2494 TEST_F(IfaceMgrTest, iface) {
2495 boost::scoped_ptr<Iface> iface;
2496 EXPECT_NO_THROW(iface.reset(new Iface("eth0",1)));
2497
2498 EXPECT_EQ("eth0", iface->getName());
2499 EXPECT_EQ(1, iface->getIndex());
2500 EXPECT_EQ("eth0/1", iface->getFullName());
2501
2502 // Let's make a copy of this address collection.
2503 Iface::AddressCollection addrs = iface->getAddresses();
2504
2505 EXPECT_EQ(0, addrs.size());
2506
2507 IOAddress addr1("192.0.2.6");
2508 iface->addAddress(addr1);
2509
2510 addrs = iface->getAddresses();
2511 ASSERT_EQ(1, addrs.size());
2512 EXPECT_EQ("192.0.2.6", addrs.begin()->get().toText());
2513
2514 // No such address, should return false.
2515 EXPECT_FALSE(iface->delAddress(IOAddress("192.0.8.9")));
2516
2517 // This address is present, delete it!
2518 EXPECT_TRUE(iface->delAddress(IOAddress("192.0.2.6")));
2519
2520 // Not really necessary, previous reference still points to the same
2521 // collection. Let's do it anyway, as test code may serve as example
2522 // usage code as well.
2523 addrs = iface->getAddresses();
2524
2525 EXPECT_EQ(0, addrs.size());
2526
2527 EXPECT_NO_THROW(iface.reset());
2528 }
2529
TEST_F(IfaceMgrTest,iface_methods)2530 TEST_F(IfaceMgrTest, iface_methods) {
2531 Iface iface("foo", 1234);
2532
2533 iface.setHWType(42);
2534 EXPECT_EQ(42, iface.getHWType());
2535
2536 ASSERT_LT(Iface::MAX_MAC_LEN + 10, 255);
2537
2538 uint8_t mac[Iface::MAX_MAC_LEN+10];
2539 for (uint8_t i = 0; i < Iface::MAX_MAC_LEN + 10; i++) {
2540 mac[i] = 255 - i;
2541 }
2542
2543 EXPECT_EQ("foo", iface.getName());
2544 EXPECT_EQ(1234, iface.getIndex());
2545
2546 // MAC is too long. Exception should be thrown and
2547 // MAC length should not be set.
2548 EXPECT_THROW(
2549 iface.setMac(mac, Iface::MAX_MAC_LEN + 1),
2550 OutOfRange
2551 );
2552
2553 // MAC length should stay not set as exception was thrown.
2554 EXPECT_EQ(0, iface.getMacLen());
2555
2556 // Setting maximum length MAC should be ok.
2557 iface.setMac(mac, Iface::MAX_MAC_LEN);
2558
2559 // For some reason constants cannot be used directly in EXPECT_EQ
2560 // as this produces linking error.
2561 size_t len = Iface::MAX_MAC_LEN;
2562 EXPECT_EQ(len, iface.getMacLen());
2563 EXPECT_EQ(0, memcmp(mac, iface.getMac(), iface.getMacLen()));
2564 }
2565
TEST_F(IfaceMgrTest,socketInfo)2566 TEST_F(IfaceMgrTest, socketInfo) {
2567
2568 // Check that socketinfo for IPv4 socket is functional
2569 SocketInfo sock1(IOAddress("192.0.2.56"), DHCP4_SERVER_PORT + 7, 7);
2570 EXPECT_EQ(7, sock1.sockfd_);
2571 EXPECT_EQ(-1, sock1.fallbackfd_);
2572 EXPECT_EQ("192.0.2.56", sock1.addr_.toText());
2573 EXPECT_EQ(AF_INET, sock1.family_);
2574 EXPECT_EQ(DHCP4_SERVER_PORT + 7, sock1.port_);
2575
2576 // Check that non-default value of the fallback socket descriptor is set
2577 SocketInfo sock2(IOAddress("192.0.2.53"), DHCP4_SERVER_PORT + 8, 8, 10);
2578 EXPECT_EQ(8, sock2.sockfd_);
2579 EXPECT_EQ(10, sock2.fallbackfd_);
2580 EXPECT_EQ("192.0.2.53", sock2.addr_.toText());
2581 EXPECT_EQ(AF_INET, sock2.family_);
2582 EXPECT_EQ(DHCP4_SERVER_PORT + 8, sock2.port_);
2583
2584 // Check that socketinfo for IPv6 socket is functional
2585 SocketInfo sock3(IOAddress("2001:db8:1::56"), DHCP4_SERVER_PORT + 9, 9);
2586 EXPECT_EQ(9, sock3.sockfd_);
2587 EXPECT_EQ(-1, sock3.fallbackfd_);
2588 EXPECT_EQ("2001:db8:1::56", sock3.addr_.toText());
2589 EXPECT_EQ(AF_INET6, sock3.family_);
2590 EXPECT_EQ(DHCP4_SERVER_PORT + 9, sock3.port_);
2591
2592 // Now let's test if IfaceMgr handles socket info properly
2593 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
2594 IfacePtr loopback = ifacemgr->getIface(LOOPBACK_NAME);
2595 ASSERT_TRUE(loopback);
2596 loopback->addSocket(sock1);
2597 loopback->addSocket(sock2);
2598 loopback->addSocket(sock3);
2599
2600 Pkt6Ptr pkt6(new Pkt6(DHCPV6_REPLY, 123456));
2601
2602 // pkt6 does not have interface set yet
2603 EXPECT_THROW(
2604 ifacemgr->getSocket(pkt6),
2605 IfaceNotFound
2606 );
2607
2608 // Try to send over non-existing interface
2609 pkt6->setIface("nosuchinterface45");
2610 pkt6->setIndex(12345);
2611 EXPECT_THROW(
2612 ifacemgr->getSocket(pkt6),
2613 IfaceNotFound
2614 );
2615
2616 // Index is now checked first
2617 pkt6->setIface(LOOPBACK_NAME);
2618 EXPECT_THROW(
2619 ifacemgr->getSocket(pkt6),
2620 IfaceNotFound
2621 );
2622
2623 // This will work
2624 pkt6->setIndex(LOOPBACK_INDEX);
2625 EXPECT_EQ(9, ifacemgr->getSocket(pkt6));
2626
2627 bool deleted = false;
2628 EXPECT_NO_THROW(
2629 deleted = ifacemgr->getIface(LOOPBACK_NAME)->delSocket(9);
2630 );
2631 EXPECT_EQ(true, deleted);
2632
2633 // It should throw again, there's no usable socket anymore
2634 EXPECT_THROW(
2635 ifacemgr->getSocket(pkt6),
2636 SocketNotFound
2637 );
2638
2639 // Repeat for pkt4
2640 Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 1));
2641
2642 // pkt4 does not have interface set yet.
2643 EXPECT_THROW(
2644 ifacemgr->getSocket(pkt4),
2645 IfaceNotFound
2646 );
2647
2648 // Try to send over non-existing interface.
2649 pkt4->setIface("nosuchinterface45");
2650 pkt4->setIndex(12345);
2651 EXPECT_THROW(
2652 ifacemgr->getSocket(pkt4),
2653 IfaceNotFound
2654 );
2655
2656 // Index is now checked first.
2657 pkt4->setIface(LOOPBACK_NAME);
2658 EXPECT_THROW(
2659 ifacemgr->getSocket(pkt4),
2660 IfaceNotFound
2661 );
2662
2663 // Socket info is set, packet has well defined interface. It should work.
2664 pkt4->setIndex(LOOPBACK_INDEX);
2665 EXPECT_EQ(7, ifacemgr->getSocket(pkt4).sockfd_);
2666
2667 // Set the local address to check if the socket for this address will
2668 // be returned.
2669 pkt4->setLocalAddr(IOAddress("192.0.2.56"));
2670 EXPECT_EQ(7, ifacemgr->getSocket(pkt4).sockfd_);
2671
2672 // Modify the local address and expect that the other socket will be
2673 // returned.
2674 pkt4->setLocalAddr(IOAddress("192.0.2.53"));
2675 EXPECT_EQ(8, ifacemgr->getSocket(pkt4).sockfd_);
2676
2677 EXPECT_NO_THROW(
2678 ifacemgr->getIface(LOOPBACK_NAME)->delSocket(7);
2679 ifacemgr->getIface(LOOPBACK_NAME)->delSocket(8);
2680 );
2681
2682 // It should throw again, there's no usable socket anymore.
2683 EXPECT_THROW(
2684 ifacemgr->getSocket(pkt4),
2685 SocketNotFound
2686 );
2687 }
2688
2689 #if defined(OS_BSD)
2690 #include <net/if_dl.h>
2691 #endif
2692
2693 #include <sys/socket.h>
2694 #include <net/if.h>
2695 #include <ifaddrs.h>
2696
2697 /// @brief Checks the index of this interface
2698 /// @param iface Kea interface structure to be checked
2699 /// @param ifptr original structure returned by getifaddrs
2700 /// @return true if index is returned properly
2701 bool
checkIfIndex(const Iface & iface,struct ifaddrs * & ifptr)2702 checkIfIndex(const Iface & iface,
2703 struct ifaddrs *& ifptr) {
2704 return (iface.getIndex() == if_nametoindex(ifptr->ifa_name));
2705 }
2706
2707 /// @brief Checks if the interface has proper flags set
2708 /// @param iface Kea interface structure to be checked
2709 /// @param ifptr original structure returned by getifaddrs
2710 /// @return true if flags are set properly
2711 bool
checkIfFlags(const Iface & iface,struct ifaddrs * & ifptr)2712 checkIfFlags(const Iface & iface,
2713 struct ifaddrs *& ifptr) {
2714 bool flag_loopback_ = ifptr->ifa_flags & IFF_LOOPBACK;
2715 bool flag_up_ = ifptr->ifa_flags & IFF_UP;
2716 bool flag_running_ = ifptr->ifa_flags & IFF_RUNNING;
2717 bool flag_multicast_ = ifptr->ifa_flags & IFF_MULTICAST;
2718
2719 return ((iface.flag_loopback_ == flag_loopback_) &&
2720 (iface.flag_up_ == flag_up_) &&
2721 (iface.flag_running_ == flag_running_) &&
2722 (iface.flag_multicast_ == flag_multicast_));
2723 }
2724
2725 /// @brief Checks if MAC Address/IP Addresses are properly well formed
2726 /// @param iface Kea interface structure to be checked
2727 /// @param ifptr original structure returned by getifaddrs
2728 /// @return true if addresses are returned properly
2729 bool
checkIfAddrs(const Iface & iface,struct ifaddrs * & ifptr)2730 checkIfAddrs(const Iface & iface, struct ifaddrs *& ifptr) {
2731 const unsigned char * p = 0;
2732 #if defined(OS_LINUX)
2733 // Workaround for Linux ...
2734 if(ifptr->ifa_data != 0) {
2735 // We avoid localhost as it has no MAC Address
2736 if (!strncmp(iface.getName().c_str(), "lo", 2)) {
2737 return (true);
2738 }
2739
2740 struct ifreq ifr;
2741 memset(& ifr.ifr_name, 0, sizeof ifr.ifr_name);
2742 strncpy(ifr.ifr_name, iface.getName().c_str(), sizeof(ifr.ifr_name) - 1);
2743
2744 int s = -1; // Socket descriptor
2745
2746 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
2747 isc_throw(Unexpected, "Cannot create AF_INET socket");
2748 }
2749
2750 if (ioctl(s, SIOCGIFHWADDR, & ifr) < 0) {
2751 close(s);
2752 isc_throw(Unexpected, "Cannot set SIOCGIFHWADDR flag");
2753 }
2754
2755 const uint8_t * p =
2756 reinterpret_cast<uint8_t *>(ifr.ifr_ifru.ifru_hwaddr.sa_data);
2757
2758 close(s);
2759
2760 /// @todo: Check MAC address length. For some interfaces it is
2761 /// different than 6. Some have 0, while some exotic ones (like
2762 /// infiniband) have 20.
2763 return (!memcmp(p, iface.getMac(), iface.getMacLen()));
2764 }
2765 #endif
2766
2767 if(!ifptr->ifa_addr) {
2768 return (false);
2769 }
2770
2771 switch(ifptr->ifa_addr->sa_family) {
2772 #if defined(OS_BSD)
2773 case AF_LINK: {
2774 // We avoid localhost as it has no MAC Address
2775 if (!strncmp(iface.getName().c_str(), "lo", 2)) {
2776 return (true);
2777 }
2778
2779 struct sockaddr_dl * hwdata =
2780 reinterpret_cast<struct sockaddr_dl *>(ifptr->ifa_addr);
2781 p = reinterpret_cast<uint8_t *>(LLADDR(hwdata));
2782
2783 // Extract MAC address length
2784 if (hwdata->sdl_alen != iface.getMacLen()) {
2785 return (false);
2786 }
2787
2788 return (!memcmp(p, iface.getMac(), hwdata->sdl_alen));
2789 }
2790 #endif
2791 case AF_INET: {
2792 struct sockaddr_in * v4data =
2793 reinterpret_cast<struct sockaddr_in *>(ifptr->ifa_addr);
2794 p = reinterpret_cast<uint8_t *>(& v4data->sin_addr);
2795
2796 IOAddress addrv4 = IOAddress::fromBytes(AF_INET, p);
2797
2798 BOOST_FOREACH(Iface::Address a, iface.getAddresses()) {
2799 if(a.get().isV4() && (a.get()) == addrv4) {
2800 return (true);
2801 }
2802 }
2803
2804 return (false);
2805 }
2806 case AF_INET6: {
2807 struct sockaddr_in6 * v6data =
2808 reinterpret_cast<struct sockaddr_in6 *>(ifptr->ifa_addr);
2809 p = reinterpret_cast<uint8_t *>(& v6data->sin6_addr);
2810
2811 IOAddress addrv6 = IOAddress::fromBytes(AF_INET6, p);
2812
2813 BOOST_FOREACH(Iface::Address a, iface.getAddresses()) {
2814 if (a.get().isV6() && (a.get() == addrv6)) {
2815 return (true);
2816 }
2817 }
2818
2819 return (false);
2820 }
2821 default:
2822 return (true);
2823 }
2824 }
2825
2826 /// This test checks that the IfaceMgr detects interfaces correctly and
2827 /// that detected interfaces have correct properties.
TEST_F(IfaceMgrTest,detectIfaces)2828 TEST_F(IfaceMgrTest, detectIfaces) {
2829 NakedIfaceMgr ifacemgr;
2830
2831 // We are using struct ifaddrs as it is the only good portable one
2832 // ifreq and ioctls are far from portable. For BSD ifreq::ifa_flags field
2833 // is only a short which, nowadays, can be negative
2834 struct ifaddrs *iflist = 0, *ifptr = 0;
2835 ASSERT_EQ(0, getifaddrs(&iflist))
2836 << "Unit test failed to detect interfaces.";
2837
2838 // Go over all interfaces detected by the unit test and see if they
2839 // match with the interfaces detected by IfaceMgr.
2840 for (ifptr = iflist; ifptr != 0; ifptr = ifptr->ifa_next) {
2841 // When more than one IPv4 address is assigned to the particular
2842 // physical interface, virtual interfaces may be created for each
2843 // additional IPv4 address. For example, when multiple addresses
2844 // are assigned to the eth0 interface, additional virtual interfaces
2845 // will be eth0:0, eth0:1 etc. This is the case on some Linux
2846 // distributions. The getifaddrs will return virtual interfaces,
2847 // with single address each, but the Netlink-based implementation
2848 // (used by IfaceMgr) will rather hold a list of physical interfaces
2849 // with multiple IPv4 addresses assigned. This means that the test
2850 // can't use a name of the interface returned by getifaddrs to match
2851 // with the interface name held by IfaceMgr. Instead, we use the
2852 // index of the interface because the virtual interfaces have the
2853 // same indexes as the physical interfaces.
2854 IfacePtr i = ifacemgr.getIface(if_nametoindex(ifptr->ifa_name));
2855
2856 // If the given interface was also detected by the IfaceMgr,
2857 // check that its properties are correct.
2858 if (i != NULL) {
2859 // Check if interface index is reported properly
2860 EXPECT_TRUE(checkIfIndex(*i, ifptr))
2861 << "Non-matching index of the detected interface "
2862 << i->getName();
2863
2864 // Check if flags are reported properly
2865 EXPECT_TRUE(checkIfFlags(*i, ifptr))
2866 << "Non-matching flags of the detected interface "
2867 << i->getName();
2868
2869 // Check if addresses are reported properly
2870 EXPECT_TRUE(checkIfAddrs(*i, ifptr))
2871 << "Non-matching addresses on the detected interface "
2872 << i->getName();
2873
2874 } else {
2875 // The interface detected here seems to be missing in the
2876 // IfaceMgr.
2877 ADD_FAILURE() << "Interface " << ifptr->ifa_name
2878 << " not detected by the Interface Manager";
2879 }
2880 }
2881
2882 freeifaddrs(iflist);
2883 iflist = 0;
2884 }
2885
2886 volatile bool callback_ok;
2887 volatile bool callback2_ok;
2888
my_callback(int)2889 void my_callback(int /* fd */) {
2890 callback_ok = true;
2891 }
2892
my_callback2(int)2893 void my_callback2(int /* fd */) {
2894 callback2_ok = true;
2895 }
2896
2897 // Tests if a single external socket and its callback can be passed and
2898 // it is supported properly by receive4() method.
TEST_F(IfaceMgrTest,SingleExternalSocket4)2899 TEST_F(IfaceMgrTest, SingleExternalSocket4) {
2900
2901 callback_ok = false;
2902
2903 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
2904
2905 // Create pipe and register it as extra socket
2906 int pipefd[2];
2907 EXPECT_TRUE(pipe(pipefd) == 0);
2908 EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));
2909
2910 ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));
2911
2912 Pkt4Ptr pkt4;
2913 ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
2914
2915 // Our callback should not be called this time (there was no data)
2916 EXPECT_FALSE(callback_ok);
2917
2918 // IfaceMgr should not process control socket data as incoming packets
2919 EXPECT_FALSE(pkt4);
2920
2921 // Now, send some data over pipe (38 bytes)
2922 EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));
2923
2924 // ... and repeat
2925 ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
2926
2927 // IfaceMgr should not process control socket data as incoming packets
2928 EXPECT_FALSE(pkt4);
2929
2930 // There was some data, so this time callback should be called
2931 EXPECT_TRUE(callback_ok);
2932
2933 // close both pipe ends
2934 close(pipefd[1]);
2935 close(pipefd[0]);
2936
2937 ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
2938 }
2939
2940 // Tests if multiple external sockets and their callbacks can be passed and
2941 // it is supported properly by receive4() method.
TEST_F(IfaceMgrTest,MultipleExternalSockets4)2942 TEST_F(IfaceMgrTest, MultipleExternalSockets4) {
2943
2944 callback_ok = false;
2945 callback2_ok = false;
2946
2947 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
2948
2949 // Create first pipe and register it as extra socket
2950 int pipefd[2];
2951 EXPECT_TRUE(pipe(pipefd) == 0);
2952 EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));
2953
2954 // Let's create a second pipe and register it as well
2955 int secondpipe[2];
2956 EXPECT_TRUE(pipe(secondpipe) == 0);
2957 EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0], my_callback2));
2958
2959 Pkt4Ptr pkt4;
2960 ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
2961
2962 // Our callbacks should not be called this time (there was no data)
2963 EXPECT_FALSE(callback_ok);
2964 EXPECT_FALSE(callback2_ok);
2965
2966 // IfaceMgr should not process control socket data as incoming packets
2967 EXPECT_FALSE(pkt4);
2968
2969 // Now, send some data over the first pipe (38 bytes)
2970 EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));
2971
2972 // ... and repeat
2973 ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
2974
2975 // IfaceMgr should not process control socket data as incoming packets
2976 EXPECT_FALSE(pkt4);
2977
2978 // There was some data, so this time callback should be called
2979 EXPECT_TRUE(callback_ok);
2980 EXPECT_FALSE(callback2_ok);
2981
2982 // Read the data sent, because our test callbacks are too dumb to actually
2983 // do it. We don't care about the content read, because we're testing
2984 // the callbacks, not pipes.
2985 char buf[80];
2986 EXPECT_EQ(38, read(pipefd[0], buf, 80));
2987
2988 // Clear the status...
2989 callback_ok = false;
2990 callback2_ok = false;
2991
2992 // And try again, using the second pipe
2993 EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));
2994
2995 // ... and repeat
2996 ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
2997
2998 // IfaceMgr should not process control socket data as incoming packets
2999 EXPECT_FALSE(pkt4);
3000
3001 // There was some data, so this time callback should be called
3002 EXPECT_FALSE(callback_ok);
3003 EXPECT_TRUE(callback2_ok);
3004
3005 // close both pipe ends
3006 close(pipefd[1]);
3007 close(pipefd[0]);
3008
3009 close(secondpipe[1]);
3010 close(secondpipe[0]);
3011 }
3012
3013 // Tests if existing external socket can be deleted and that such deletion does
3014 // not affect any other existing sockets. Tests uses receive4()
TEST_F(IfaceMgrTest,DeleteExternalSockets4)3015 TEST_F(IfaceMgrTest, DeleteExternalSockets4) {
3016
3017 callback_ok = false;
3018 callback2_ok = false;
3019
3020 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
3021
3022 // Create first pipe and register it as extra socket
3023 int pipefd[2];
3024 EXPECT_TRUE(pipe(pipefd) == 0);
3025 EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));
3026
3027 // Let's create a second pipe and register it as well
3028 int secondpipe[2];
3029 EXPECT_TRUE(pipe(secondpipe) == 0);
3030 EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0], my_callback2));
3031
3032 // Now delete the first session socket
3033 EXPECT_NO_THROW(ifacemgr->deleteExternalSocket(pipefd[0]));
3034
3035 // Now check whether the second callback is still functional
3036 EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));
3037
3038 // ... and repeat
3039 Pkt4Ptr pkt4;
3040 ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
3041
3042 // IfaceMgr should not process control socket data as incoming packets
3043 EXPECT_FALSE(pkt4);
3044
3045 // There was some data, so this time callback should be called
3046 EXPECT_FALSE(callback_ok);
3047 EXPECT_TRUE(callback2_ok);
3048
3049 // Let's reset the status
3050 callback_ok = false;
3051 callback2_ok = false;
3052
3053 // Now let's send something over the first callback that was unregistered.
3054 // We should NOT receive any callback.
3055 EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));
3056
3057 // Now check that the first callback is NOT called.
3058 ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
3059 EXPECT_FALSE(callback_ok);
3060
3061 // close both pipe ends
3062 close(pipefd[1]);
3063 close(pipefd[0]);
3064
3065 close(secondpipe[1]);
3066 close(secondpipe[0]);
3067 }
3068
3069 // Tests that an existing external socket that becomes invalid
3070 // is detected and purged, without affecting other sockets.
3071 // Tests uses receive4() without queuing.
TEST_F(IfaceMgrTest,purgeExternalSockets4Direct)3072 TEST_F(IfaceMgrTest, purgeExternalSockets4Direct) {
3073 purgeExternalSockets4Test();
3074 }
3075
3076
3077 // Tests that an existing external socket that becomes invalid
3078 // is detected and purged, without affecting other sockets.
3079 // Tests uses receive4() with queuing.
TEST_F(IfaceMgrTest,purgeExternalSockets4Indirect)3080 TEST_F(IfaceMgrTest, purgeExternalSockets4Indirect) {
3081 purgeExternalSockets4Test(true);
3082 }
3083
3084 // Tests if a single external socket and its callback can be passed and
3085 // it is supported properly by receive6() method.
TEST_F(IfaceMgrTest,SingleExternalSocket6)3086 TEST_F(IfaceMgrTest, SingleExternalSocket6) {
3087
3088 callback_ok = false;
3089
3090 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
3091
3092 // Create pipe and register it as extra socket
3093 int pipefd[2];
3094 EXPECT_TRUE(pipe(pipefd) == 0);
3095 EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));
3096
3097 Pkt6Ptr pkt6;
3098 ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
3099
3100 // Our callback should not be called this time (there was no data)
3101 EXPECT_FALSE(callback_ok);
3102
3103 // IfaceMgr should not process control socket data as incoming packets
3104 EXPECT_FALSE(pkt6);
3105
3106 // Now, send some data over pipe (38 bytes)
3107 EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));
3108
3109 // ... and repeat
3110 ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
3111
3112 // IfaceMgr should not process control socket data as incoming packets
3113 EXPECT_FALSE(pkt6);
3114
3115 // There was some data, so this time callback should be called
3116 EXPECT_TRUE(callback_ok);
3117
3118 // close both pipe ends
3119 close(pipefd[1]);
3120 close(pipefd[0]);
3121 }
3122
3123 // Tests if multiple external sockets and their callbacks can be passed and
3124 // it is supported properly by receive6() method.
TEST_F(IfaceMgrTest,MultipleExternalSockets6)3125 TEST_F(IfaceMgrTest, MultipleExternalSockets6) {
3126
3127 callback_ok = false;
3128 callback2_ok = false;
3129
3130 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
3131
3132 // Create first pipe and register it as extra socket
3133 int pipefd[2];
3134 EXPECT_TRUE(pipe(pipefd) == 0);
3135 EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));
3136
3137 // Let's create a second pipe and register it as well
3138 int secondpipe[2];
3139 EXPECT_TRUE(pipe(secondpipe) == 0);
3140 EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0], my_callback2));
3141
3142 Pkt6Ptr pkt6;
3143 ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
3144
3145 // Our callbacks should not be called this time (there was no data)
3146 EXPECT_FALSE(callback_ok);
3147 EXPECT_FALSE(callback2_ok);
3148
3149 // IfaceMgr should not process control socket data as incoming packets
3150 EXPECT_FALSE(pkt6);
3151
3152 // Now, send some data over the first pipe (38 bytes)
3153 EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));
3154
3155 // ... and repeat
3156 ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
3157
3158 // IfaceMgr should not process control socket data as incoming packets
3159 EXPECT_FALSE(pkt6);
3160
3161 // There was some data, so this time callback should be called
3162 EXPECT_TRUE(callback_ok);
3163 EXPECT_FALSE(callback2_ok);
3164
3165 // Read the data sent, because our test callbacks are too dumb to actually
3166 // do it. We don't care about the content read, because we're testing
3167 // the callbacks, not pipes.
3168 char buf[80];
3169 EXPECT_EQ(38, read(pipefd[0], buf, 80));
3170
3171 // Clear the status...
3172 callback_ok = false;
3173 callback2_ok = false;
3174
3175 // And try again, using the second pipe
3176 EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));
3177
3178 // ... and repeat
3179 ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
3180
3181 // IfaceMgr should not process control socket data as incoming packets
3182 EXPECT_FALSE(pkt6);
3183
3184 // There was some data, so this time callback should be called
3185 EXPECT_FALSE(callback_ok);
3186 EXPECT_TRUE(callback2_ok);
3187
3188 // close both pipe ends
3189 close(pipefd[1]);
3190 close(pipefd[0]);
3191
3192 close(secondpipe[1]);
3193 close(secondpipe[0]);
3194 }
3195
3196 // Tests if existing external socket can be deleted and that such deletion does
3197 // not affect any other existing sockets. Tests uses receive6()
TEST_F(IfaceMgrTest,DeleteExternalSockets6)3198 TEST_F(IfaceMgrTest, DeleteExternalSockets6) {
3199
3200 callback_ok = false;
3201 callback2_ok = false;
3202
3203 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
3204
3205 // Create first pipe and register it as extra socket
3206 int pipefd[2];
3207 EXPECT_TRUE(pipe(pipefd) == 0);
3208 EXPECT_NO_THROW(ifacemgr->addExternalSocket(pipefd[0], my_callback));
3209
3210 // Let's create a second pipe and register it as well
3211 int secondpipe[2];
3212 EXPECT_TRUE(pipe(secondpipe) == 0);
3213 EXPECT_NO_THROW(ifacemgr->addExternalSocket(secondpipe[0], my_callback2));
3214
3215 // Now delete the first session socket
3216 EXPECT_NO_THROW(ifacemgr->deleteExternalSocket(pipefd[0]));
3217
3218 // Now check whether the second callback is still functional
3219 EXPECT_EQ(38, write(secondpipe[1], "Hi, this is a message sent over a pipe", 38));
3220
3221 // ... and repeat
3222 Pkt6Ptr pkt6;
3223 ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
3224
3225 // IfaceMgr should not process control socket data as incoming packets
3226 EXPECT_FALSE(pkt6);
3227
3228 // There was some data, so this time callback should be called
3229 EXPECT_FALSE(callback_ok);
3230 EXPECT_TRUE(callback2_ok);
3231
3232 // Let's reset the status
3233 callback_ok = false;
3234 callback2_ok = false;
3235
3236 // Now let's send something over the first callback that was unregistered.
3237 // We should NOT receive any callback.
3238 EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));
3239
3240 // Now check that the first callback is NOT called.
3241 ASSERT_NO_THROW(pkt6 = ifacemgr->receive6(1));
3242 EXPECT_FALSE(callback_ok);
3243
3244 // close both pipe ends
3245 close(pipefd[1]);
3246 close(pipefd[0]);
3247
3248 close(secondpipe[1]);
3249 close(secondpipe[0]);
3250 }
3251
3252 // Tests that an existing external socket that becomes invalid
3253 // is detected and purged, without affecting other sockets.
3254 // Tests uses receive6() without queuing.
TEST_F(IfaceMgrTest,purgeExternalSockets6Direct)3255 TEST_F(IfaceMgrTest, purgeExternalSockets6Direct) {
3256 purgeExternalSockets6Test();
3257 }
3258
3259
3260 // Tests that an existing external socket that becomes invalid
3261 // is detected and purged, without affecting other sockets.
3262 // Tests uses receive6() with queuing.
TEST_F(IfaceMgrTest,purgeExternalSockets6Indirect)3263 TEST_F(IfaceMgrTest, purgeExternalSockets6Indirect) {
3264 purgeExternalSockets6Test(true);
3265 }
3266
3267 // Test checks if the unicast sockets can be opened.
3268 // This test is now disabled, because there is no reliable way to test it. We
3269 // can't even use loopback, because openSockets() skips loopback interface
3270 // (as it should be, because DHCP server is not supposed to listen on loopback).
TEST_F(IfaceMgrTest,DISABLED_openUnicastSockets)3271 TEST_F(IfaceMgrTest, DISABLED_openUnicastSockets) {
3272 /// @todo Need to implement a test that is able to check whether we can open
3273 /// unicast sockets. There are 2 problems with it:
3274 /// 1. We need to have a non-link-local address on an interface that is
3275 /// up, running, IPv6 and multicast capable
3276 /// 2. We need that information on every OS that we run tests on. So far
3277 /// we are only supporting interface detection in Linux.
3278 ///
3279 /// To achieve this, we will probably need a pre-test setup, similar to what
3280 /// BIND9 is doing (i.e. configuring well known addresses on loopback).
3281
3282 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
3283
3284 // Get the interface (todo: which interface)
3285 IfacePtr iface = ifacemgr->getIface("eth0");
3286 ASSERT_TRUE(iface);
3287 iface->inactive6_ = false;
3288
3289 // Tell the interface that it should bind to this global interface
3290 EXPECT_NO_THROW(iface->addUnicast(IOAddress("2001:db8::1")));
3291
3292 // Tell IfaceMgr to open sockets. This should trigger at least 2 sockets
3293 // to open on eth0: link-local and global. On some systems (Linux), an
3294 // additional socket for multicast may be opened.
3295 EXPECT_TRUE(ifacemgr->openSockets6(PORT1));
3296
3297 const Iface::SocketCollection& sockets = iface->getSockets();
3298 ASSERT_GE(2, sockets.size());
3299
3300 // Global unicast should be first
3301 EXPECT_TRUE(getSocketByAddr(sockets, IOAddress("2001:db8::1")));
3302 EXPECT_TRUE(getSocketByAddr(sockets, IOAddress("figure-out-link-local-addr")));
3303 }
3304
3305 // Checks if there is a protection against unicast duplicates.
TEST_F(IfaceMgrTest,unicastDuplicates)3306 TEST_F(IfaceMgrTest, unicastDuplicates) {
3307 NakedIfaceMgr ifacemgr;
3308
3309 IfacePtr iface = ifacemgr.getIface(LOOPBACK_NAME);
3310 if (!iface) {
3311 cout << "Local loopback interface not found. Skipping test. " << endl;
3312 return;
3313 }
3314
3315 // Tell the interface that it should bind to this global interface
3316 // It is the first attempt so it should succeed
3317 EXPECT_NO_THROW(iface->addUnicast(IOAddress("2001:db8::1")));
3318
3319 // Tell the interface that it should bind to this global interface
3320 // It is the second attempt so it should fail
3321 EXPECT_THROW(iface->addUnicast(IOAddress("2001:db8::1")), BadValue);
3322 }
3323
3324 // This test requires addresses 2001:db8:15c::1/128 and fe80::1/64 to be
3325 // configured on loopback interface
3326 //
3327 // Useful commands:
3328 // ip a a 2001:db8:15c::1/128 dev lo
3329 // ip a a fe80::1/64 dev lo
3330 //
3331 // If you do not issue those commands before running this test, it will fail.
TEST_F(IfaceMgrTest,DISABLED_getSocket)3332 TEST_F(IfaceMgrTest, DISABLED_getSocket) {
3333 // Testing socket operation in a portable way is tricky
3334 // without interface detection implemented.
3335
3336 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
3337
3338 IOAddress lo_addr("::1");
3339 IOAddress link_local("fe80::1");
3340 IOAddress global("2001:db8:15c::1");
3341
3342 IOAddress dst_link_local("fe80::dead:beef");
3343 IOAddress dst_global("2001:db8:15c::dead:beef");
3344
3345 // Bind loopback address
3346 int socket1 = ifacemgr->openSocket(LOOPBACK_NAME, lo_addr, 10547);
3347 EXPECT_GE(socket1, 0); // socket >= 0
3348
3349 // Bind link-local address
3350 int socket2 = ifacemgr->openSocket(LOOPBACK_NAME, link_local, 10547);
3351 EXPECT_GE(socket2, 0);
3352
3353 int socket3 = ifacemgr->openSocket(LOOPBACK_NAME, global, 10547);
3354 EXPECT_GE(socket3, 0);
3355
3356 // Let's make sure those sockets are unique
3357 EXPECT_NE(socket1, socket2);
3358 EXPECT_NE(socket2, socket3);
3359 EXPECT_NE(socket3, socket1);
3360
3361 // Create a packet
3362 Pkt6Ptr pkt6(new Pkt6(DHCPV6_SOLICIT, 123));
3363 pkt6->setIface(LOOPBACK_NAME);
3364 pkt6->setIndex(LOOPBACK_INDEX);
3365
3366 // Check that packets sent to link-local will get socket bound to link local
3367 pkt6->setLocalAddr(global);
3368 pkt6->setRemoteAddr(dst_global);
3369 EXPECT_EQ(socket3, ifacemgr->getSocket(pkt6));
3370
3371 // Check that packets sent to link-local will get socket bound to link local
3372 pkt6->setLocalAddr(link_local);
3373 pkt6->setRemoteAddr(dst_link_local);
3374 EXPECT_EQ(socket2, ifacemgr->getSocket(pkt6));
3375
3376 // Close sockets here because the following tests will want to
3377 // open sockets on the same ports.
3378 ifacemgr->closeSockets();
3379 }
3380
3381 // Verifies DHCPv4 behavior of configureDHCPPacketQueue()
TEST_F(IfaceMgrTest,configureDHCPPacketQueueTest4)3382 TEST_F(IfaceMgrTest, configureDHCPPacketQueueTest4) {
3383 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
3384
3385 // First let's make sure there is no queue and no thread.
3386 ASSERT_FALSE(ifacemgr->getPacketQueue4());
3387 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3388
3389 bool queue_enabled = false;
3390 // Given an empty pointer, we should default to no queue.
3391 data::ConstElementPtr queue_control;
3392 ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control));
3393 EXPECT_FALSE(queue_enabled);
3394 EXPECT_FALSE(ifacemgr->getPacketQueue4());
3395 // configureDHCPPacketQueue() should never start the thread.
3396 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3397
3398 // Verify that calling startDHCPReceiver with no queue, does NOT start the thread.
3399 ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));
3400 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3401
3402 // Now let's try with a populated queue control, but with enable-queue = false.
3403 queue_control = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500, false);
3404 ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control));
3405 EXPECT_FALSE(queue_enabled);
3406 EXPECT_FALSE(ifacemgr->getPacketQueue4());
3407 // configureDHCPPacketQueue() should never start the thread.
3408 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3409
3410 // Now let's enable the queue.
3411 queue_control = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500, true);
3412 ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control));
3413 ASSERT_TRUE(queue_enabled);
3414 // Verify we have correctly created the queue.
3415 CHECK_QUEUE_INFO(ifacemgr->getPacketQueue4(), "{ \"capacity\": 500, \"queue-type\": \""
3416 << PacketQueueMgr4::DEFAULT_QUEUE_TYPE4 << "\", \"size\": 0 }");
3417 // configureDHCPPacketQueue() should never start the thread.
3418 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3419
3420 // Calling startDHCPReceiver with a queue, should start the thread.
3421 ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));
3422 ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
3423
3424 // Verify that calling startDHCPReceiver when the thread is running, throws.
3425 ASSERT_THROW(ifacemgr->startDHCPReceiver(AF_INET), InvalidOperation);
3426
3427 // Create a disabled config.
3428 queue_control = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500, false);
3429
3430 // Trying to reconfigure with a running thread should throw.
3431 ASSERT_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control),
3432 InvalidOperation);
3433
3434 // We should still have our queue and the thread should still be running.
3435 EXPECT_TRUE(ifacemgr->getPacketQueue4());
3436 ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
3437
3438 // Now let's stop stop the thread.
3439 ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
3440 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3441 // Stopping the thread should not destroy the queue.
3442 ASSERT_TRUE(ifacemgr->getPacketQueue4());
3443
3444 // Reconfigure with the queue turned off. We should have neither queue nor thread.
3445 ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control));
3446 EXPECT_FALSE(ifacemgr->getPacketQueue4());
3447 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3448 }
3449
3450 // Verifies DHCPv6 behavior of configureDHCPPacketQueue()
TEST_F(IfaceMgrTest,configureDHCPPacketQueueTest6)3451 TEST_F(IfaceMgrTest, configureDHCPPacketQueueTest6) {
3452 scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
3453
3454 // First let's make sure there is no queue and no thread.
3455 ASSERT_FALSE(ifacemgr->getPacketQueue6());
3456 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3457
3458 bool queue_enabled = false;
3459 // Given an empty pointer, we should default to no queue.
3460 data::ConstElementPtr queue_control;
3461 ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control));
3462 EXPECT_FALSE(queue_enabled);
3463 EXPECT_FALSE(ifacemgr->getPacketQueue6());
3464 // configureDHCPPacketQueue() should never start the thread.
3465 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3466
3467 // Verify that calling startDHCPReceiver with no queue, does NOT start the thread.
3468 ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET));
3469 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3470
3471 // Now let's try with a populated queue control, but with enable-queue = false.
3472 queue_control = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500, false);
3473 ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, queue_control));
3474 EXPECT_FALSE(queue_enabled);
3475 EXPECT_FALSE(ifacemgr->getPacketQueue6());
3476 // configureDHCPPacketQueue() should never start the thread.
3477 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3478
3479 // Now let's enable the queue.
3480 queue_control = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500, true);
3481 ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, queue_control));
3482 ASSERT_TRUE(queue_enabled);
3483 // Verify we have correctly created the queue.
3484 CHECK_QUEUE_INFO(ifacemgr->getPacketQueue6(), "{ \"capacity\": 500, \"queue-type\": \""
3485 << PacketQueueMgr6::DEFAULT_QUEUE_TYPE6 << "\", \"size\": 0 }");
3486 // configureDHCPPacketQueue() should never start the thread.
3487 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3488
3489 // Calling startDHCPReceiver with a queue, should start the thread.
3490 ASSERT_NO_THROW(ifacemgr->startDHCPReceiver(AF_INET6));
3491 ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
3492
3493 // Verify that calling startDHCPReceiver when the thread is running, throws.
3494 ASSERT_THROW(ifacemgr->startDHCPReceiver(AF_INET6), InvalidOperation);
3495
3496 // Create a disabled config.
3497 queue_control = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500, false);
3498
3499 // Trying to reconfigure with a running thread should throw.
3500 ASSERT_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, queue_control),
3501 InvalidOperation);
3502
3503 // We should still have our queue and the thread should still be running.
3504 EXPECT_TRUE(ifacemgr->getPacketQueue6());
3505 ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
3506
3507 // Now let's stop stop the thread.
3508 ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
3509 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3510 // Stopping the thread should not destroy the queue.
3511 ASSERT_TRUE(ifacemgr->getPacketQueue6());
3512
3513 // Reconfigure with the queue turned off. We should have neither queue nor thread.
3514 ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, queue_control));
3515 EXPECT_FALSE(ifacemgr->getPacketQueue6());
3516 ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
3517 }
3518
3519 }
3520