iface_mgr.h 26.7 KB
Newer Older
1
// Copyright (C) 2011-2012  Internet Systems Consortium, Inc. ("ISC")
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//
// 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,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// 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.

#ifndef IFACE_MGR_H
#define IFACE_MGR_H

18
#include <asiolink/io_address.h>
19
#include <dhcp/dhcp4.h>
20
#include <dhcp/dhcp6.h>
21
22
#include <dhcp/pkt4.h>
#include <dhcp/pkt6.h>
23

24
25
26
27
28
29
#include <boost/noncopyable.hpp>
#include <boost/scoped_array.hpp>
#include <boost/shared_ptr.hpp>

#include <list>

30
31
namespace isc {

32
namespace dhcp {
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

/// @brief IfaceMgr exception thrown thrown when interface detection fails.
class IfaceDetectError : public Exception {
public:
    IfaceDetectError(const char* file, size_t line, const char* what) :
        isc::Exception(file, line, what) { };
};

/// @brief IfaceMgr exception thrown thrown when socket opening
/// or configuration failed.
class SocketConfigError : public Exception {
public:
    SocketConfigError(const char* file, size_t line, const char* what) :
        isc::Exception(file, line, what) { };
};

/// @brief IfaceMgr exception thrown thrown when error occured during
/// reading data from socket.
class SocketReadError : public Exception {
public:
    SocketReadError(const char* file, size_t line, const char* what) :
        isc::Exception(file, line, what) { };
};

/// @brief IfaceMgr exception thrown thrown when error occured during
/// sedning data through socket.
class SocketWriteError : public Exception {
public:
    SocketWriteError(const char* file, size_t line, const char* what) :
        isc::Exception(file, line, what) { };
};

65
66
67
68
69
70
71
72
73
/// @brief handles network interfaces, transmission and reception
///
/// IfaceMgr is an interface manager class that detects available network
/// interfaces, configured addresses, link-local addresses, and provides
/// API for using sockets.
///
class IfaceMgr : public boost::noncopyable {
public:
    /// type that defines list of addresses
74
    typedef std::vector<isc::asiolink::IOAddress> AddressCollection;
75

76
77
78
    /// defines callback used when commands are received over control session
    typedef void (*SessionCallback) (void);

79
80
81
    /// maximum MAC address length (Infiniband uses 20 bytes)
    static const unsigned int MAX_MAC_LEN = 20;

82
83
84
85
86
87
88
89
90
    /// @brief Packet reception buffer size
    ///
    /// RFC3315 states that server responses may be
    /// fragmented if they are over MTU. There is no
    /// text whether client's packets may be larger
    /// than 1500. For now, we can assume that
    /// we don't support packets larger than 1500.
    static const uint32_t RCVBUFSIZE = 1500;

91
92
93
94
95
96
    /// Holds information about socket.
    struct SocketInfo {
        uint16_t sockfd_; /// socket descriptor
        isc::asiolink::IOAddress addr_; /// bound address
        uint16_t port_;   /// socket port
        uint16_t family_; /// IPv4 or IPv6
Tomek Mrugalski's avatar
Tomek Mrugalski committed
97
98
99
100
101
102

        /// @brief SocketInfo constructor.
        ///
        /// @param sockfd socket descriptor
        /// @param addr an address the socket is bound to
        /// @param port a port the socket is bound to
103
104
105
106
107
108
        SocketInfo(uint16_t sockfd, const isc::asiolink::IOAddress& addr,
                   uint16_t port)
        :sockfd_(sockfd), addr_(addr), port_(port), family_(addr.getFamily()) { }
    };

    /// type that holds a list of socket informations
109
    /// @todo: Add SocketCollectionConstIter type
110
111
    typedef std::list<SocketInfo> SocketCollection;

112

113
    /// @brief represents a single network interface
114
    ///
115
116
117
    /// Iface structure represents network interface with all useful
    /// information, like name, interface index, MAC address and
    /// list of assigned addresses
Tomek Mrugalski's avatar
Tomek Mrugalski committed
118
119
    class Iface {
    public:
120
121
122
123
124
125
        /// @brief Iface constructor.
        ///
        /// Creates Iface object that represents network interface.
        ///
        /// @param name name of the interface
        /// @param ifindex interface index (unique integer identifier)
126
127
        Iface(const std::string& name, int ifindex);

128
        /// @brief Closes all open sockets on interface.
129
130
        void closeSockets();

131
132
133
        /// @brief Returns full interface name as "ifname/ifindex" string.
        ///
        /// @return string with interface name
134
135
        std::string getFullName() const;

136
137
138
        /// @brief Returns link-layer address a plain text.
        ///
        /// @return MAC address as a plain text (string)
139
        std::string getPlainMac() const;
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
        /// @brief Sets MAC address of the interface.
        ///
        /// @param mac pointer to MAC address buffer
        /// @param macLen length of mac address
        void setMac(const uint8_t* mac, size_t macLen);

        /// @brief Returns MAC length.
        ///
        /// @return length of MAC address
        size_t getMacLen() const { return mac_len_; }

        /// @brief Returns pointer to MAC address.
        ///
        /// Note: Returned pointer is only valid as long as the interface object
        /// that returned it.
        const uint8_t* getMac() const { return mac_; }

158
159
160
161
162
163
        /// @brief Sets flag_*_ fields based on bitmask value returned by OS
        ///
        /// Note: Implementation of this method is OS-dependent as bits have
        /// different meaning on each OS.
        ///
        /// @param flags bitmask value returned by OS in interface detection
164
165
        void setFlags(uint32_t flags);

166
167
168
        /// @brief Returns interface index.
        ///
        /// @return interface index
169
170
        uint16_t getIndex() const { return ifindex_; }

171
172
173
174
175
        /// @brief Returns interface name.
        ///
        /// @return interface name
        std::string getName() const { return name_; };

176
177
178
179
180
181
182
183
184
185
        /// @brief Sets up hardware type of the interface.
        ///
        /// @param type hardware type
        void setHWType(uint16_t type ) { hardware_type_ = type; }

        /// @brief Returns hardware type of the interface.
        ///
        /// @return hardware type
        uint16_t getHWType() const { return hardware_type_; }

186
187
188
189
190
191
192
193
194
195
        /// @brief Returns all interfaces available on an interface.
        ///
        /// Care should be taken to not use this collection after Iface object
        /// ceases to exist. That is easy in most cases as Iface objects are
        /// created by IfaceMgr that is a singleton an is expected to be
        /// available at all time. We may revisit this if we ever decide to
        /// implement dynamic interface detection, but such fancy feature would
        /// mostly be useful for clients with wifi/vpn/virtual interfaces.
        ///
        /// @return collection of addresses
196
197
        const AddressCollection& getAddresses() const { return addrs_; }

198
199
200
201
202
203
        /// @brief Adds an address to an interface.
        ///
        /// This only adds an address to collection, it does not physically
        /// configure address on actual network interface.
        ///
        /// @param addr address to be added
204
205
206
207
        void addAddress(const isc::asiolink::IOAddress& addr) {
            addrs_.push_back(addr);
        }

208
209
210
211
212
213
214
215
216
        /// @brief Deletes an address from an interface.
        ///
        /// This only deletes address from collection, it does not physically
        /// remove address configuration from actual network interface.
        ///
        /// @param addr address to be removed.
        ///
        /// @return true if removal was successful (address was in collection),
        ///         false otherwise
217
218
        bool delAddress(const isc::asiolink::IOAddress& addr);

219
220
        /// @brief Adds socket descriptor to an interface.
        ///
221
        /// @param sock SocketInfo structure that describes socket.
222
223
224
225
226
227
228
229
        void addSocket(const SocketInfo& sock)
            { sockets_.push_back(sock); }

        /// @brief Closes socket.
        ///
        /// Closes socket and removes corresponding SocketInfo structure
        /// from an interface.
        ///
230
        /// @param sockfd socket descriptor to be closed/removed.
231
232
233
        /// @return true if there was such socket, false otherwise
        bool delSocket(uint16_t sockfd);

234
235
236
237
238
239
240
241
242
        /// @brief Returns collection of all sockets added to interface.
        ///
        /// When new socket is created with @ref IfaceMgr::openSocket
        /// it is added to sockets collection on particular interface.
        /// If socket is opened by other means (e.g. function that does
        /// not use @ref IfaceMgr::openSocket) it will not be available
        /// in this collection. Note that functions like
        /// @ref IfaceMgr::openSocketFromIface use
        /// @ref IfaceMgr::openSocket internally.
243
244
        /// The returned reference is only valid during the lifetime of
        /// the IfaceMgr object that returned it.
245
246
247
248
249
        ///
        /// @return collection of sockets added to interface
        const SocketCollection& getSockets() const { return sockets_; }

    protected:
250
251
252
        /// socket used to sending data
        SocketCollection sockets_;

253
254
255
256
257
        /// network interface name
        std::string name_;

        /// interface index (a value that uniquely indentifies an interface)
        int ifindex_;
258
259

        /// list of assigned addresses
260
        AddressCollection addrs_;
261
262
263
264
265

        /// link-layer address
        uint8_t mac_[MAX_MAC_LEN];

        /// length of link-layer address (usually 6)
266
267
268
269
        size_t mac_len_;

        /// hardware type
        uint16_t hardware_type_;
270

271
    public:
272
273
274
        /// @todo: Make those fields protected once we start supporting more
        /// than just Linux

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
        /// specifies if selected interface is loopback
        bool flag_loopback_;

        /// specifies if selected interface is up
        bool flag_up_;

        /// flag specifies if selected interface is running
        /// (e.g. cable plugged in, wifi associated)
        bool flag_running_;

        /// flag specifies if selected interface is multicast capable
        bool flag_multicast_;

        /// flag specifies if selected interface is broadcast capable
        bool flag_broadcast_;

        /// interface flags (this value is as is returned by OS,
        /// it may mean different things on different OSes)
        uint32_t flags_;
294
    };
295

296
297
298
299
300
    // TODO performance improvement: we may change this into
    //      2 maps (ifindex-indexed and name-indexed) and
    //      also hide it (make it public make tests easier for now)

    /// type that holds a list of interfaces
301
    typedef std::list<Iface> IfaceCollection;
302
303
304
305
306
307
308

    /// IfaceMgr is a singleton class. This method returns reference
    /// to its sole instance.
    ///
    /// @return the only existing instance of interface manager
    static IfaceMgr& instance();

309
310
311
312
313
314
315
316
317
318
    /// @brief Can be packet can be send directly to the client without address.
    ///
    /// Checks if IfaceMgr can send DHCPv4 packet to the client
    /// who hasn't got address assigned. If this is not supported
    /// broadcast address should be used to send response to
    /// the client.
    ///
    /// @return true if direct response is supported.
    bool isDirectResponseSupported();

319
320
321
322
323
324
325
    /// @brief Returns interface with specified interface index
    ///
    /// @param ifindex index of searched interface
    ///
    /// @return interface with requested index (or NULL if no such
    ///         interface is present)
    ///
326
    Iface* getIface(int ifindex);
327
328
329
330
331
332
333
334
335
336
337

    /// @brief Returns interface with specified interface name
    ///
    /// @param ifname name of searched interface
    ///
    /// @return interface with requested name (or NULL if no such
    ///         interface is present)
    ///
    Iface*
    getIface(const std::string& ifname);

Tomek Mrugalski's avatar
Tomek Mrugalski committed
338
339
    /// @brief Returns container with all interfaces.
    ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
340
341
342
343
    /// This reference is only valid as long as IfaceMgr is valid. However,
    /// since IfaceMgr is a singleton and is expected to be destroyed after
    /// main() function completes, you should not worry much about this.
    ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
344
345
346
    /// @return container with all interfaces.
    const IfaceCollection& getIfaces() { return ifaces_; }

347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
    /// @brief Return most suitable socket for transmitting specified IPv6 packet.
    ///
    /// This method takes Pkt6 (see overloaded implementation that takes
    /// Pkt4) and chooses appropriate socket to send it. This method
    /// may throw BadValue if specified packet does not have outbound
    /// interface specified, no such interface exists, or specified
    /// interface does not have any appropriate sockets open.
    ///
    /// @param pkt a packet to be transmitted
    ///
    /// @return a socket descriptor
    uint16_t getSocket(const isc::dhcp::Pkt6& pkt);

    /// @brief Return most suitable socket for transmitting specified IPv6 packet.
    ///
    /// This method takes Pkt4 (see overloaded implementation that takes
    /// Pkt6) and chooses appropriate socket to send it. This method
    /// may throw BadValue if specified packet does not have outbound
    /// interface specified, no such interface exists, or specified
    /// interface does not have any appropriate sockets open.
    ///
    /// @param pkt a packet to be transmitted
    ///
    /// @return a socket descriptor
    uint16_t getSocket(const isc::dhcp::Pkt4& pkt);

373
374
375
376
377
378
    /// debugging method that prints out all available interfaces
    ///
    /// @param out specifies stream to print list of interfaces to
    void
    printIfaces(std::ostream& out = std::cout);

Tomek Mrugalski's avatar
Tomek Mrugalski committed
379
    /// @brief Sends an IPv6 packet.
380
    ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
381
    /// Sends an IPv6 packet. All parameters for actual transmission are specified in
382
383
    /// Pkt6 structure itself. That includes destination address, src/dst port
    /// and interface over which data will be sent.
384
385
386
    ///
    /// @param pkt packet to be sent
    ///
387
388
    /// @throw isc::BadValue if invalid interface specified in the packet.
    /// @throw isc::dhcp::SocketWriteError if sendmsg() failed to send packet.
389
    /// @return true if sending was successful
Tomek Mrugalski's avatar
Tomek Mrugalski committed
390
    bool send(const Pkt6Ptr& pkt);
391

Tomek Mrugalski's avatar
Tomek Mrugalski committed
392
393
394
395
396
397
398
399
    /// @brief Sends an IPv4 packet.
    ///
    /// Sends an IPv4 packet. All parameters for actual transmission are specified
    /// in Pkt4 structure itself. That includes destination address, src/dst
    /// port and interface over which data will be sent.
    ///
    /// @param pkt a packet to be sent
    ///
400
401
    /// @throw isc::BadValue if invalid interface specified in the packet.
    /// @throw isc::dhcp::SocketWriteError if sendmsg() failed to send packet.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
402
    /// @return true if sending was successful
Tomek Mrugalski's avatar
Tomek Mrugalski committed
403
    bool send(const Pkt4Ptr& pkt);
404

Tomek Mrugalski's avatar
Tomek Mrugalski committed
405
    /// @brief Tries to receive IPv6 packet over open IPv6 sockets.
406
    ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
407
    /// Attempts to receive a single IPv6 packet of any of the open IPv6 sockets.
408
409
410
    /// If reception is successful and all information about its sender
    /// are obtained, Pkt6 object is created and returned.
    ///
411
412
413
    /// TODO Start using select() and add timeout to be able
    /// to not wait infinitely, but rather do something useful
    /// (e.g. remove expired leases)
414
    ///
415
416
417
    /// @param timeout_sec specifies integral part of the timeout (in seconds)
    /// @param timeout_usec specifies fractional part of the timeout
    /// (in microseconds)
418
    ///
419
    /// @throw isc::BadValue if timeout_usec is greater than one million
420
    /// @throw isc::dhcp::SocketReadError if error occured when receiving a packet.
421
    /// @return Pkt6 object representing received packet (or NULL)
422
    Pkt6Ptr receive6(uint32_t timeout_sec, uint32_t timeout_usec = 0);
423

Tomek Mrugalski's avatar
Tomek Mrugalski committed
424
425
426
427
428
429
    /// @brief Tries to receive IPv4 packet over open IPv4 sockets.
    ///
    /// Attempts to receive a single IPv4 packet of any of the open IPv4 sockets.
    /// If reception is successful and all information about its sender
    /// are obtained, Pkt4 object is created and returned.
    ///
430
431
432
    /// @param timeout_sec specifies integral part of the timeout (in seconds)
    /// @param timeout_usec specifies fractional part of the timeout
    /// (in microseconds)
Tomek Mrugalski's avatar
Tomek Mrugalski committed
433
    ///
434
    /// @throw isc::BadValue if timeout_usec is greater than one million
435
    /// @throw isc::dhcp::SocketReadError if error occured when receiving a packet.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
436
    /// @return Pkt4 object representing received packet (or NULL)
437
    Pkt4Ptr receive4(uint32_t timeout_sec, uint32_t timeout_usec = 0);
438

439
440
441
442
443
444
445
446
447
    /// Opens UDP/IP socket and binds it to address, interface and port.
    ///
    /// Specific type of socket (UDP/IPv4 or UDP/IPv6) depends on passed addr
    /// family.
    ///
    /// @param ifname name of the interface
    /// @param addr address to be bound.
    /// @param port UDP port.
    ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
448
449
450
    /// Method will throw if socket creation, socket binding or multicast
    /// join fails.
    ///
451
    /// @return socket descriptor, if socket creation, binding and multicast
Tomek Mrugalski's avatar
Tomek Mrugalski committed
452
    /// group join were all successful.
453
    int openSocket(const std::string& ifname,
454
455
                   const isc::asiolink::IOAddress& addr,
                   const uint16_t port);
456

457
458
    /// @brief Opens UDP/IP socket and binds it to interface specified.
    ///
459
460
461
462
    /// This method differs from \ref openSocket in that it does not require
    /// the specification of a local address to which socket will be bound.
    /// Instead, the method searches through the addresses on the specified
    /// interface and selects one that matches the address family.
463
464
465
    ///
    /// @param ifname name of the interface
    /// @param port UDP port
466
    /// @param family address family (AF_INET or AF_INET6)
467
468
    /// @return socket descriptor, if socket creation, binding and multicast
    /// group join were all successful.
469
    /// @throw isc::Unexpected if failed to create and bind socket.
470
471
    /// @throw isc::BadValue if there is no address on specified interface
    /// that belongs to given family.
472
473
    int openSocketFromIface(const std::string& ifname,
                            const uint16_t port,
474
475
                            const uint8_t family);

476
477
    /// @brief Opens UDP/IP socket and binds to address specified
    ///
478
479
    /// This methods differs from \ref openSocket in that it does not require
    /// the specification of the interface to which the socket will be bound.
480
481
482
483
484
    ///
    /// @param addr address to be bound
    /// @param port UDP port
    /// @return socket descriptor, if socket creation, binding and multicast
    /// group join were all successful.
485
    /// @throw isc::Unexpected if failed to create and bind socket
486
487
    /// @throw isc::BadValue if specified address is not available on
    /// any interface
488
489
490
491
492
    int openSocketFromAddress(const isc::asiolink::IOAddress& addr,
                              const uint16_t port);

    /// @brief Opens UDP/IP socket to be used to connect to remote address
    ///
493
494
495
496
    /// This method identifies the local address to be used to connect to the
    /// remote address specified as argument.  Once the local address is
    /// identified, \ref openSocket is called to open a socket and bind it to
    /// the interface, address and port.
497
498
499
500
501
    ///
    /// @param remote_addr remote address to connect to
    /// @param port UDP port
    /// @return socket descriptor, if socket creation, binding and multicast
    /// group join were all successful.
502
    /// @throw isc::Unexpected if failed to create and bind socket
503
504
    int openSocketFromRemoteAddress(const isc::asiolink::IOAddress& remote_addr,
                                    const uint16_t port);
505

506

Tomek Mrugalski's avatar
Tomek Mrugalski committed
507
508
509
510
511
    /// Opens IPv6 sockets on detected interfaces.
    ///
    /// Will throw exception if socket creation fails.
    ///
    /// @param port specifies port number (usually DHCP6_SERVER_PORT)
512
    ///
513
    /// @throw SocketOpenFailure if tried and failed to open socket.
514
    /// @return true if any sockets were open
Tomek Mrugalski's avatar
Tomek Mrugalski committed
515
    bool openSockets6(const uint16_t port = DHCP6_SERVER_PORT);
516
517
518
519
520

    /// @brief Closes all open sockets.
    /// Is used in destructor, but also from Dhcpv4_srv and Dhcpv6_srv classes.
    void closeSockets();

521
522
523
    /// Opens IPv4 sockets on detected interfaces.
    /// Will throw exception if socket creation fails.
    ///
524
    /// @param port specifies port number (usually DHCP4_SERVER_PORT)
525
    ///
526
    /// @throw SocketOpenFailure if tried and failed to open socket.
527
    /// @return true if any sockets were open
Tomek Mrugalski's avatar
Tomek Mrugalski committed
528
    bool openSockets4(const uint16_t port = DHCP4_SERVER_PORT);
529

530
531
532
533
534
    /// @brief returns number of detected interfaces
    ///
    /// @return number of detected interfaces
    uint16_t countIfaces() { return ifaces_.size(); }

535
536
537
538
539
540
541
542
543
544
545
546
    /// @brief Sets session socket and a callback
    ///
    /// Specifies session socket and a callback that will be called
    /// when data will be received over that socket.
    ///
    /// @param socketfd socket descriptor
    /// @param callback callback function
    void set_session_socket(int socketfd, SessionCallback callback) {
        session_socket_ = socketfd;
        session_callback_ = callback;
    }

547
    /// A value of socket descriptor representing "not specified" state.
548
    static const int INVALID_SOCKET = -1;
549

550
551
552
553
554
555
    // don't use private, we need derived classes in tests
protected:

    /// @brief Protected constructor.
    ///
    /// Protected constructor. This is a singleton class. We don't want
Tomek Mrugalski's avatar
Tomek Mrugalski committed
556
    /// anyone to create instances of IfaceMgr. Use instance() method instead.
557
558
    IfaceMgr();

559
    virtual ~IfaceMgr();
560

Tomek Mrugalski's avatar
Tomek Mrugalski committed
561
562
563
564
565
566
567
568
569
    /// @brief Opens IPv4 socket.
    ///
    /// Please do not use this method directly. Use openSocket instead.
    ///
    /// This method may throw exception if socket creation fails.
    ///
    /// @param iface reference to interface structure.
    /// @param addr an address the created socket should be bound to
    /// @param port a port that created socket should be bound to
570
571
    /// @param receive_bcast configure socket to receive broadcast messages
    /// @param send_bcast configure socket to send broadcast messages.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
572
573
    ///
    /// @return socket descriptor
574
575
    int openSocket4(Iface& iface, const isc::asiolink::IOAddress& addr, uint16_t port,
                    bool receive_bcast = false, bool send_bcast = false);
576

Tomek Mrugalski's avatar
Tomek Mrugalski committed
577
578
579
580
581
582
583
584
585
586
587
    /// @brief Opens IPv6 socket.
    ///
    /// Please do not use this method directly. Use openSocket instead.
    ///
    /// This method may throw exception if socket creation fails.
    ///
    /// @param iface reference to interface structure.
    /// @param addr an address the created socket should be bound to
    /// @param port a port that created socket should be bound to
    ///
    /// @return socket descriptor
Tomek Mrugalski's avatar
Tomek Mrugalski committed
588
    int openSocket6(Iface& iface, const isc::asiolink::IOAddress& addr, uint16_t port);
589

Tomek Mrugalski's avatar
Tomek Mrugalski committed
590
591
592
    /// @brief Adds an interface to list of known interfaces.
    ///
    /// @param iface reference to Iface object.
593
594
595
596
    void addInterface(const Iface& iface) {
        ifaces_.push_back(iface);
    }

597
598
599
600
601
602
603
604
    /// @brief Detects network interfaces.
    ///
    /// This method will eventually detect available interfaces. For now
    /// it offers stub implementation. First interface name and link-local
    /// IPv6 address is read from intefaces.txt file.
    void
    detectIfaces();

605
606
607
608
609
610
611
612
613
    /// @brief Stub implementation of network interface detection.
    ///
    /// This implementations reads a single line from interfaces.txt file
    /// and pretends to detect such interface. First interface name and
    /// link-local IPv6 address or IPv4 address is read from the
    /// intefaces.txt file.
    void
    stubDetectIfaces();

614
615
616
617
    // TODO: having 2 maps (ifindex->iface and ifname->iface would)
    //      probably be better for performance reasons

    /// List of available interfaces
618
    IfaceCollection ifaces_;
619
620
621
622

    // TODO: Also keep this interface on Iface once interface detection
    // is implemented. We may need it e.g. to close all sockets on
    // specific interface
623
624
625
    //int recvsock_; // TODO: should be fd_set eventually, but we have only
    //int sendsock_; // 2 sockets for now. Will do for until next release

626
627
628
629
    // we can't use the same socket, as receiving socket
    // is bound to multicast address. And we all know what happens
    // to people who try to use multicast as source address.

630
    /// length of the control_buf_ array
631
    size_t control_buf_len_;
632

633
634
635
    /// control-buffer, used in transmission and reception
    boost::scoped_array<char> control_buf_;

636
637
638
639
640
641
642
    /// @brief A wrapper for OS-specific operations before sending IPv4 packet
    ///
    /// @param m message header (will be later used for sendmsg() call)
    /// @param control_buf buffer to be used during transmission
    /// @param control_buf_len buffer length
    /// @param pkt packet to be sent
    void os_send4(struct msghdr& m, boost::scoped_array<char>& control_buf,
643
                  size_t control_buf_len, const Pkt4Ptr& pkt);
644
645
646
647
648
649
650
651
652

    /// @brief OS-specific operations during IPv4 packet reception
    ///
    /// @param m message header (was used during recvmsg() call)
    /// @param pkt packet received (some fields will be set here)
    ///
    /// @return true if successful, false otherwise
    bool os_receive4(struct msghdr& m, Pkt4Ptr& pkt);

653
654
655
656
657
    /// socket descriptor of the session socket
    int session_socket_;

    /// a callback that will be called when data arrives over session_socket_
    SessionCallback session_callback_;
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
private:

    /// @brief Joins IPv6 multicast group on a socket.
    ///
    /// Socket must be created and bound to an address. Note that this
    /// address is different than the multicast address. For example DHCPv6
    /// server should bind its socket to link-local address (fe80::1234...)
    /// and later join ff02::1:2 multicast group.
    ///
    /// @param sock socket fd (socket must be bound)
    /// @param ifname interface name (for link-scoped multicast groups)
    /// @param mcast multicast address to join (e.g. "ff02::1:2")
    ///
    /// @return true if multicast join was successful
    ///
    bool
674
675
    joinMulticast(int sock, const std::string& ifname,
                  const std::string& mcast);
676

677
678
679
680
681
    /// @brief Identifies local network address to be used to
    /// connect to remote address.
    ///
    /// This method identifies local network address that can be used
    /// to connect to remote address specified.
682
    /// It first creates socket and makes attempt to connect
683
684
685
686
687
688
689
    /// to remote location via this socket. If connection
    /// is established successfully, the local address to which
    /// socket is bound is returned.
    ///
    /// @param remote_addr remote address to connect to
    /// @param port port to be used
    /// @return local address to be used to connect to remote address
690
    /// @throw isc::Unexpected if unable to indentify local address
691
692
693
    isc::asiolink::IOAddress
    getLocalAddress(const isc::asiolink::IOAddress& remote_addr,
                    const uint16_t port);
694
695
696
};

}; // namespace isc::dhcp
697
}; // namespace isc
698

699
#endif // IFACE_MGR_H