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