iface_mgr_unittest.cc 46.1 KB
Newer Older
1
// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
2
3
4
5
6
7
8
9
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
10
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11
12
13
14
15
16
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#include <config.h>

17
18
19
20
#include <asiolink/io_address.h>
#include <dhcp/dhcp4.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/pkt6.h>
21
#include <dhcp/pkt_filter.h>
22

23
#include <boost/scoped_ptr.hpp>
24
25
#include <gtest/gtest.h>

26
27
28
29
30
31
#include <fstream>
#include <iostream>
#include <sstream>

#include <arpa/inet.h>
#include <unistd.h>
32
33
34

using namespace std;
using namespace isc;
35
using namespace isc::asiolink;
36
using namespace isc::dhcp;
37

38
namespace {
39

40
41
42
43
44
45
46
47
// Name of loopback interface detection
const size_t BUF_SIZE = 32;
char LOOPBACK[BUF_SIZE] = "lo";

// Ports used during testing
const uint16_t PORT1 = 10547;   // V6 socket
const uint16_t PORT2 = 10548;   // V4 socket

48
49
50
51
52
53
54
// On some systems measured duration of receive6() and
// receive4() appears to be shorter than select() timeout.
// called by these functions. This may be the case
// if different ime resolutions are used by these functions.
// For such cases we set the tolerance of 0.01s.
const uint32_t TIMEOUT_TOLERANCE = 10000;

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/// Mock object implementing PktFilter class.  It is used by
/// IfaceMgrTest::setPacketFilter to verify that IfaceMgr::setPacketFilter
/// sets this object as a handler for opening sockets. This dummy
/// class simply records that openSocket function was called by
/// the IfaceMgr as expected.
///
/// @todo This class currently doesn't verify that send/receive functions
/// were called. In order to test it, there is a need to supply dummy
/// function performing select() on certain sockets. The system select()
/// call will fail when dummy socket descriptor is provided and thus
/// TestPktFilter::receive will never be called. The appropriate extension
/// to IfaceMgr is planned along with implementation of other "Packet
/// Filters" such as these supporting Linux Packet Filtering and
/// Berkley Packet Filtering.
class TestPktFilter : public PktFilter {
public:

    /// Constructor
    TestPktFilter()
        : open_socket_called_(false) {
    }

    /// Pretends to open socket. Only records a call to this function.
    virtual int openSocket(const Iface&,
                           const isc::asiolink::IOAddress&,
                           const uint16_t,
                           const bool,
                           const bool) {
        open_socket_called_ = true;
        return (1024);
    }

    /// Does nothing
    virtual Pkt4Ptr receive(const Iface&,
                            const SocketInfo&) {
        return (Pkt4Ptr());
    }

    /// Does nothing
94
    virtual int send(const Iface&, uint16_t, const Pkt4Ptr&) {
95
96
97
98
99
100
101
        return (0);
    }

    /// Holds the information whether openSocket was called on this
    /// object after its creation.
    bool open_socket_called_;
};
102

103
class NakedIfaceMgr: public IfaceMgr {
104
    // "naked" Interface Manager, exposes internal fields
105
public:
106
107
    NakedIfaceMgr() {
    }
108
    IfaceCollection & getIfacesLst() { return ifaces_; }
109
110
111
112
113
};

// dummy class for now, but this will be expanded when needed
class IfaceMgrTest : public ::testing::Test {
public:
114
    // these are empty for now, but let's keep them around
115
116
    IfaceMgrTest() {
    }
117

118
119
    ~IfaceMgrTest() {
    }
120

121
122
};

123
124
125
126
// We need some known interface to work reliably. Loopback interface
// is named lo on Linux and lo0 on BSD boxes. We need to find out
// which is available. This is not a real test, but rather a workaround
// that will go away when interface detection is implemented.
127
128
129

// NOTE: At this stage of development, write access to current directory
// during running tests is required.
130
131
TEST_F(IfaceMgrTest, loDetect) {

132
    // poor man's interface detection
133
134
    // it will go away as soon as proper interface detection
    // is implemented
135
    if (if_nametoindex("lo") > 0) {
136
        snprintf(LOOPBACK, BUF_SIZE - 1, "lo");
137
    } else if (if_nametoindex("lo0") > 0) {
138
        snprintf(LOOPBACK, BUF_SIZE - 1, "lo0");
139
    } else {
140
        cout << "Failed to detect loopback interface. Neither "
141
142
             << "lo nor lo0 worked. I give up." << endl;
        FAIL();
143
144
145
    }
}

146
// Uncomment this test to create packet writer. It will
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// write incoming DHCPv6 packets as C arrays. That is useful
// for generating test sequences based on actual traffic
//
// TODO: this potentially should be moved to a separate tool
//

#if 0
TEST_F(IfaceMgrTest, dhcp6Sniffer) {
    // testing socket operation in a portable way is tricky
    // without interface detection implemented

    unlink("interfaces.txt");

    ofstream interfaces("interfaces.txt", ios::ate);
    interfaces << "eth0 fe80::21e:8cff:fe9b:7349";
    interfaces.close();

164
    NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
165

166
    Pkt6* pkt = NULL;
167
168
169
170
    int cnt = 0;
    cout << "---8X-----------------------------------------" << endl;
    while (true) {
        pkt = ifacemgr->receive();
171

172
        cout << "// this code is autogenerated. Do NOT edit." << endl;
173
174
175
176
177
        cout << "// Received " << pkt->data_len_ << " bytes packet:" << endl;
        cout << "Pkt6 *capture" << cnt++ << "() {" << endl;
        cout << "    Pkt6* pkt;" << endl;
        cout << "    pkt = new Pkt6(" << pkt->data_len_ << ");" << endl;
        cout << "    pkt->remote_port_ = " << pkt-> remote_port_ << ";" << endl;
178
179
        cout << "    pkt->remote_addr_ = IOAddress(\""
             << pkt->remote_addr_.toText() << "\");" << endl;
180
        cout << "    pkt->local_port_ = " << pkt-> local_port_ << ";" << endl;
181
182
        cout << "    pkt->local_addr_ = IOAddress(\""
             << pkt->local_addr_.toText() << "\");" << endl;
183
184
        cout << "    pkt->ifindex_ = " << pkt->ifindex_ << ";" << endl;
        cout << "    pkt->iface_ = \"" << pkt->iface_ << "\";" << endl;
185

186
187
        // TODO it is better to declare statically initialize the array
        // and then memcpy it to packet.
188
        for (int i=0; i< pkt->data_len_; i++) {
189
190
            cout << "    pkt->data_[" << i << "]="
                 << (int)(unsigned char)pkt->data_[i] << "; ";
191
192
193
194
195
196
197
198
199
200
            if (!(i%4))
                cout << endl;
        }
        cout << endl;
        cout << "    return (pkt);" << endl;
        cout << "}" << endl << endl;

        delete pkt;
    }
    cout << "---8X-----------------------------------------" << endl;
201

202
203
204
205
206
207
    // never happens. Infinite loop is infinite
    delete pkt;
    delete ifacemgr;
}
#endif

208
209
210
211
212
213
214
215
216
217
TEST_F(IfaceMgrTest, basic) {
    // checks that IfaceManager can be instantiated

    IfaceMgr & ifacemgr = IfaceMgr::instance();
    ASSERT_TRUE(&ifacemgr != 0);
}

TEST_F(IfaceMgrTest, ifaceClass) {
    // basic tests for Iface inner class

218
    Iface* iface = new Iface("eth5", 7);
219
220
221
222
223
224

    EXPECT_STREQ("eth5/7", iface->getFullName().c_str());

    delete iface;
}

225
226
// TODO: Implement getPlainMac() test as soon as interface detection
// is implemented.
227
228
229
TEST_F(IfaceMgrTest, getIface) {

    cout << "Interface checks. Please ignore socket binding errors." << endl;
230
    NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
231
232

    // interface name, ifindex
233
234
235
236
    Iface iface1("lo1", 100);
    Iface iface2("eth9", 101);
    Iface iface3("en3", 102);
    Iface iface4("e1000g4", 103);
237
238
239
    cout << "This test assumes that there are less than 100 network interfaces"
         << " in the tested system and there are no lo1, eth9, en3, e1000g4"
         << " or wifi15 interfaces present." << endl;
240

241
    // note: real interfaces may be detected as well
242
243
244
245
246
    ifacemgr->getIfacesLst().push_back(iface1);
    ifacemgr->getIfacesLst().push_back(iface2);
    ifacemgr->getIfacesLst().push_back(iface3);
    ifacemgr->getIfacesLst().push_back(iface4);

247
248
    cout << "There are " << ifacemgr->getIfacesLst().size()
         << " interfaces." << endl;
249
    for (IfaceMgr::IfaceCollection::iterator iface=ifacemgr->getIfacesLst().begin();
250
251
         iface != ifacemgr->getIfacesLst().end();
         ++iface) {
252
        cout << "  " << iface->getFullName() << endl;
253
254
255
    }


256
    // check that interface can be retrieved by ifindex
257
    Iface* tmp = ifacemgr->getIface(102);
258
    ASSERT_TRUE(tmp != NULL);
259

260
    EXPECT_EQ("en3", tmp->getName());
261
    EXPECT_EQ(102, tmp->getIndex());
262
263

    // check that interface can be retrieved by name
264
    tmp = ifacemgr->getIface("lo1");
265
    ASSERT_TRUE(tmp != NULL);
266

267
    EXPECT_EQ("lo1", tmp->getName());
268
    EXPECT_EQ(100, tmp->getIndex());
269
270

    // check that non-existing interfaces are not returned
271
    EXPECT_EQ(static_cast<void*>(NULL), ifacemgr->getIface("wifi15") );
272
273

    delete ifacemgr;
274

275
276
}

277
TEST_F(IfaceMgrTest, receiveTimeout6) {
278
    using namespace boost::posix_time;
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
    std::cout << "Testing DHCPv6 packet reception timeouts."
              << " Test will block for a few seconds when waiting"
              << " for timeout to occur." << std::endl;

    boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
    // Open socket on the lo interface.
    IOAddress loAddr("::1");
    int socket1 = 0;
    ASSERT_NO_THROW(
        socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547)
    );
    // Socket is open if its descriptor is greater than zero.
    ASSERT_GT(socket1, 0);

    // Remember when we call receive6().
294
    ptime start_time = microsec_clock::universal_time();
295
    // Call receive with timeout of 1s + 400000us = 1.4s.
296
    Pkt6Ptr pkt;
297
    ASSERT_NO_THROW(pkt = ifacemgr->receive6(1, 400000));
298
    // Remember when call to receive6() ended.
299
    ptime stop_time = microsec_clock::universal_time();
300
301
302
303
    // We did not send a packet to lo interface so we expect that
    // nothing has been received and timeout has been reached.
    ASSERT_FALSE(pkt);
    // Calculate duration of call to receive6().
304
    time_duration duration = stop_time - start_time;
305
306
307
    // We stop the clock when the call completes so it does not
    // precisely reflect the receive timeout. However the
    // uncertainity should be low enough to expect that measured
308
    // value is in the range <1.4s; 1.7s>.
309
310
    EXPECT_GE(duration.total_microseconds(),
              1400000 - TIMEOUT_TOLERANCE);
311
    EXPECT_LE(duration.total_microseconds(), 1700000);
312
313

    // Test timeout shorter than 1s.
314
    start_time = microsec_clock::universal_time();
315
    ASSERT_NO_THROW(pkt = ifacemgr->receive6(0, 500000));
316
    stop_time = microsec_clock::universal_time();
317
    ASSERT_FALSE(pkt);
318
    duration = stop_time - start_time;
319
    // Check if measured duration is within <0.5s; 0.8s>.
320
321
    EXPECT_GE(duration.total_microseconds(),
              500000 - TIMEOUT_TOLERANCE);
322
    EXPECT_LE(duration.total_microseconds(), 800000);
323
324
325
326

    // Test with invalid fractional timeout values.
    EXPECT_THROW(ifacemgr->receive6(0, 1000000), isc::BadValue);
    EXPECT_THROW(ifacemgr->receive6(1, 1000010), isc::BadValue);
327
328
329
}

TEST_F(IfaceMgrTest, receiveTimeout4) {
330
    using namespace boost::posix_time;
331
332
333
334
335
336
337
338
339
340
341
342
343
344
    std::cout << "Testing DHCPv6 packet reception timeouts."
              << " Test will block for a few seconds when waiting"
              << " for timeout to occur." << std::endl;

    boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
    // Open socket on the lo interface.
    IOAddress loAddr("127.0.0.1");
    int socket1 = 0;
    ASSERT_NO_THROW(
        socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10067)
    );
    // Socket is open if its descriptor is greater than zero.
    ASSERT_GT(socket1, 0);

345
    Pkt4Ptr pkt;
346
    // Remember when we call receive4().
347
    ptime start_time = microsec_clock::universal_time();
348
349
    // Call receive with timeout of 2s + 300000us = 2.3s.
    ASSERT_NO_THROW(pkt = ifacemgr->receive4(2, 300000));
350
    // Remember when call to receive4() ended.
351
    ptime stop_time = microsec_clock::universal_time();
352
353
354
355
    // We did not send a packet to lo interface so we expect that
    // nothing has been received and timeout has been reached.
    ASSERT_FALSE(pkt);
    // Calculate duration of call to receive4().
356
    time_duration duration = stop_time - start_time;
357
358
359
    // We stop the clock when the call completes so it does not
    // precisely reflect the receive timeout. However the
    // uncertainity should be low enough to expect that measured
360
    // value is in the range <2.3s; 2.6s>.
361
362
    EXPECT_GE(duration.total_microseconds(),
              2300000 - TIMEOUT_TOLERANCE);
363
    EXPECT_LE(duration.total_microseconds(), 2600000);
364
365

    // Test timeout shorter than 1s.
366
    start_time = microsec_clock::universal_time();
367
    ASSERT_NO_THROW(pkt = ifacemgr->receive4(0, 400000));
368
    stop_time = microsec_clock::universal_time();
369
    ASSERT_FALSE(pkt);
370
    duration = stop_time - start_time;
371
    // Check if measured duration is within <0.4s; 0.7s>.
372
373
    EXPECT_GE(duration.total_microseconds(),
              400000 - TIMEOUT_TOLERANCE);
374
    EXPECT_LE(duration.total_microseconds(), 700000);
375
376
377
378

    // Test with invalid fractional timeout values.
    EXPECT_THROW(ifacemgr->receive6(0, 1000000), isc::BadValue);
    EXPECT_THROW(ifacemgr->receive6(2, 1000005), isc::BadValue);
379
380
}

381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
TEST_F(IfaceMgrTest, multipleSockets) {
    boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());

    // container for initialized socket descriptors
    std::list<uint16_t> init_sockets;

    // create socket #1
    int socket1 = 0;
    ASSERT_NO_THROW(
        socket1 = ifacemgr->openSocketFromIface(LOOPBACK, PORT1, AF_INET);
    );
    ASSERT_GT(socket1, 0);
    init_sockets.push_back(socket1);

    // create socket #2
    IOAddress loAddr("127.0.0.1");
    int socket2 = 0;
    ASSERT_NO_THROW(
        socket2 = ifacemgr->openSocketFromRemoteAddress(loAddr, PORT2);
    );
    ASSERT_GT(socket2, 0);
    init_sockets.push_back(socket2);

    // Get loopback interface. If we don't find one we are unable to run
    // this test but we don't want to fail.
406
    Iface* iface_ptr = ifacemgr->getIface(LOOPBACK);
407
408
409
410
411
412
413
    if (iface_ptr == NULL) {
        cout << "Local loopback interface not found. Skipping test. " << endl;
        return;
    }
    // Once sockets have been sucessfully opened, they are supposed to
    // be on the list. Here we start to test if all expected sockets
    // are on the list and no other (unexpected) socket is there.
414
    Iface::SocketCollection sockets = iface_ptr->getSockets();
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
    int matched_sockets = 0;
    for (std::list<uint16_t>::iterator init_sockets_it =
             init_sockets.begin();
         init_sockets_it != init_sockets.end(); ++init_sockets_it) {
        // Set socket descriptors non blocking in order to be able
        // to call recv() on them without hang.
        int flags = fcntl(*init_sockets_it, F_GETFL, 0);
        ASSERT_GE(flags, 0);
        ASSERT_GE(fcntl(*init_sockets_it, F_SETFL, flags | O_NONBLOCK), 0);
        // recv() is expected to result in EWOULDBLOCK error on non-blocking
        // socket in case socket is valid but simply no data are coming in.
        char buf;
        recv(*init_sockets_it, &buf, 1, MSG_PEEK);
        EXPECT_EQ(EWOULDBLOCK, errno);
        // Apart from the ability to use the socket we want to make
        // sure that socket on the list is the one that we created.
431
        for (Iface::SocketCollection::const_iterator socket_it =
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
                 sockets.begin(); socket_it != sockets.end(); ++socket_it) {
            if (*init_sockets_it == socket_it->sockfd_) {
                // This socket is the one that we created.
                ++matched_sockets;
                break;
            }
        }
    }
    // all created sockets have been matched if this condition works.
    EXPECT_EQ(sockets.size(), matched_sockets);

    // closeSockets() is the other function that we want to test. It
    // is supposed to close all sockets so as we will not be able to use
    // them anymore communication.
    ifacemgr->closeSockets();

    // closed sockets are supposed to be removed from the list
    sockets = iface_ptr->getSockets();
    ASSERT_EQ(0, sockets.size());

    // We are still in posession of socket descriptors that we created
    // on the beginning of this test. We can use them to check whether
    // closeSockets() only removed them from the list or they have been
    // really closed.
    for (std::list<uint16_t>::const_iterator init_sockets_it =
             init_sockets.begin();
         init_sockets_it != init_sockets.end(); ++init_sockets_it) {
        // recv() must result in error when using invalid socket.
        char buf;
        recv(*init_sockets_it, &buf, 1, MSG_PEEK);
        // EWOULDBLOCK would mean that socket is valid/open but
        // simply no data is received so we have to check for
        // other errors.
        EXPECT_NE(EWOULDBLOCK, errno);
    }
}

469
TEST_F(IfaceMgrTest, sockets6) {
470
471
472
    // testing socket operation in a portable way is tricky
    // without interface detection implemented

473
    boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
474

475
    IOAddress loAddr("::1");
476

477
478
    Pkt6 pkt6(DHCPV6_SOLICIT, 123);
    pkt6.setIface(LOOPBACK);
479

480
    // bind multicast socket to port 10547
481
    int socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
482
483
    EXPECT_GT(socket1, 0); // socket > 0

484
485
    EXPECT_EQ(socket1, ifacemgr->getSocket(pkt6));

486
    // bind unicast socket to port 10548
487
    int socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10548);
488
489
    EXPECT_GT(socket2, 0);

490
491
    // removed code for binding socket twice to the same address/port
    // as it caused problems on some platforms (e.g. Mac OS X)
492

493
494
    // Close sockets here because the following tests will want to
    // open sockets on the same ports.
495
    ifacemgr->closeSockets();
496

497
498
499
500
501
502
503
504
505
506
507
508
    // Use address that is not assigned to LOOPBACK iface.
    IOAddress invalidAddr("::2");
    EXPECT_THROW(
        ifacemgr->openSocket(LOOPBACK, invalidAddr, 10547),
        SocketConfigError
    );

    // Use non-existing interface name.
    EXPECT_THROW(
        ifacemgr->openSocket("non_existing_interface", loAddr, 10548),
        BadValue
    );
509
510
511

    // Do not call closeSockets() because it is called by IfaceMgr's
    // virtual destructor.
512
513
}

514
TEST_F(IfaceMgrTest, socketsFromIface) {
515
    boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
516

517
    // Open v6 socket on loopback interface and bind to port
518
519
    int socket1 = 0;
    EXPECT_NO_THROW(
520
        socket1 = ifacemgr->openSocketFromIface(LOOPBACK, PORT1, AF_INET6);
521
    );
522
    // Socket descriptor must be positive integer
523
    EXPECT_GT(socket1, 0);
524
    close(socket1);
525

526
    // Open v4 socket on loopback interface and bind to different port
527
528
    int socket2 = 0;
    EXPECT_NO_THROW(
529
        socket2 = ifacemgr->openSocketFromIface(LOOPBACK, PORT2, AF_INET);
530
531
    );
    // socket descriptor must be positive integer
532
533
534
    EXPECT_GT(socket2, 0);
    close(socket2);

535
536
    // Close sockets here because the following tests will want to
    // open sockets on the same ports.
537
538
539
540
541
542
543
    ifacemgr->closeSockets();

    // Use invalid interface name.
    EXPECT_THROW(
        ifacemgr->openSocketFromIface("non_existing_interface", PORT1, AF_INET),
        BadValue
    );
544
545
546

    // Do not call closeSockets() because it is called by IfaceMgr's
    // virtual destructor.
547
548
549
}


550
TEST_F(IfaceMgrTest, socketsFromAddress) {
551
    boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
552

553
    // Open v6 socket on loopback interface and bind to port
554
    int socket1 = 0;
555
    IOAddress loAddr6("::1");
556
    EXPECT_NO_THROW(
557
        socket1 = ifacemgr->openSocketFromAddress(loAddr6, PORT1);
558
559
    );
    // socket descriptor must be positive integer
560
561
    EXPECT_GT(socket1, 0);

562
    // Open v4 socket on loopback interface and bind to different port
563
    int socket2 = 0;
564
    IOAddress loAddr("127.0.0.1");
565
    EXPECT_NO_THROW(
566
        socket2 = ifacemgr->openSocketFromAddress(loAddr, PORT2);
567
568
    );
    // socket descriptor must be positive integer
569
    EXPECT_GT(socket2, 0);
570

571
572
    // Close sockets here because the following tests will want to
    // open sockets on the same ports.
573
574
575
576
577
578
579
    ifacemgr->closeSockets();

    // Use non-existing address.
    IOAddress invalidAddr("1.2.3.4");
    EXPECT_THROW(
        ifacemgr->openSocketFromAddress(invalidAddr, PORT1), BadValue
    );
580
581
582

    // Do not call closeSockets() because it is called by IfaceMgr's
    // virtual destructor.
583
584
}

585
TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
586
    boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
587

588
589
590
    // Open v6 socket to connect to remote address.
    // Loopback address is the only one that we know
    // so let's treat it as remote address.
591
    int socket1 = 0;
592
    IOAddress loAddr6("::1");
593
    EXPECT_NO_THROW(
594
        socket1 = ifacemgr->openSocketFromRemoteAddress(loAddr6, PORT1);
595
    );
596
597
    EXPECT_GT(socket1, 0);

598
    // Open v4 socket to connect to remote address.
599
    int socket2 = 0;
600
    IOAddress loAddr("127.0.0.1");
601
    EXPECT_NO_THROW(
602
        socket2 = ifacemgr->openSocketFromRemoteAddress(loAddr, PORT2);
603
    );
604
    EXPECT_GT(socket2, 0);
605

606
607
    // Close sockets here because the following tests will want to
    // open sockets on the same ports.
608
    ifacemgr->closeSockets();
609

610
611
612
613
614
    // The following test is currently disabled for OSes other than
    // Linux because interface detection is not implemented on them.
    // @todo enable this test for all OSes once interface detection
    // is implemented.
#if defined(OS_LINUX)
615
616
617
618
619
620
621
    // Open v4 socket to connect to broadcast address.
    int socket3  = 0;
    IOAddress bcastAddr("255.255.255.255");
    EXPECT_NO_THROW(
        socket3 = ifacemgr->openSocketFromRemoteAddress(bcastAddr, PORT2);
    );
    EXPECT_GT(socket3, 0);
622
#endif
623
624
625

    // Do not call closeSockets() because it is called by IfaceMgr's
    // virtual destructor.
626
627
}

628
629
// TODO: disabled due to other naming on various systems
// (lo in Linux, lo0 in BSD systems)
630
TEST_F(IfaceMgrTest, DISABLED_sockets6Mcast) {
631
632
633
    // testing socket operation in a portable way is tricky
    // without interface detection implemented

634
    NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
635
636
637
638
639

    IOAddress loAddr("::1");
    IOAddress mcastAddr("ff02::1:2");

    // bind multicast socket to port 10547
640
    int socket1 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
641
642
643
644
    EXPECT_GT(socket1, 0); // socket > 0

    // expect success. This address/port is already bound, but
    // we are using SO_REUSEADDR, so we can bind it twice
645
    int socket2 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
646
647
    EXPECT_GT(socket2, 0);

648
649
650
651
    // there's no good way to test negative case here.
    // we would need non-multicast interface. We will be able
    // to iterate thru available interfaces and check if there
    // are interfaces without multicast-capable flag.
652
653
654

    close(socket1);
    close(socket2);
655
656

    delete ifacemgr;
657
658
}

659
TEST_F(IfaceMgrTest, sendReceive6) {
660

661
662
663
    // testing socket operation in a portable way is tricky
    // without interface detection implemented

664
    boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
665
666

    // let's assume that every supported OS have lo interface
667
    IOAddress loAddr("::1");
668
669
670
671
672
    int socket1 = 0, socket2 = 0;
    EXPECT_NO_THROW(
        socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
        socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10546);
    );
673

674
675
    EXPECT_GT(socket1, 0);
    EXPECT_GT(socket2, 0);
676
677
678


    // prepare dummy payload
679
    uint8_t data[128];
680
    for (int i = 0; i < 128; i++) {
681
        data[i] = i;
682
    }
683
    Pkt6Ptr sendPkt = Pkt6Ptr(new Pkt6(data, 128));
684

685
    sendPkt->repack();
686

687
688
689
690
691
692
    sendPkt->setRemotePort(10547);
    sendPkt->setRemoteAddr(IOAddress("::1"));
    sendPkt->setIndex(1);
    sendPkt->setIface(LOOPBACK);

    Pkt6Ptr rcvPkt;
693
694
695

    EXPECT_EQ(true, ifacemgr->send(sendPkt));

696
    rcvPkt = ifacemgr->receive6(10);
697

698
    ASSERT_TRUE(rcvPkt); // received our own packet
699
700

    // let's check that we received what was sent
701
702
703
    ASSERT_EQ(sendPkt->getData().size(), rcvPkt->getData().size());
    EXPECT_EQ(0, memcmp(&sendPkt->getData()[0], &rcvPkt->getData()[0],
                        rcvPkt->getData().size()));
704

705
    EXPECT_EQ(sendPkt->getRemoteAddr().toText(), rcvPkt->getRemoteAddr().toText());
706
707
708

    // since we opened 2 sockets on the same interface and none of them is multicast,
    // none is preferred over the other for sending data, so we really should not
709
    // assume the one or the other will always be chosen for sending data. Therefore
710
    // we should accept both values as source ports.
711
    EXPECT_TRUE((rcvPkt->getRemotePort() == 10546) || (rcvPkt->getRemotePort() == 10547));
712

713
    // try to send/receive data over the closed socket. Closed socket's descriptor is
714
715
716
    // still being hold by IfaceMgr which will try to use it to receive data.
    close(socket1);
    EXPECT_THROW(ifacemgr->receive6(10), SocketReadError);
717
    EXPECT_THROW(ifacemgr->send(sendPkt), SocketWriteError);
718
719
}

720
721
722
723
724
TEST_F(IfaceMgrTest, sendReceive4) {

    // testing socket operation in a portable way is tricky
    // without interface detection implemented

725
    boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
726
727
728

    // let's assume that every supported OS have lo interface
    IOAddress loAddr("127.0.0.1");
729
    int socket1 = 0;
730
731
732
733
    EXPECT_NO_THROW(
        socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
    );

734
    EXPECT_GE(socket1, 0);
735
    //    EXPECT_GE(socket2, 0);
736

737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
    boost::shared_ptr<Pkt4> sendPkt(new Pkt4(DHCPDISCOVER, 1234) );

    sendPkt->setLocalAddr(IOAddress("127.0.0.1"));

    sendPkt->setLocalPort(DHCP4_SERVER_PORT + 10000 + 1);
    sendPkt->setRemotePort(DHCP4_SERVER_PORT + 10000);
    sendPkt->setRemoteAddr(IOAddress("127.0.0.1"));
    sendPkt->setIndex(1);
    sendPkt->setIface(string(LOOPBACK));
    sendPkt->setHops(6);
    sendPkt->setSecs(42);
    sendPkt->setCiaddr(IOAddress("192.0.2.1"));
    sendPkt->setSiaddr(IOAddress("192.0.2.2"));
    sendPkt->setYiaddr(IOAddress("192.0.2.3"));
    sendPkt->setGiaddr(IOAddress("192.0.2.4"));

753
754
755
    // Unpack() now checks if mandatory DHCP_MESSAGE_TYPE is present.
    // Workarounds (creating DHCP Message Type Option by hand) are no longer
    // needed as setDhcpType() is called in constructor.
756

757
758
759
760
761
762
763
764
765
766
767
    uint8_t sname[] = "That's just a string that will act as SNAME";
    sendPkt->setSname(sname, strlen((const char*)sname));
    uint8_t file[] = "/another/string/that/acts/as/a/file_name.txt";
    sendPkt->setFile(file, strlen((const char*)file));

    ASSERT_NO_THROW(
        sendPkt->pack();
    );

    boost::shared_ptr<Pkt4> rcvPkt;

768
    EXPECT_NO_THROW(ifacemgr->send(sendPkt));
769

770
    ASSERT_NO_THROW(rcvPkt = ifacemgr->receive4(10));
771
    ASSERT_TRUE(rcvPkt); // received our own packet
772
773
774
775
776
777
778
779

    ASSERT_NO_THROW(
        rcvPkt->unpack();
    );

    // let's check that we received what was sent
    EXPECT_EQ(sendPkt->len(), rcvPkt->len());

780
    EXPECT_EQ("127.0.0.1", rcvPkt->getRemoteAddr().toText());
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
    EXPECT_EQ(sendPkt->getRemotePort(), rcvPkt->getLocalPort());

    // now let's check content
    EXPECT_EQ(sendPkt->getHops(), rcvPkt->getHops());
    EXPECT_EQ(sendPkt->getOp(),   rcvPkt->getOp());
    EXPECT_EQ(sendPkt->getSecs(), rcvPkt->getSecs());
    EXPECT_EQ(sendPkt->getFlags(), rcvPkt->getFlags());
    EXPECT_EQ(sendPkt->getCiaddr(), rcvPkt->getCiaddr());
    EXPECT_EQ(sendPkt->getSiaddr(), rcvPkt->getSiaddr());
    EXPECT_EQ(sendPkt->getYiaddr(), rcvPkt->getYiaddr());
    EXPECT_EQ(sendPkt->getGiaddr(), rcvPkt->getGiaddr());
    EXPECT_EQ(sendPkt->getTransid(), rcvPkt->getTransid());
    EXPECT_TRUE(sendPkt->getSname() == rcvPkt->getSname());
    EXPECT_TRUE(sendPkt->getFile() == rcvPkt->getFile());
    EXPECT_EQ(sendPkt->getHtype(), rcvPkt->getHtype());
    EXPECT_EQ(sendPkt->getHlen(), rcvPkt->getHlen());

    // since we opened 2 sockets on the same interface and none of them is multicast,
    // none is preferred over the other for sending data, so we really should not
800
    // assume the one or the other will always be chosen for sending data. We should
801
802
    // skip checking source port of sent address.

803
804
805
806
    // try to receive data over the closed socket. Closed socket's descriptor is
    // still being hold by IfaceMgr which will try to use it to receive data.
    close(socket1);
    EXPECT_THROW(ifacemgr->receive4(10), SocketReadError);
807
    EXPECT_THROW(ifacemgr->send(sendPkt), SocketWriteError);
808
809
}

810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
// Verifies that it is possible to set custom packet filter object
// to handle sockets opening and send/receive operation.
TEST_F(IfaceMgrTest, setPacketFilter) {

    // Create an instance of IfaceMgr.
    boost::scoped_ptr<NakedIfaceMgr> iface_mgr(new NakedIfaceMgr());
    ASSERT_TRUE(iface_mgr);

    // Try to set NULL packet filter object and make sure it is rejected.
    boost::shared_ptr<TestPktFilter> custom_packet_filter;
    EXPECT_THROW(iface_mgr->setPacketFilter(custom_packet_filter),
                 isc::dhcp::InvalidPacketFilter);

    // Create valid object and check if it can be set.
    custom_packet_filter.reset(new TestPktFilter());
    ASSERT_TRUE(custom_packet_filter);
    ASSERT_NO_THROW(iface_mgr->setPacketFilter(custom_packet_filter));

    // Try to open socket using IfaceMgr. It should call the openSocket() function
    // on the packet filter object we have set.
    IOAddress loAddr("127.0.0.1");
    int socket1 = 0;
    EXPECT_NO_THROW(
        socket1 = iface_mgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
    );

    // Check that openSocket function was called.
    EXPECT_TRUE(custom_packet_filter->open_socket_called_);
    // This function always returns fake socket descriptor equal to 1024.
    EXPECT_EQ(1024, socket1);
}

842

843
844
845
846
TEST_F(IfaceMgrTest, socket4) {

    NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();

847
    // Let's assume that every supported OS have lo interface.
848
    IOAddress loAddr("127.0.0.1");
849
    // Use unprivileged port (it's convenient for running tests as non-root).
850
851
852
853
854
855
856
857
    int socket1 = 0;

    EXPECT_NO_THROW(
        socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
    );

    EXPECT_GT(socket1, 0);

858
859
860
    Pkt4 pkt(DHCPDISCOVER, 1234);
    pkt.setIface(LOOPBACK);

861
    // Expect that we get the socket that we just opened.
862
863
    EXPECT_EQ(socket1, ifacemgr->getSocket(pkt));

864
865
866
867
868
    close(socket1);

    delete ifacemgr;
}

869
870
// Test the Iface structure itself
TEST_F(IfaceMgrTest, iface) {
871
    Iface* iface = NULL;
872
    EXPECT_NO_THROW(
873
        iface = new Iface("eth0",1);
874
875
876
877
878
879
880
    );

    EXPECT_EQ("eth0", iface->getName());
    EXPECT_EQ(1, iface->getIndex());
    EXPECT_EQ("eth0/1", iface->getFullName());

    // Let's make a copy of this address collection.
881
    Iface::AddressCollection addrs = iface->getAddresses();
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909

    EXPECT_EQ(0, addrs.size());

    IOAddress addr1("192.0.2.6");
    iface->addAddress(addr1);

    addrs = iface->getAddresses();
    ASSERT_EQ(1, addrs.size());
    EXPECT_EQ("192.0.2.6", addrs.at(0).toText());

    // No such address, should return false.
    EXPECT_FALSE(iface->delAddress(IOAddress("192.0.8.9")));

    // This address is present, delete it!
    EXPECT_TRUE(iface->delAddress(IOAddress("192.0.2.6")));

    // Not really necessary, previous reference still points to the same
    // collection. Let's do it anyway, as test code may serve as example
    // usage code as well.
    addrs = iface->getAddresses();

    EXPECT_EQ(0, addrs.size());

    EXPECT_NO_THROW(
        delete iface;
    );
}

910
TEST_F(IfaceMgrTest, iface_methods) {
911
    Iface iface("foo", 1234);
912
913
914
915

    iface.setHWType(42);
    EXPECT_EQ(42, iface.getHWType());

916
917
    uint8_t mac[Iface::MAX_MAC_LEN+10];
    for (int i = 0; i < Iface::MAX_MAC_LEN + 10; i++)
918
919
920
921
922
923
924
925
        mac[i] = 255 - i;

    EXPECT_EQ("foo", iface.getName());
    EXPECT_EQ(1234, iface.getIndex());

    // MAC is too long. Exception should be thrown and
    // MAC length should not be set.
    EXPECT_THROW(
926
        iface.setMac(mac, Iface::MAX_MAC_LEN + 1),
927
928
929
930
931
932
933
        OutOfRange
    );

    // MAC length should stay not set as excep
    EXPECT_EQ(0, iface.getMacLen());

    // Setting maximum length MAC should be ok.
934
    iface.setMac(mac, Iface::MAX_MAC_LEN);
935
936
937

    // For some reason constants cannot be used directly in EXPECT_EQ
    // as this produces linking error.
938
    size_t len = Iface::MAX_MAC_LEN;
939
940
941
942
    EXPECT_EQ(len, iface.getMacLen());
    EXPECT_EQ(0, memcmp(mac, iface.getMac(), iface.getMacLen()));
}

943
944
945
TEST_F(IfaceMgrTest, socketInfo) {

    // check that socketinfo for IPv4 socket is functional
946
    SocketInfo sock1(7, IOAddress("192.0.2.56"), DHCP4_SERVER_PORT + 7);
947
948
949
950
951
952
    EXPECT_EQ(7, sock1.sockfd_);
    EXPECT_EQ("192.0.2.56", sock1.addr_.toText());
    EXPECT_EQ(AF_INET, sock1.family_);
    EXPECT_EQ(DHCP4_SERVER_PORT + 7, sock1.port_);

    // check that socketinfo for IPv6 socket is functional
953
    SocketInfo sock2(9, IOAddress("2001:db8:1::56"), DHCP4_SERVER_PORT + 9);
954
955
956
957
958
959
    EXPECT_EQ(9, sock2.sockfd_);
    EXPECT_EQ("2001:db8:1::56", sock2.addr_.toText());
    EXPECT_EQ(AF_INET6, sock2.family_);
    EXPECT_EQ(DHCP4_SERVER_PORT + 9, sock2.port_);

    // now let's test if IfaceMgr handles socket info properly
960
    NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
961
    Iface* loopback = ifacemgr->getIface(LOOPBACK);
962
963
964
965
    ASSERT_TRUE(loopback);
    loopback->addSocket(sock1);
    loopback->addSocket(sock2);

966
    Pkt6 pkt6(DHCPV6_REPLY, 123456);
967
968
969
970
971
972
973
974

    // pkt6 dos not have interface set yet
    EXPECT_THROW(
        ifacemgr->getSocket(pkt6),
        BadValue
    );

    // try to send over non-existing interface
975
    pkt6.setIface("nosuchinterface45");
976
977
978
979
980
981
    EXPECT_THROW(
        ifacemgr->getSocket(pkt6),
        BadValue
    );

    // this will work
982
    pkt6.setIface(LOOPBACK);
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
    EXPECT_EQ(9, ifacemgr->getSocket(pkt6));

    bool deleted = false;
    EXPECT_NO_THROW(
        deleted = ifacemgr->getIface(LOOPBACK)->delSocket(9);
    );
    EXPECT_EQ(true, deleted);

    // it should throw again, there's no usable socket anymore
    EXPECT_THROW(
        ifacemgr->getSocket(pkt6),
        Unexpected
    );

    // repeat for pkt4
    Pkt4 pkt4(DHCPDISCOVER, 1);

    // pkt4 does not have interface set yet.
    EXPECT_THROW(
        ifacemgr->getSocket(pkt4),
        BadValue
    );

    // Try to send over non-existing interface.
    pkt4.setIface("nosuchinterface45");
    EXPECT_THROW(
        ifacemgr->getSocket(pkt4),
        BadValue
    );

    // Socket info is set, packet has well defined interface. It should work.
    pkt4.setIface(LOOPBACK);
    EXPECT_EQ(7, ifacemgr->getSocket(pkt4));

    EXPECT_NO_THROW(
        ifacemgr->getIface(LOOPBACK)->delSocket(7);
    );

    // It should throw again, there's no usable socket anymore.
    EXPECT_THROW(
        ifacemgr->getSocket(pkt4),
        Unexpected
    );
1026
1027
1028
1029

    delete ifacemgr;
}

1030
1031
#if defined(OS_LINUX)

1032
1033
1034
/// @brief parses text representation of MAC address
///
/// This function parses text representation of a MAC address and stores
1035
/// it in binary format. Text format is expected to be separate with
1036
1037
/// semicolons, e.g. f4:6d:04:96:58:f2
///
1038
/// TODO: Iface::mac_ uses uint8_t* type, should be vector<uint8_t>
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
///
/// @param textMac string with MAC address to parse
/// @param mac pointer to output buffer
/// @param macLen length of output buffer
///
/// @return number of bytes filled in output buffer
size_t parse_mac(const std::string& textMac, uint8_t* mac, size_t macLen) {
    stringstream tmp(textMac);
    tmp.flags(ios::hex);
    int i = 0;
    uint8_t octet = 0; // output octet
1050
    uint8_t byte;  // parsed character from text representation
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
    while (!tmp.eof()) {

        tmp >> byte; // hex value
        if (byte == ':') {
            mac[i++] = octet;

            if (i == macLen) {
                // parsing aborted. We hit output buffer size
                return(i);
            }
            octet = 0;
            continue;
        }
        if (isalpha(byte)) {
            byte = toupper(byte) - 'A' + 10;
        } else if (isdigit(byte)) {
            byte -= '0';
        } else {
            // parse error. Let's return what we were able to parse so far
            break;
        }
        octet <<= 4;
        octet += byte;
    }
    mac[i++] = octet;

    return (i);
}

/// @brief Parses 'ifconfig -a' output and creates list of interfaces
///
/// This method tries to parse ifconfig output. Note that there are some
/// oddities in recent versions of ifconfig, like putting extra spaces
/// after MAC address, inconsistent naming and spacing between inet and inet6.
/// This is an attempt to find a balance between tight parsing of every piece
/// of text that ifconfig prints and robustness to handle slight differences
/// in ifconfig output.
///
1089
1090
/// @todo: Consider using isc::util::str::tokens here.
///
1091
1092
/// @param textFile name of a text file that holds output of ifconfig -a
/// @param ifaces empty list of interfaces to be filled
1093
void parse_ifconfig(const std::string& textFile, IfaceMgr::IfaceCollection& ifaces) {
1094
1095
1096
    fstream f(textFile.c_str());

    bool first_line = true;
1097
    IfaceMgr::IfaceCollection::iterator iface;
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
    while (!f.eof()) {
        string line;
        getline(f, line);

        // interfaces are separated by empty line
        if (line.length() == 0) {
            first_line = true;
            continue;
        }

        // uncomment this for ifconfig output debug
        // cout << "line[" << line << "]" << endl;

        // this is first line of a new interface
        if (first_line) {
            first_line = false;

            size_t offset;
            offset = line.find_first_of(" ");
            if (offset == string::npos) {
                isc_throw(BadValue, "Malformed output of ifconfig");
            }
1120
1121

            // ifconfig in Gentoo prints out eth0: instead of eth0
1122
            if (line[offset - 1] == ':') {
1123
1124
                offset--;
            }
1125
1126
1127
            string name = line.substr(0, offset);

            // sadly, ifconfig does not return ifindex
1128
            ifaces.push_back(Iface(name, 0));
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
            iface = ifaces.end();
            --iface; // points to the last element

            offset = line.find(string("HWaddr"));

            string mac = "";
            if (offset != string::npos) { // some interfaces don't have MAC (e.g. lo)
                offset += 7;
                mac = line.substr(offset, string::npos);
                mac = mac.substr(0, mac.find_first_of(" "));

1140
1141
                uint8_t buf[Iface::MAX_MAC_LEN];
                int mac_len = parse_mac(mac, buf, Iface::MAX_MAC_LEN);
1142
                iface->setMac(buf, mac_len);
1143
1144
1145
1146
1147
            }
        }

        if (line.find("inet6") != string::npos) {
            // IPv6 address
1148
1149
1150
            string addr;
            if (line.find("addr:", line.find("inet6")) != string::npos) {
                // Ubuntu style format: inet6 addr: ::1/128 Scope:Host
1151
                addr = line.substr(line.find("addr:") + 6, string::npos);
1152
1153
            } else {
                // Gentoo style format: inet6 fe80::6ef0:49ff:fe96:ba17  prefixlen 64  scopeid 0x20<link>
1154
                addr = line.substr(line.find("inet6") + 6, string::npos);
1155
1156
1157
            }

            // handle Ubuntu format: inet6 addr: fe80::f66d:4ff:fe96:58f2/64 Scope:Link
1158
            addr = addr.substr(0, addr.find("/"));
1159
1160
1161

            // handle inet6 fe80::ca3a:35ff:fed4:8f1d  prefixlen 64  scopeid 0x20<link>
            addr = addr.substr(0, addr.find(" "));
1162
            IOAddress a(addr);
1163
            iface->addAddress(a);
1164
1165
        } else if(line.find("inet") != string::npos) {
            // IPv4 address
1166
1167
1168
            string addr;
            if (line.find("addr:", line.find("inet")) != string::npos) {
                // Ubuntu style format: inet addr:127.0.0.1  Mask:255.0.0.0
1169
                addr = line.substr(line.find("addr:") + 5, string::npos);
1170
1171
            } else {
                // Gentoo style format: inet 10.53.0.4  netmask 255.255.255.0
1172
                addr = line.substr(line.find("inet") + 5, string::npos);
1173
1174
            }

1175
1176
            addr = addr.substr(0, addr.find_first_of(" "));
            IOAddress a(addr);
1177
            iface->addAddress(a);
1178
        } else if(line.find("Metric") != string::npos) {
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
            // flags
            if (line.find("UP") != string::npos) {
                iface->flag_up_ = true;
            }
            if (line.find("LOOPBACK") != string::npos) {
                iface->flag_loopback_ = true;
            }
            if (line.find("RUNNING") != string::npos) {
                iface->flag_running_ = true;
            }
            if (line.find("BROADCAST") != string::npos) {
                iface->flag_broadcast_ = true;
            }
            if (line.find("MULTICAST") != string::npos) {
                iface->flag_multicast_ = true;
            }
        }
    }
}


// This test compares implemented detection routines to output of "ifconfig -a" command.
// It is far from perfect, but it is able to verify that interface names, flags,
// MAC address, IPv4 and IPv6 addresses are detected properly. Interface list completeness
// (check that each interface is reported, i.e. no missing or extra interfaces) and
// address completeness is verified.
//
1206
// Things that are not tested:
1207
1208
// - ifindex (ifconfig does not print it out)
// - address scopes and lifetimes (we don't need it, so it is not implemented in IfaceMgr)
1209
1210
// TODO: temporarily disabled, see ticket #1529
TEST_F(IfaceMgrTest, DISABLED_detectIfaces_linux) {
1211
1212

    NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
1213
    IfaceMgr::IfaceCollection& detectedIfaces = ifacemgr->getIfacesLst();