iface_mgr.h 51 KB
 Francis Dupont committed Feb 09, 2017 1 // Copyright (C) 2011-2015,2017 Internet Systems Consortium, Inc. ("ISC")  Tomek Mrugalski committed Jun 30, 2011 2 //  Marcin Siodelski committed Dec 16, 2015 3 4 5 // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/.  Tomek Mrugalski committed Jun 30, 2011 6 7 8 9  #ifndef IFACE_MGR_H #define IFACE_MGR_H  Tomek Mrugalski committed Nov 08, 2011 10 #include  Tomek Mrugalski committed Dec 07, 2011 11 #include  Stephen Morris committed Nov 16, 2012 12 #include  Tomek Mrugalski committed Nov 08, 2011 13 14 #include #include  Marcin Siodelski committed Apr 03, 2013 15 #include  Marcin Siodelski committed Dec 12, 2013 16 #include  Marcin Siodelski committed Dec 17, 2014 17 #include  Tomek Mrugalski committed Jun 30, 2011 18   Marcin Siodelski committed Nov 28, 2013 19 #include  Stephen Morris committed Nov 16, 2012 20 21 22 23 24 #include #include #include #include  Francis Dupont committed Feb 16, 2015 25 #include  Stephen Morris committed Nov 16, 2012 26   Tomek Mrugalski committed Jun 30, 2011 27 28 namespace isc {  Tomek Mrugalski committed Oct 14, 2011 29 namespace dhcp {  Marcin Siodelski committed Sep 25, 2012 30   Marcin Siodelski committed Jan 15, 2014 31   Marcin Siodelski committed Sep 25, 2012 32 33 34 35 36 37 38 /// @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) { }; };  Marcin Siodelski committed Apr 26, 2013 39 40 41 42 43 44 45 /// @brief Exception thrown when it is not allowed to set new Packet Filter. class PacketFilterChangeDenied : public Exception { public: PacketFilterChangeDenied(const char* file, size_t line, const char* what) : isc::Exception(file, line, what) { }; };  Marcin Siodelski committed Aug 13, 2014 46 47 48 49 50 51 52 /// @brief Exception thrown when a call to select is interrupted by a signal. class SignalInterruptOnSelect : public Exception { public: SignalInterruptOnSelect(const char* file, size_t line, const char* what) : isc::Exception(file, line, what) { }; };  Marcin Siodelski committed Sep 25, 2012 53 54 55 56 57 58 59 60 /// @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) { }; };  Andrei Pavel committed Dec 14, 2016 61 /// @brief IfaceMgr exception thrown thrown when error occurred during  Marcin Siodelski committed Sep 25, 2012 62 63 64 65 66 67 68 /// reading data from socket. class SocketReadError : public Exception { public: SocketReadError(const char* file, size_t line, const char* what) : isc::Exception(file, line, what) { }; };  Andrei Pavel committed Dec 14, 2016 69 /// @brief IfaceMgr exception thrown thrown when error occurred during  Josh Soref committed Jul 23, 2017 70 /// sending data through socket.  Marcin Siodelski committed Sep 25, 2012 71 72 73 74 75 76 class SocketWriteError : public Exception { public: SocketWriteError(const char* file, size_t line, const char* what) : isc::Exception(file, line, what) { }; };  Marcin Siodelski committed Feb 13, 2015 77 78 79 80 81 82 83 84 85 86 87 88 89 90 /// @brief IfaceMgr exception thrown when there is no suitable interface. class IfaceNotFound : public Exception { public: IfaceNotFound(const char* file, size_t line, const char* what) : isc::Exception(file, line, what) { }; }; /// @brief IfaceMgr exception thrown when there is no suitable socket found. class SocketNotFound : public Exception { public: SocketNotFound(const char* file, size_t line, const char* what) : isc::Exception(file, line, what) { }; };  Marcin Siodelski committed Aug 13, 2014 91   Marcin Siodelski committed Apr 03, 2013 92 93 /// Holds information about socket. struct SocketInfo {  Marcin Siodelski committed Nov 25, 2013 94   Marcin Siodelski committed Apr 03, 2013 95 96 97 98  isc::asiolink::IOAddress addr_; /// bound address uint16_t port_; /// socket port uint16_t family_; /// IPv4 or IPv6  Marcin Siodelski committed Nov 25, 2013 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125  /// @brief Socket descriptor (a.k.a. primary socket). int sockfd_; /// @brief Fallback socket descriptor. /// /// This socket descriptor holds the handle to the fallback socket. /// The fallback socket is created when there is a need for the regular /// datagram socket to be bound to an IP address and port, besides /// primary socket (sockfd_) which is actually used to receive and process /// the DHCP messages. The fallback socket (if exists) is always associated /// with the primary socket. In particular, the need for the fallback socket /// arises when raw socket is a primary one. When primary socket is open, /// it is bound to an interface not the address and port. The implications /// include the possibility that the other process (e.g. the other instance /// of DHCP server) will bind to the same address and port through which the /// raw socket receives the DHCP messages.Another implication is that the /// kernel, being unaware of the DHCP server operating through the raw /// socket, will respond with the ICMP "Destination port unreachable" /// messages when DHCP messages are only received through the raw socket. /// In order to workaround the issues mentioned here, the fallback socket /// should be opened so as/ the kernel is aware that the certain address /// and port is in use. /// /// The fallback description is supposed to be set to a negative value if /// the fallback socket is closed (not open). int fallbackfd_;  Marcin Siodelski committed Apr 03, 2013 126 127  /// @brief SocketInfo constructor. ///  Marcin Siodelski committed Nov 25, 2013 128 129 130 131 132 133 134 135 136  /// @param addr An address the socket is bound to. /// @param port A port the socket is bound to. /// @param sockfd Socket descriptor. /// @param fallbackfd A descriptor of the fallback socket. SocketInfo(const isc::asiolink::IOAddress& addr, const uint16_t port, const int sockfd, const int fallbackfd = -1) : addr_(addr), port_(port), family_(addr.getFamily()), sockfd_(sockfd), fallbackfd_(fallbackfd) { }  Marcin Siodelski committed Apr 03, 2013 137 138 };  Marcin Siodelski committed May 21, 2013 139 /// @brief Represents a single network interface  Tomek Mrugalski committed Oct 14, 2011 140 ///  Marcin Siodelski committed Apr 03, 2013 141 142 143 /// Iface structure represents network interface with all useful /// information, like name, interface index, MAC address and /// list of assigned addresses  Marcin Siodelski committed Jul 08, 2014 144 145 146 147 148 149 150 151 152 /// /// This class also holds the pointer to the socket read buffer. /// Functions reading from the socket may utilize this buffer to store the /// data being read from the socket. The advantage of using the /// pre-allocated buffer is that the buffer is allocated only once, rather /// than on every read. In addition, some OS specific code (e.g. BPF) /// may require use of fixed-size buffers. The size of such a buffer is /// returned by the OS kernel when the socket is opened. Hence, it is /// convenient to allocate the buffer when the socket is being opened and  Josh Soref committed Jul 23, 2017 153 /// utilize it throughout the lifetime of the socket.  Marcin Siodelski committed Mar 13, 2015 154 155 156 157 /// /// In order to avoid potentially expensive copies of the @c Iface objects /// holding pre-allocated buffers and multiple containers, this class is /// noncopyable.  Marcin Siodelski committed Mar 13, 2015 158 class Iface : public boost::noncopyable {  Tomek Mrugalski committed Oct 14, 2011 159 public:  Tomek Mrugalski committed May 30, 2012 160   Marcin Siodelski committed May 21, 2013 161  /// Maximum MAC address length (Infiniband uses 20 bytes)  Tomek Mrugalski committed Oct 14, 2011 162 163  static const unsigned int MAX_MAC_LEN = 20;  Marcin Siodelski committed Mar 13, 2015 164 165 166  /// @brief Address type. typedef util::OptionalValue Address;  Marcin Siodelski committed May 21, 2013 167  /// Type that defines list of addresses  Marcin Siodelski committed Mar 13, 2015 168  typedef std::list
AddressCollection;  Tomek Mrugalski committed Mar 13, 2012 169   Marcin Siodelski committed May 21, 2013 170 171 172 173 174 175 176 177  /// @brief Type that holds a list of socket information. /// /// @warning The type of the container used here must guarantee /// that the iterators do not invalidate when erase() is called. /// This is because, the \ref closeSockets function removes /// elements selectively by calling erase on the element to be /// removed and further iterates through remaining elements. ///  Tomek Mrugalski committed Sep 10, 2012 178  /// @todo: Add SocketCollectionConstIter type  Tomek Mrugalski committed Nov 09, 2011 179 180  typedef std::list SocketCollection;  Marcin Siodelski committed Apr 03, 2013 181 182 183 184 185 186 187 188  /// @brief Iface constructor. /// /// Creates Iface object that represents network interface. /// /// @param name name of the interface /// @param ifindex interface index (unique integer identifier) Iface(const std::string& name, int ifindex);  Marcin Siodelski committed Jul 07, 2014 189  /// @brief Destructor.  Francis Dupont committed Feb 16, 2015 190  ~Iface() { }  Marcin Siodelski committed Jul 07, 2014 191   Marcin Siodelski committed Apr 03, 2013 192 193  /// @brief Closes all open sockets on interface. void closeSockets();  Tomek Mrugalski committed Sep 10, 2012 194   Marcin Siodelski committed Apr 26, 2013 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215  /// @brief Closes all IPv4 or IPv6 sockets. /// /// This function closes sockets of the specific 'type' and closes them. /// The 'type' of the socket indicates whether it is used to send IPv4 /// or IPv6 packets. The allowed values of the parameter are AF_INET and /// AF_INET6 for IPv4 and IPv6 packets respectively. It is important /// to realize that the actual types of sockets may be different than /// AF_INET for IPv4 packets. This is because, historically the IfaceMgr /// always used AF_INET sockets for IPv4 traffic. This is no longer the /// case when the Direct IPv4 traffic must be supported. In order to support /// direct traffic, the IfaceMgr operates on raw sockets, e.g. AF_PACKET /// family sockets on Linux. /// /// @todo Replace the AF_INET and AF_INET6 values with an enum /// which will not be confused with the actual socket type. /// /// @param family type of the sockets to be closed (AF_INET or AF_INET6) /// /// @throw BadValue if family value is different than AF_INET or AF_INET6. void closeSockets(const uint16_t family);  Marcin Siodelski committed Apr 03, 2013 216  /// @brief Returns full interface name as "ifname/ifindex" string.  Tomek Mrugalski committed Oct 14, 2011 217  ///  Marcin Siodelski committed Apr 03, 2013 218 219  /// @return string with interface name std::string getFullName() const;  Tomek Mrugalski committed Oct 14, 2011 220   Marcin Siodelski committed Apr 03, 2013 221 222 223 224  /// @brief Returns link-layer address a plain text. /// /// @return MAC address as a plain text (string) std::string getPlainMac() const;  Marcin Siodelski committed Aug 03, 2012 225   Marcin Siodelski committed Apr 03, 2013 226 227 228 229 230  /// @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);  Tomek Mrugalski committed Oct 14, 2011 231   Marcin Siodelski committed Apr 03, 2013 232 233 234 235  /// @brief Returns MAC length. /// /// @return length of MAC address size_t getMacLen() const { return mac_len_; }  Tomek Mrugalski committed Jun 30, 2011 236   Marcin Siodelski committed Apr 03, 2013 237 238 239 240 241  /// @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_; }  Tomek Mrugalski committed Mar 16, 2012 242   Marcin Siodelski committed Apr 03, 2013 243 244  /// @brief Sets flag_*_ fields based on bitmask value returned by OS ///  Marcin Siodelski committed May 21, 2013 245  /// @note Implementation of this method is OS-dependent as bits have  Marcin Siodelski committed Apr 03, 2013 246  /// different meaning on each OS.  Tomek Mrugalski committed Oct 22, 2013 247  /// We need to make it 64 bits, because Solaris uses 64, not 32 bits.  Marcin Siodelski committed Apr 03, 2013 248 249  /// /// @param flags bitmask value returned by OS in interface detection  Tomek Mrugalski committed Oct 22, 2013 250  void setFlags(uint64_t flags);  Tomek Mrugalski committed Mar 16, 2012 251   Marcin Siodelski committed Apr 03, 2013 252 253 254 255  /// @brief Returns interface index. /// /// @return interface index uint16_t getIndex() const { return ifindex_; }  Tomek Mrugalski committed Mar 16, 2012 256   Marcin Siodelski committed Apr 03, 2013 257 258 259 260  /// @brief Returns interface name. /// /// @return interface name std::string getName() const { return name_; };  Tomek Mrugalski committed Nov 30, 2011 261   Marcin Siodelski committed Apr 03, 2013 262 263 264 265  /// @brief Sets up hardware type of the interface. /// /// @param type hardware type void setHWType(uint16_t type ) { hardware_type_ = type; }  Tomek Mrugalski committed Nov 08, 2011 266   Marcin Siodelski committed Apr 03, 2013 267 268 269 270  /// @brief Returns hardware type of the interface. /// /// @return hardware type uint16_t getHWType() const { return hardware_type_; }  Tomek Mrugalski committed Nov 09, 2011 271   Marcin Siodelski committed Dec 17, 2014 272 273 274 275 276 277 278 279 280  /// @brief Returns all addresses available on an interface. /// /// The returned addresses are encapsulated in the @c util::OptionalValue /// class to be able to selectively flag some of the addresses as active /// (when optional value is specified) or inactive (when optional value /// is specified). If the address is marked as active, the /// @c IfaceMgr::openSockets4 method will open socket and bind to this /// address. Otherwise, it will not bind any socket to this address. /// This is useful when an interface has multiple IPv4 addresses assigned.  Marcin Siodelski committed Apr 03, 2013 281 282 283 284 285 286 287 288 289 290  /// /// 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 const AddressCollection& getAddresses() const { return addrs_; }  Tomek Mrugalski committed Mar 16, 2012 291   Marcin Siodelski committed Jan 30, 2014 292 293 294 295 296 297 298 299 300 301 302  /// @brief Returns IPv4 address assigned to the interface. /// /// This function looks for an IPv4 address assigned to the interface /// and returns it through the argument. /// /// @param [out] address IPv4 address assigned to the interface. /// /// @return Boolean value which informs whether IPv4 address has been found /// for the interface (if true), or not (false). bool getAddress4(isc::asiolink::IOAddress& address) const;  Marcin Siodelski committed Aug 20, 2014 303 304 305  /// @brief Check if the interface has the specified address assigned. /// /// @param address Address to be checked.  Andrei Pavel committed Dec 14, 2016 306  /// @return true if address is assigned to the interface, false otherwise.  Marcin Siodelski committed Aug 20, 2014 307 308  bool hasAddress(const isc::asiolink::IOAddress& address) const;  Marcin Siodelski committed Apr 03, 2013 309 310 311 312 313 314  /// @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  Marcin Siodelski committed Dec 17, 2014 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338  void addAddress(const isc::asiolink::IOAddress& addr); /// @brief Activates or deactivates address for the interface. /// /// This method marks a specified address on the interface active or /// inactive. If the address is marked inactive, the /// @c IfaceMgr::openSockets4 method will NOT open socket for this address. /// /// @param address An address which should be activated, deactivated. /// @param active A boolean flag which indicates that the specified address /// should be active (if true) or inactive (if false). /// /// @throw BadValue if specified address doesn't exist for the interface. void setActive(const isc::asiolink::IOAddress& address, const bool active); /// @brief Activates or deactivates all addresses for the interface. /// /// This method marks all addresses on the interface active or inactive. /// If the address is marked inactive, the @c IfaceMgr::openSockets4 /// method will NOT open socket for this address. /// /// @param active A boolean flag which indicates that the addresses /// should be active (if true) or inactive (if false). void setActive(const bool active);  Tomek Mrugalski committed Mar 16, 2012 339   Marcin Siodelski committed Feb 13, 2015 340  /// @brief Returns a number of activated IPv4 addresses on the interface.  Marcin Siodelski committed Feb 16, 2015 341  unsigned int countActive4() const;  Marcin Siodelski committed Feb 13, 2015 342   Marcin Siodelski committed Apr 03, 2013 343 344 345 346 347 348 349 350 351 352  /// @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 bool delAddress(const isc::asiolink::IOAddress& addr);  Tomek Mrugalski committed Nov 08, 2011 353   Marcin Siodelski committed Apr 03, 2013 354 355 356 357 358 359  /// @brief Adds socket descriptor to an interface. /// /// @param sock SocketInfo structure that describes socket. void addSocket(const SocketInfo& sock) { sockets_.push_back(sock); }  Tomek Mrugalski committed Nov 08, 2011 360   Marcin Siodelski committed Apr 03, 2013 361 362 363 364 365 366 367 368  /// @brief Closes socket. /// /// Closes socket and removes corresponding SocketInfo structure /// from an interface. /// /// @param sockfd socket descriptor to be closed/removed. /// @return true if there was such socket, false otherwise bool delSocket(uint16_t sockfd);  Tomek Mrugalski committed Nov 08, 2011 369   Marcin Siodelski committed Apr 03, 2013 370 371 372 373 374 375 376 377 378 379 380 381 382 383  /// @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. /// The returned reference is only valid during the lifetime of /// the IfaceMgr object that returned it. /// /// @return collection of sockets added to interface const SocketCollection& getSockets() const { return sockets_; }  Tomek Mrugalski committed Nov 09, 2011 384   Tomek Mrugalski committed Oct 22, 2013 385 386 387 388  /// @brief Removes any unicast addresses /// /// Removes any unicast addresses that the server was configured to /// listen on  Tomek Mrugalski committed Oct 15, 2013 389 390 391 392  void clearUnicasts() { unicasts_.clear(); }  Tomek Mrugalski committed Oct 22, 2013 393 394 395 396 397  /// @brief Adds unicast the server should listen on /// /// @throw BadValue if specified address is already defined on interface /// @param addr unicast address to listen on void addUnicast(const isc::asiolink::IOAddress& addr);  Tomek Mrugalski committed Oct 15, 2013 398   Tomek Mrugalski committed Oct 22, 2013 399 400 401  /// @brief Returns a container of addresses the server should listen on /// /// @return address collection (may be empty)  Tomek Mrugalski committed Oct 15, 2013 402 403 404 405  const AddressCollection& getUnicasts() const { return unicasts_; }  Marcin Siodelski committed Jul 03, 2014 406 407 408 409 410  /// @brief Returns the pointer to the buffer used for data reading. /// /// The returned pointer is only valid during the lifetime of the /// object which returns it or until the buffer is resized. /// This function is meant to be used with socket API to gather  Marcin Siodelski committed Jul 07, 2014 411  /// data from the socket.  Marcin Siodelski committed Jul 03, 2014 412 413 414  /// /// @return Pointer to the first element of the read buffer or /// NULL if the buffer is empty.  Francis Dupont committed Feb 16, 2015 415 416 417 418 419  uint8_t* getReadBuffer() { if (read_buffer_.empty()) { return NULL; } return (&read_buffer_[0]);  Marcin Siodelski committed Jul 03, 2014 420 421 422 423  } /// @brief Returns the current size of the socket read buffer. size_t getReadBufferSize() const {  Francis Dupont committed Feb 16, 2015 424  return (read_buffer_.size());  Marcin Siodelski committed Jul 03, 2014 425 426  }  Marcin Siodelski committed Jul 08, 2014 427  /// @brief Reallocates the socket read buffer.  Marcin Siodelski committed Jul 03, 2014 428 429  /// /// @param new_size New size of the buffer.  Francis Dupont committed Feb 16, 2015 430 431 432  void resizeReadBuffer(const size_t new_size) { read_buffer_.resize(new_size); }  Marcin Siodelski committed Jul 03, 2014 433   Marcin Siodelski committed Apr 03, 2013 434 protected:  Marcin Siodelski committed May 21, 2013 435  /// Socket used to send data.  Marcin Siodelski committed Apr 03, 2013 436  SocketCollection sockets_;  Tomek Mrugalski committed Nov 09, 2011 437   Marcin Siodelski committed May 21, 2013 438  /// Network interface name.  Marcin Siodelski committed Apr 03, 2013 439  std::string name_;  Marcin Siodelski committed Aug 03, 2012 440   Andrei Pavel committed Dec 14, 2016 441  /// Interface index (a value that uniquely identifies an interface).  Marcin Siodelski committed Apr 03, 2013 442  int ifindex_;  Tomek Mrugalski committed Nov 09, 2011 443   Marcin Siodelski committed May 21, 2013 444  /// List of assigned addresses.  Marcin Siodelski committed Apr 03, 2013 445  AddressCollection addrs_;  Tomek Mrugalski committed Oct 14, 2011 446   Tomek Mrugalski committed Oct 15, 2013 447 448 449  /// List of unicast addresses the server should listen on AddressCollection unicasts_;  Marcin Siodelski committed May 21, 2013 450  /// Link-layer address.  Marcin Siodelski committed Apr 03, 2013 451  uint8_t mac_[MAX_MAC_LEN];  Tomek Mrugalski committed Oct 14, 2011 452   Marcin Siodelski committed May 21, 2013 453  /// Length of link-layer address (usually 6).  Marcin Siodelski committed Apr 03, 2013 454  size_t mac_len_;  Tomek Mrugalski committed Oct 14, 2011 455   Marcin Siodelski committed May 21, 2013 456  /// Hardware type.  Marcin Siodelski committed Apr 03, 2013 457  uint16_t hardware_type_;  Tomek Mrugalski committed Oct 14, 2011 458   Marcin Siodelski committed Apr 03, 2013 459 460 461 public: /// @todo: Make those fields protected once we start supporting more /// than just Linux  Tomek Mrugalski committed Mar 16, 2012 462   Marcin Siodelski committed May 21, 2013 463  /// Specifies if selected interface is loopback.  Marcin Siodelski committed Apr 03, 2013 464  bool flag_loopback_;  Tomek Mrugalski committed Oct 14, 2011 465   Marcin Siodelski committed May 21, 2013 466  /// Specifies if selected interface is up.  Marcin Siodelski committed Apr 03, 2013 467  bool flag_up_;  Tomek Mrugalski committed Mar 16, 2012 468   Marcin Siodelski committed May 21, 2013 469 470  /// Flag specifies if selected interface is running /// (e.g. cable plugged in, wifi associated).  Marcin Siodelski committed Apr 03, 2013 471  bool flag_running_;  Tomek Mrugalski committed Nov 30, 2011 472   Marcin Siodelski committed May 21, 2013 473  /// Flag specifies if selected interface is multicast capable.  Marcin Siodelski committed Apr 03, 2013 474  bool flag_multicast_;  Tomek Mrugalski committed Nov 30, 2011 475   Marcin Siodelski committed May 21, 2013 476  /// Flag specifies if selected interface is broadcast capable.  Marcin Siodelski committed Apr 03, 2013 477  bool flag_broadcast_;  Tomek Mrugalski committed Nov 30, 2011 478   Marcin Siodelski committed May 21, 2013 479 480  /// Interface flags (this value is as is returned by OS, /// it may mean different things on different OSes).  Tomek Mrugalski committed Oct 22, 2013 481 482 483  /// Solaris based os have unsigned long flags field (64 bits). /// It is usually 32 bits, though. uint64_t flags_;  Marcin Siodelski committed Jul 11, 2013 484   Marcin Siodelski committed Jul 11, 2013 485 486 487 488 489 490 491  /// Indicates that IPv4 sockets should (true) or should not (false) /// be opened on this interface. bool inactive4_; /// Indicates that IPv6 sockets should (true) or should not (false) /// be opened on this interface. bool inactive6_;  Marcin Siodelski committed Jul 03, 2014 492   Marcin Siodelski committed Jul 08, 2014 493 494 private:  Francis Dupont committed Feb 16, 2015 495  /// @brief The buffer holding the data read from the socket.  Marcin Siodelski committed Jul 03, 2014 496  ///  Marcin Siodelski committed Jul 08, 2014 497  /// See @c Iface manager description for details.  Francis Dupont committed Feb 16, 2015 498  std::vector read_buffer_;  Marcin Siodelski committed Apr 03, 2013 499 };  Tomek Mrugalski committed Nov 30, 2011 500   Marcin Siodelski committed Mar 13, 2015 501 502 typedef boost::shared_ptr IfacePtr;  Marcin Siodelski committed Sep 18, 2015 503 504 505 506 507 508 /// @brief Forward declaration to the @c IfaceMgr. class IfaceMgr; /// @brief Type definition for the pointer to the @c IfaceMgr. typedef boost::shared_ptr IfaceMgrPtr;  Marcin Siodelski committed Nov 28, 2013 509 510 511 512 513 514 515 /// @brief This type describes the callback function invoked when error occurs /// in the IfaceMgr. /// /// @param errmsg An error message. typedef boost::function IfaceMgrErrorMsgCallback;  Marcin Siodelski committed May 21, 2013 516 /// @brief Handles network interfaces, transmission and reception.  Tomek Mrugalski committed Oct 14, 2011 517 518 519 520 521 522 523 /// /// 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:  Tomek Mrugalski committed Feb 03, 2014 524 525  /// Defines callback used when data is received over external sockets. typedef boost::function SocketCallback;  Tomek Mrugalski committed May 30, 2012 526   Tomek Mrugalski committed Jan 30, 2014 527  /// Keeps callback information for external sockets.  Tomek Mrugalski committed Feb 03, 2014 528  struct SocketCallbackInfo {  Tomek Mrugalski committed Jan 30, 2014 529 530 531 532  /// Socket descriptor of the external socket. int socket_; /// A callback that will be called when data arrives over socket_.  Tomek Mrugalski committed Feb 03, 2014 533  SocketCallback callback_;  Tomek Mrugalski committed Jan 30, 2014 534 535 536  }; /// Defines storage container for callbacks for external sockets  Tomek Mrugalski committed Feb 04, 2014 537  typedef std::list SocketCallbackInfoContainer;  Tomek Mrugalski committed Jan 30, 2014 538   Tomek Mrugalski committed Mar 13, 2012 539 540 541 542 543 544 545 546 547  /// @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;  Tomek Mrugalski committed Oct 14, 2011 548 549 550 551  // 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)  Marcin Siodelski committed Mar 13, 2015 552  /// Type that holds a list of pointers to interfaces.  Marcin Siodelski committed Mar 13, 2015 553  typedef std::list IfaceCollection;  Tomek Mrugalski committed Oct 14, 2011 554 555 556 557 558 559 560  /// IfaceMgr is a singleton class. This method returns reference /// to its sole instance. /// /// @return the only existing instance of interface manager static IfaceMgr& instance();  Marcin Siodelski committed Sep 18, 2015 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577  /// @brief Returns pointer to the sole instance of the interface manager. /// /// This method returns the pointer to the instance of the interface manager /// which can be held in singleton objects that depend on it. This will /// eliminate issues with the static deinitialization fiasco between this /// object and dependent singleton objects. /// /// The @c IfaceMgr::instance method should be considered deprecated. /// /// @return Shared pointer to the @c IfaceMgr instance. static const IfaceMgrPtr& instancePtr(); /// @brief Destructor. /// /// Closes open sockets. virtual ~IfaceMgr();  Marcin Siodelski committed Feb 10, 2015 578 579  /// @brief Sets or clears the test mode for @c IfaceMgr. ///  Marcin Siodelski committed Sep 18, 2015 580  /// Various unit test may set this flag to true, to indicate that the  Marcin Siodelski committed Feb 10, 2015 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597  /// @c IfaceMgr is in the test mode. There are places in the code that /// modify the behavior depending if the @c IfaceMgr is in the test /// mode or not. /// /// @param test_mode A flag which indicates that the @c IfaceMgr is in the /// test mode (if true), or not (if false). void setTestMode(const bool test_mode) { test_mode_ = test_mode; } /// @brief Checks if the @c IfaceMgr is in the test mode. /// /// @return true if the @c IfaceMgr is in the test mode, false otherwise. bool isTestMode() const { return (test_mode_); }  Marcin Siodelski committed Apr 04, 2013 598  /// @brief Check if packet be sent directly to the client having no address.  Marcin Siodelski committed Mar 28, 2013 599 600 601 602 603 604 605  /// /// 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.  Marcin Siodelski committed Apr 25, 2013 606  bool isDirectResponseSupported() const;  Marcin Siodelski committed Mar 28, 2013 607   Marcin Siodelski committed Mar 13, 2015 608  /// @brief Returns interface specified interface index  Tomek Mrugalski committed Oct 14, 2011 609 610 611 612 613 614  /// /// @param ifindex index of searched interface /// /// @return interface with requested index (or NULL if no such /// interface is present) ///  Marcin Siodelski committed Mar 13, 2015 615  IfacePtr getIface(int ifindex);  Tomek Mrugalski committed Oct 14, 2011 616 617 618 619 620 621 622  /// @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)  Marcin Siodelski committed Mar 13, 2015 623  IfacePtr getIface(const std::string& ifname);  Tomek Mrugalski committed Oct 14, 2011 624   Tomek Mrugalski committed Feb 17, 2012 625 626  /// @brief Returns container with all interfaces. ///  Tomek Mrugalski committed Mar 08, 2012 627 628 629 630  /// 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 committed Feb 17, 2012 631  /// @return container with all interfaces.  Marcin Siodelski committed Jan 02, 2014 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647  const IfaceCollection& getIfaces() { return (ifaces_); } /// @brief Removes detected interfaces. /// /// This method removes all detected interfaces. This method should be /// used by unit tests to supply a custom set of interfaces. For example: /// a unit test may create a pool of fake interfaces and use the custom /// @c PktFilter class to mimic socket operation on these interfaces. void clearIfaces(); /// @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 interfaces.txt file. void detectIfaces();  Tomek Mrugalski committed Feb 17, 2012 648   Marcin Siodelski committed Aug 20, 2014 649 650 651  /// @brief Clears unicast addresses on all interfaces. void clearUnicasts();  Tomek Mrugalski committed Nov 09, 2011 652 653 654 655  /// @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  Marcin Siodelski committed Feb 13, 2015 656 657 658  /// may throw if specified packet does not have outbound interface specified, /// no such interface exists, or specified interface does not have any /// appropriate sockets open.  Tomek Mrugalski committed Nov 09, 2011 659 660 661 662  /// /// @param pkt a packet to be transmitted /// /// @return a socket descriptor  Marcin Siodelski committed Feb 13, 2015 663 664  /// @throw SocketNotFound If no suitable socket found. /// @throw IfaceNotFound If interface is not set for the packet.  Tomek Mrugalski committed Nov 09, 2011 665 666  uint16_t getSocket(const isc::dhcp::Pkt6& pkt);  Marcin Siodelski committed Jan 02, 2014 667  /// @brief Return most suitable socket for transmitting specified IPv4 packet.  Tomek Mrugalski committed Nov 09, 2011 668  ///  Marcin Siodelski committed Feb 13, 2015 669 670 671 672 673  /// This method uses the local address assigned to the packet and tries /// to match it with addresses to which sockets are bound for the particular /// interface. If the match is not found, the method returns the first IPv4 /// socket found for the particular interface. In case, there are no IPv4 /// sockets assigned to the interface the exception is thrown.  Tomek Mrugalski committed Nov 09, 2011 674  ///  Marcin Siodelski committed Feb 13, 2015 675 676  /// @param pkt A packet to be transmitted. It must hold a local address and /// a valid pointer to the interface.  Tomek Mrugalski committed Nov 09, 2011 677  ///  Marcin Siodelski committed Jan 02, 2014 678  /// @return A structure describing a socket.  Marcin Siodelski committed Feb 13, 2015 679  /// @throw SocketNotFound if no suitable socket found.  Marcin Siodelski committed Jan 02, 2014 680  SocketInfo getSocket(const isc::dhcp::Pkt4& pkt);  Tomek Mrugalski committed Nov 09, 2011 681   Marcin Siodelski committed May 21, 2013 682  /// Debugging method that prints out all available interfaces.  Tomek Mrugalski committed Oct 14, 2011 683 684  /// /// @param out specifies stream to print list of interfaces to  Marcin Siodelski committed May 21, 2013 685  void printIfaces(std::ostream& out = std::cout);  Tomek Mrugalski committed Oct 14, 2011 686   Tomek Mrugalski committed Dec 05, 2011 687  /// @brief Sends an IPv6 packet.  Tomek Mrugalski committed Oct 14, 2011 688  ///  Tomek Mrugalski committed Dec 05, 2011 689  /// Sends an IPv6 packet. All parameters for actual transmission are specified in  Tomek Mrugalski committed Oct 14, 2011 690 691  /// Pkt6 structure itself. That includes destination address, src/dst port /// and interface over which data will be sent.  Tomek Mrugalski committed Oct 14, 2011 692 693 694  /// /// @param pkt packet to be sent ///  Marcin Siodelski committed Sep 26, 2012 695 696  /// @throw isc::BadValue if invalid interface specified in the packet. /// @throw isc::dhcp::SocketWriteError if sendmsg() failed to send packet.  Tomek Mrugalski committed Oct 14, 2011 697  /// @return true if sending was successful  Tomek Mrugalski committed Feb 17, 2012 698  bool send(const Pkt6Ptr& pkt);  Tomek Mrugalski committed Oct 14, 2011 699   Tomek Mrugalski committed Dec 05, 2011 700 701 702 703 704 705 706 707  /// @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 ///  Marcin Siodelski committed Sep 26, 2012 708 709  /// @throw isc::BadValue if invalid interface specified in the packet. /// @throw isc::dhcp::SocketWriteError if sendmsg() failed to send packet.  Tomek Mrugalski committed Dec 05, 2011 710  /// @return true if sending was successful  Tomek Mrugalski committed Feb 17, 2012 711  bool send(const Pkt4Ptr& pkt);  Tomek Mrugalski committed Nov 08, 2011 712   Marcin Siodelski committed Aug 13, 2014 713  /// @brief Tries to receive DHCPv6 message over open IPv6 sockets.  Tomek Mrugalski committed Oct 14, 2011 714  ///  Marcin Siodelski committed Aug 13, 2014 715 716 717  /// Attempts to receive a single DHCPv6 message over any of the open IPv6 /// sockets. If reception is successful and all information about its /// sender is obtained, Pkt6 object is created and returned.  Tomek Mrugalski committed Oct 14, 2011 718  ///  Marcin Siodelski committed Aug 18, 2014 719 720 721  /// This method also checks if data arrived over registered external socket. /// This data may be of a different protocol family than AF_INET6. ///  Marcin Siodelski committed Sep 11, 2012 722 723 724  /// @param timeout_sec specifies integral part of the timeout (in seconds) /// @param timeout_usec specifies fractional part of the timeout /// (in microseconds)  Tomek Mrugalski committed Jun 22, 2012 725  ///  Marcin Siodelski committed Sep 11, 2012 726  /// @throw isc::BadValue if timeout_usec is greater than one million  Andrei Pavel committed Dec 14, 2016 727  /// @throw isc::dhcp::SocketReadError if error occurred when receiving a  Marcin Siodelski committed Aug 13, 2014 728 729 730 731  /// packet. /// @throw isc::dhcp::SignalInterruptOnSelect when a call to select() is /// interrupted by a signal. ///  Tomek Mrugalski committed Oct 14, 2011 732  /// @return Pkt6 object representing received packet (or NULL)  Marcin Siodelski committed Sep 11, 2012 733  Pkt6Ptr receive6(uint32_t timeout_sec, uint32_t timeout_usec = 0);  Tomek Mrugalski committed Nov 08, 2011 734   Tomek Mrugalski committed Dec 05, 2011 735 736  /// @brief Tries to receive IPv4 packet over open IPv4 sockets. ///  Marcin Siodelski committed Aug 13, 2014 737 738 739  /// Attempts to receive a single DHCPv4 message over any of the open /// IPv4 sockets. If reception is successful and all information about /// its sender is obtained, Pkt4 object is created and returned.  Tomek Mrugalski committed Dec 05, 2011 740  ///  Marcin Siodelski committed Aug 18, 2014 741 742 743  /// This method also checks if data arrived over registered external socket. /// This data may be of a different protocol family than AF_INET. ///  Marcin Siodelski committed Sep 11, 2012 744 745 746  /// @param timeout_sec specifies integral part of the timeout (in seconds) /// @param timeout_usec specifies fractional part of the timeout /// (in microseconds)  Tomek Mrugalski committed Dec 05, 2011 747  ///  Marcin Siodelski committed Sep 11, 2012 748  /// @throw isc::BadValue if timeout_usec is greater than one million  Andrei Pavel committed Dec 14, 2016 749  /// @throw isc::dhcp::SocketReadError if error occurred when receiving a  Marcin Siodelski committed Aug 13, 2014 750 751 752 753  /// packet. /// @throw isc::dhcp::SignalInterruptOnSelect when a call to select() is /// interrupted by a signal. ///  Tomek Mrugalski committed Dec 05, 2011 754  /// @return Pkt4 object representing received packet (or NULL)  Marcin Siodelski committed Sep 11, 2012 755  Pkt4Ptr receive4(uint32_t timeout_sec, uint32_t timeout_usec = 0);  Tomek Mrugalski committed Nov 08, 2011 756   Tomek Mrugalski committed Nov 08, 2011 757 758 759 760 761 762 763 764  /// 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.  Marcin Siodelski committed Dec 13, 2013 765 766  /// @param receive_bcast configure IPv4 socket to receive broadcast /// messages or IPv6 socket to join multicast group.  Marcin Siodelski committed Apr 04, 2013 767 768  /// @param send_bcast configure IPv4 socket to send broadcast messages. /// This parameter is ignored for IPv6 sockets.  Tomek Mrugalski committed Nov 08, 2011 769  ///  Tomek Mrugalski committed Dec 05, 2011 770 771 772  /// Method will throw if socket creation, socket binding or multicast /// join fails. ///  Tomek Mrugalski committed Nov 08, 2011 773  /// @return socket descriptor, if socket creation, binding and multicast  Tomek Mrugalski committed Dec 05, 2011 774  /// group join were all successful.  Tomek Mrugalski committed Dec 07, 2011 775  int openSocket(const std::string& ifname,  Marcin Siodelski committed Jun 14, 2012 776  const isc::asiolink::IOAddress& addr,  Marcin Siodelski committed Apr 04, 2013 777 778 779  const uint16_t port, const bool receive_bcast = false, const bool send_bcast = false);  Tomek Mrugalski committed Nov 08, 2011 780   Marcin Siodelski committed Jun 14, 2012 781 782  /// @brief Opens UDP/IP socket and binds it to interface specified. ///  Stephen Morris committed Jun 25, 2012 783 784 785 786  /// 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.  Marcin Siodelski committed Jun 14, 2012 787  ///  Marcin Siodelski committed Dec 13, 2013 788 789  /// @note This method does not join the socket to the multicast group. ///  Marcin Siodelski committed Jun 14, 2012 790 791  /// @param ifname name of the interface /// @param port UDP port  Marcin Siodelski committed Jun 15, 2012 792  /// @param family address family (AF_INET or AF_INET6)  Marcin Siodelski committed Dec 13, 2013 793 794  /// @return socket descriptor, if socket creation and binding was /// successful.  Marcin Siodelski committed Jun 15, 2012 795  /// @throw isc::Unexpected if failed to create and bind socket.  Marcin Siodelski committed Jul 06, 2012 796 797  /// @throw isc::BadValue if there is no address on specified interface /// that belongs to given family.  Marcin Siodelski committed Jun 14, 2012 798 799  int openSocketFromIface(const std::string& ifname, const uint16_t port,  Marcin Siodelski committed Jun 13, 2012 800 801  const uint8_t family);  Marcin Siodelski committed Jun 14, 2012 802 803  /// @brief Opens UDP/IP socket and binds to address specified ///  Stephen Morris committed Jun 25, 2012 804 805  /// This methods differs from \ref openSocket in that it does not require /// the specification of the interface to which the socket will be bound.  Marcin Siodelski committed Jun 14, 2012 806  ///  Marcin Siodelski committed Dec 13, 2013 807 808  /// @note This method does not join the socket to the multicast group. ///  Marcin Siodelski committed Jun 14, 2012 809 810  /// @param addr address to be bound /// @param port UDP port  Marcin Siodelski committed Dec 13, 2013 811 812  /// @return socket descriptor, if socket creation and binding was /// successful.  Marcin Siodelski committed Jun 15, 2012 813  /// @throw isc::Unexpected if failed to create and bind socket  Marcin Siodelski committed Jul 06, 2012 814 815  /// @throw isc::BadValue if specified address is not available on /// any interface  Marcin Siodelski committed Jun 14, 2012 816 817 818 819 820  int openSocketFromAddress(const isc::asiolink::IOAddress& addr, const uint16_t port); /// @brief Opens UDP/IP socket to be used to connect to remote address ///  Stephen Morris committed Jun 25, 2012 821 822 823 824  /// 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.  Marcin Siodelski committed Jun 14, 2012 825  ///  Marcin Siodelski committed Dec 13, 2013 826 827  /// @note This method does not join the socket to a multicast group. ///  Marcin Siodelski committed Jun 14, 2012 828 829  /// @param remote_addr remote address to connect to /// @param port UDP port  Marcin Siodelski committed Dec 13, 2013 830 831  /// @return socket descriptor, if socket creation and binding was /// successful.  Marcin Siodelski committed Jun 15, 2012 832  /// @throw isc::Unexpected if failed to create and bind socket  Marcin Siodelski committed Jun 14, 2012 833 834  int openSocketFromRemoteAddress(const isc::asiolink::IOAddress& remote_addr, const uint16_t port);  Marcin Siodelski committed Jun 13, 2012 835   Tomek Mrugalski committed Nov 08, 2011 836   Marcin Siodelski committed Dec 03, 2013 837  /// @brief Opens IPv6 sockets on detected interfaces.  Tomek Mrugalski committed Dec 05, 2011 838  ///  Marcin Siodelski committed Aug 11, 2014 839  /// This method opens sockets only on interfaces which have the  Tomek Mrugalski committed Aug 11, 2014 840  /// @c inactive6_ field set to false (are active). If the interface is active  Marcin Siodelski committed Aug 11, 2014 841 842 843  /// but it is not running, it is down, or is a loopback interface, /// an error is reported. ///  Marcin Siodelski committed Jan 14, 2014 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870  /// On the systems with multiple interfaces, it is often desired that the /// failure to open a socket on a particular interface doesn't cause a /// fatal error and sockets should be opened on remaining interfaces. /// However, the warning about the failure for the particular socket should /// be communicated to the caller. The libdhcp++ is a common library with /// no logger associated with it. Most of the functions in this library /// communicate errors via exceptions. In case of openSockets6 function /// exception must not be thrown if the function is supposed to continue /// opening sockets, despite an error. Therefore, if such a behavior is /// desired, the error handler function can be passed as a parameter. /// This error handler is called (if present) with an error string. /// Typically, error handler will simply log an error using an application /// logger, but it can do more sophisticated error handling too. /// /// @todo It is possible that additional parameters will have to be added /// to the error handler, e.g. Iface if it was really supposed to do /// some more sophisticated error handling. /// /// If the error handler is not installed (is NULL), the exception is thrown /// for each failure (default behavior). /// /// @warning This function does not check if there has been any sockets /// already open by the @c IfaceMgr. Therefore a caller should call /// @c IfaceMgr::closeSockets(AF_INET6) before calling this function. /// If there are any sockets open, the function may either throw an /// exception or invoke an error handler on attempt to bind the new socket /// to the same address and port.  Tomek Mrugalski committed Dec 05, 2011 871 872  /// /// @param port specifies port number (usually DHCP6_SERVER_PORT)  Marcin Siodelski committed Jan 10, 2014 873 874 875  /// @param error_handler A pointer to an error handler function which is /// called by the openSockets6 when it fails to open a socket. This /// parameter can be NULL to indicate that the callback should not be used.  Tomek Mrugalski committed Dec 07, 2011 876  ///  Marcin Siodelski committed Sep 25, 2012 877  /// @throw SocketOpenFailure if tried and failed to open socket.  Tomek Mrugalski committed Dec 07, 2011 878  /// @return true if any sockets were open  Marcin Siodelski committed Jan 10, 2014 879  bool openSockets6(const uint16_t port = DHCP6_SERVER_PORT,  Francis Dupont committed Feb 09, 2017 880  IfaceMgrErrorMsgCallback error_handler = 0);  Tomek Mrugalski committed Dec 05, 2011 881   Marcin Siodelski committed Dec 03, 2013 882 883  /// @brief Opens IPv4 sockets on detected interfaces. ///  Marcin Siodelski committed Aug 11, 2014 884  /// This method opens sockets only on interfaces which have the  Tomek Mrugalski committed Aug 11, 2014 885  /// @c inactive4_ field set to false (are active). If the interface is active  Marcin Siodelski committed Aug 11, 2014 886 887  /// but it is not running, it is down, or is a loopback interface, /// an error is reported.  Marcin Siodelski committed Dec 03, 2013 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929  /// /// The type of the socket being open depends on the selected Packet Filter /// represented by a class derived from @c isc::dhcp::PktFilter abstract /// class. /// /// It is possible to specify whether sockets should be broadcast capable. /// In most of the cases, the sockets should support broadcast traffic, e.g. /// DHCPv4 server and relay need to listen to broadcast messages sent by /// clients. If the socket has to be open on the particular interface, this /// interface must have broadcast flag set. If this condition is not met, /// the socket will be created in the unicast-only mode. If there are /// multiple broadcast-capable interfaces present, they may be all open /// in a broadcast mode only if the OS supports SO_BINDTODEVICE (bind socket /// to a device) socket option. If this option is not supported, only the /// first broadcast-capable socket will be opened in the broadcast mode. /// The error will be reported for sockets being opened on other interfaces. /// If the socket is bound to a device (interface), the broadcast traffic /// sent to this interface will be received on this interface only. /// This allows the DHCPv4 server or relay to detect the interface on which /// the broadcast message has been received. This interface is later used /// to send a response. /// /// On the systems with multiple interfaces, it is often desired that the /// failure to open a socket on a particular interface doesn't cause a /// fatal error and sockets should be opened on remaining interfaces. /// However, the warning about the failure for the particular socket should /// be communicated to the caller. The libdhcp++ is a common library with /// no logger associated with it. Most of the functions in this library /// communicate errors via exceptions. In case of openSockets4 function /// exception must not be thrown if the function is supposed to continue /// opening sockets, despite an error. Therefore, if such a behavior is /// desired, the error handler function can be passed as a parameter. /// This error handler is called (if present) with an error string. /// Typically, error handler will simply log an error using an application /// logger, but it can do more sophisticated error handling too. /// /// @todo It is possible that additional parameters will have to be added /// to the error handler, e.g. Iface if it was really supposed to do /// some more sophisticated error handling. /// /// If the error handler is not installed (is NULL), the exception is thrown /// for each failure (default behavior).  Tomek Mrugalski committed Dec 07, 2011 930  ///  Marcin Siodelski committed Jan 14, 2014 931 932 933 934 935 936 937  /// @warning This function does not check if there has been any sockets /// already open by the @c IfaceMgr. Therefore a caller should call /// @c IfaceMgr::closeSockets(AF_INET) before calling this function. /// If there are any sockets open, the function may either throw an /// exception or invoke an error handler on attempt to bind the new socket /// to the same address and port. ///  Tomek Mrugalski committed Dec 20, 2011 938  /// @param port specifies port number (usually DHCP4_SERVER_PORT)  Marcin Siodelski committed Apr 04, 2013 939  /// @param use_bcast configure sockets to support broadcast messages.  Marcin Siodelski committed Dec 03, 2013 940 941 942  /// @param error_handler A pointer to an error handler function which is /// called by the openSockets4 when it fails to open a socket. This /// parameter can be NULL to indicate that the callback should not be used.  Marcin Siodelski committed Nov 28, 2013 943 944 945  /// /// @throw SocketOpenFailure if tried and failed to open socket and callback /// function hasn't been specified.  Tomek Mrugalski committed Dec 07, 2011 946  /// @return true if any sockets were open  Marcin Siodelski committed Apr 04, 2013 947  bool openSockets4(const uint16_t port = DHCP4_SERVER_PORT,  Marcin Siodelski committed Nov 28, 2013 948  const bool use_bcast = true,  Francis Dupont committed Feb 09, 2017 949  IfaceMgrErrorMsgCallback error_handler = 0);  Tomek Mrugalski committed Dec 07, 2011 950   Marcin Siodelski committed Apr 04, 2013 951  /// @brief Closes all open sockets.  Marcin Siodelski committed May 21, 2013 952  /// Is used in destructor, but also from Dhcpv4Srv and Dhcpv6Srv classes.  Marcin Siodelski committed Apr 04, 2013 953  void closeSockets();  Tomek Mrugalski committed Dec 07, 2011 954   Marcin Siodelski committed Apr 26, 2013 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975  /// @brief Closes all IPv4 or IPv6 sockets. /// /// This function closes sockets of the specific 'type' and closes them. /// The 'type' of the socket indicates whether it is used to send IPv4 /// or IPv6 packets. The allowed values of the parameter are AF_INET and /// AF_INET6 for IPv4 and IPv6 packets respectively. It is important /// to realize that the actual types of sockets may be different than /// AF_INET for IPv4 packets. This is because, historically the IfaceMgr /// always used AF_INET sockets for IPv4 traffic. This is no longer the /// case when the Direct IPv4 traffic must be supported. In order to support /// direct traffic, the IfaceMgr operates on raw sockets, e.g. AF_PACKET /// family sockets on Linux. /// /// @todo Replace the AF_INET and AF_INET6 values with an enum /// which will not be confused with the actual socket type. /// /// @param family type of the sockets to be closed (AF_INET or AF_INET6) /// /// @throw BadValue if family value is different than AF_INET or AF_INET6. void closeSockets(const uint16_t family);  Marcin Siodelski committed May 21, 2013 976  /// @brief Returns number of detected interfaces.  Tomek Mrugalski committed Nov 30, 2011 977 978 979 980  /// /// @return number of detected interfaces uint16_t countIfaces() { return ifaces_.size(); }  Tomek Mrugalski committed Feb 03, 2014 981  /// @brief Adds external socket and a callback  Tomek Mrugalski committed May 30, 2012 982  ///  Tomek Mrugalski committed Feb 03, 2014 983  /// Specifies external socket and a callback that will be called  Tomek Mrugalski committed May 30, 2012 984 985 986 987  /// when data will be received over that socket. /// /// @param socketfd socket descriptor /// @param callback callback function  Tomek Mrugalski committed Feb 03, 2014 988  void addExternalSocket(int socketfd, SocketCallback callback);  Tomek Mrugalski committed Jan 30, 2014 989 990 991  /// @brief Deletes external socket void deleteExternalSocket(int socketfd);  Tomek Mrugalski committed May 30, 2012 992   Tomek Mrugalski committed Jun 10, 2015 993 994 995  /// @brief Deletes all external sockets. void deleteAllExternalSockets();  Marcin Siodelski committed Dec 12, 2013 996 997  /// @brief Set packet filter object to handle sending and receiving DHCPv4 /// messages.  Marcin Siodelski committed Apr 04, 2013 998  ///  Marcin Siodelski committed Dec 12, 2013 999 1000 1001 1002 1003 1004  /// Packet filter objects provide means for the @c IfaceMgr to open sockets /// for IPv4 packets reception and sending. This function sets custom packet /// filter (represented by a class derived from PktFilter) to be used by /// @c IfaceMgr. Note that there must be no IPv4 sockets open when this /// function is called. Call closeSockets(AF_INET) to close all hanging IPv4 /// sockets opened by the current packet filter object.  Marcin Siodelski committed Apr 04, 2013 1005  ///  Marcin Siodelski committed Dec 12, 2013 1006 1007  /// @param packet_filter A pointer to the new packet filter object to be /// used by @c IfaceMgr.  Marcin Siodelski committed Apr 04, 2013 1008 1009  /// /// @throw InvalidPacketFilter if provided packet filter object is NULL.  Marcin Siodelski committed Dec 12, 2013 1010  /// @throw PacketFilterChangeDenied if there are open IPv4 sockets.  Marcin Siodelski committed May 21, 2013 1011  void setPacketFilter(const PktFilterPtr& packet_filter);  Marcin Siodelski committed Apr 02, 2013 1012   Andrei Pavel committed Dec 14, 2016 1013  /// @brief Set packet filter object to handle sending and receiving DHCPv6  Marcin Siodelski committed Dec 12, 2013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034  /// messages. /// /// Packet filter objects provide means for the @c IfaceMgr to open sockets /// for IPv6 packets reception and sending. This function sets the new /// instance of the packet filter which will be used by @c IfaceMgr to send /// and receive DHCPv6 messages, until replaced by another packet filter. /// /// It is required that DHCPv6 messages are send and received using methods /// of the same object that was used to open socket. Therefore, it is /// required that all IPv6 sockets are closed prior to calling this /// function. Call closeSockets(AF_INET6) to close all hanging IPv6 sockets /// opened by the current packet filter object. /// /// @param packet_filter A pointer to the new packet filter object to be /// used by @c IfaceMgr. /// /// @throw isc::dhcp::InvalidPacketFilter if specified object is NULL. /// @throw isc::dhcp::PacketFilterChangeDenied if there are open IPv6 /// sockets. void setPacketFilter(const PktFilter6Ptr& packet_filter);  Marcin Siodelski committed Apr 25, 2013 1035 1036 1037  /// @brief Set Packet Filter object to handle send/receive packets. /// /// This function sets Packet Filter object to be used by IfaceMgr,  Marcin Siodelski committed Apr 30, 2013 1038 1039 1040 1041 1042 1043 1044 1045  /// appropriate for the current OS. Setting the argument to 'true' /// indicates that function should set a packet filter class /// which supports direct responses to clients having no address /// assigned yet. Filters picked by this function will vary, depending /// on the OS being used. There is no guarantee that there is an /// implementation that supports this feature on a particular OS. /// If there isn't, the PktFilterInet object will be set. If the /// argument is set to 'false', PktFilterInet object instance will  Andrei Pavel committed Dec 14, 2016 1046  /// be set as the Packet Filter regardless of the OS type.  Marcin Siodelski committed Apr 25, 2013 1047 1048  /// /// @param direct_response_desired specifies whether the Packet Filter  Marcin Siodelski committed Apr 30, 2013 1049  /// object being set should support direct traffic to the host  Marcin Siodelski committed Apr 25, 2013 1050 1051 1052  /// not having address assigned. void setMatchingPacketFilter(const bool direct_response_desired = false);  Marcin Siodelski committed Nov 29, 2013 1053 1054 1055 1056 1057  /// @brief Adds an interface to list of known interfaces. /// /// @param iface reference to Iface object. /// @note This function must be public because it has to be callable /// from unit tests.  Marcin Siodelski committed Mar 13, 2015 1058  void addInterface(const IfacePtr& iface) {  Marcin Siodelski committed Nov 29, 2013 1059 1060 1061  ifaces_.push_back(iface); }  Marcin Siodelski committed Jan 13, 2014 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072  /// @brief Checks if there is at least one socket of the specified family /// open. /// /// @param family A socket family. /// /// @return true if there is at least one socket open, false otherwise. bool hasOpenSocket(const uint16_t family) const; /// @brief Checks if there is a socket open and bound to an address. /// /// This function checks if one of the sockets opened by the IfaceMgr is  Marcin Siodelski committed Jun 23, 2014 1073 1074 1075 1076  /// bound to the IP address specified as the method parameter. If the /// socket is bound to the port (and address is unspecified), the /// method will check if the address passed in the argument is configured /// on an interface.  Marcin Siodelski committed Jan 13, 2014 1077 1078 1079 1080 1081 1082  /// /// @param addr Address of the socket being searched. /// /// @return true if there is a socket bound to the specified address. bool hasOpenSocket(const isc::asiolink::IOAddress& addr) const;  Tomek Mrugalski committed Oct 14, 2011 1083 1084 1085 1086 1087 1088  // 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 committed Dec 05, 2011 1089  /// anyone to create instances of IfaceMgr. Use instance() method instead.  Tomek Mrugalski committed Oct 14, 2011 1090 1091  IfaceMgr();  Tomek Mrugalski committed Dec 05, 2011 1092 1093 1094 1095 1096 1097 1098 1099 1100  /// @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  Marcin Siodelski committed Mar 28, 2013 1101 1102  /// @param receive_bcast configure socket to receive broadcast messages /// @param send_bcast configure socket to send broadcast messages.  Tomek Mrugalski committed Dec 05, 2011 1103 1104  /// /// @return socket descriptor  Marcin Siodelski committed Apr 04, 2013 1105 1106 1107  int openSocket4(Iface& iface, const isc::asiolink::IOAddress& addr, const uint16_t port, const bool receive_bcast = false, const bool send_bcast = false);  Tomek Mrugalski committed Nov 08, 2011 1108   Tomek Mrugalski committed Dec 05, 2011 1109 1110 1111 1112 1113 1114 1115 1116 1117  /// @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  Marcin Siodelski committed Dec 13, 2013 1118 1119 1120  /// @param join_multicast A boolean parameter which indicates whether /// socket should join All_DHCP_Relay_Agents_and_servers multicast /// group.  Tomek Mrugalski committed Dec 05, 2011 1121 1122  /// /// @return socket descriptor  Marcin Siodelski committed Dec 13, 2013 1123 1124  int openSocket6(Iface& iface, const isc::asiolink::IOAddress& addr, uint16_t port, const bool join_multicast);  Tomek Mrugalski committed Nov 08, 2011 1125   Tomek Mrugalski committed Nov 30, 2011 1126 1127 1128 1129 1130  /// @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  Jeremy C. Reed committed Apr 09, 2013 1131  /// interfaces.txt file.  Tomek Mrugalski committed Nov 30, 2011 1132 1133 1134  void stubDetectIfaces();  Tomek Mrugalski committed Oct 14, 2011 1135 1136 1137 1138  // TODO: having 2 maps (ifindex->iface and ifname->iface would) // probably be better for performance reasons /// List of available interfaces  Tomek Mrugalski committed Nov 08, 2011 1139  IfaceCollection ifaces_;  Tomek Mrugalski committed Oct 14, 2011 1140 1141 1142 1143  // 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  Tomek Mrugalski committed Nov 09, 2011 1144 1145 1146  //int recvsock_; // TODO: should be fd_set eventually, but we have only //int sendsock_; // 2 sockets for now. Will do for until next release  Marcin Siodelski committed May 21, 2013 1147  // We can't use the same socket, as receiving socket  Tomek Mrugalski committed Oct 14, 2011 1148 1149 1150  // is bound to multicast address. And we all know what happens // to people who try to use multicast as source address.  Marcin Siodelski committed May 21, 2013 1151  /// Length of the control_buf_ array  Tomek Mrugalski committed Mar 07, 2012 1152  size_t control_buf_len_;  Tomek Mrugalski committed Oct 14, 2011 1153   Marcin Siodelski committed May 21, 2013 1154  /// Control-buffer, used in transmission and reception.  Tomek Mrugalski committed Oct 14, 2011 1155 1156  boost::scoped_array control_buf_;  Tomek Mrugalski committed Oct 14, 2011 1157 private:  Marcin Siodelski committed Jun 14, 2012 1158 1159 1160 1161 1162  /// @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.  Marcin Siodelski committed Jun 15, 2012 1163  /// It first creates socket and makes attempt to connect  Marcin Siodelski committed Jun 14, 2012 1164 1165 1166 1167 1168 1169 1170  /// 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  Jeremy C. Reed committed Apr 09, 2013 1171  /// @throw isc::Unexpected if unable to identify local address  Marcin Siodelski committed Jun 14, 2012 1172 1173 1174  isc::asiolink::IOAddress getLocalAddress(const isc::asiolink::IOAddress& remote_addr, const uint16_t port);  Marcin Siodelski committed Apr 02, 2013 1175   Marcin Siodelski committed Dec 12, 2013 1176   Marcin Siodelski committed Jan 15, 2014 1177 1178  /// @brief Open an IPv6 socket with multicast support. ///  Marcin Siodelski committed Jun 18, 2014 1179 1180 1181 1182  /// This function opens a socket capable of receiving messages sent to /// the All_DHCP_Relay_Agents_and_Servers (ff02::1:2) multicast address. /// The socket is bound to the in6addr_any address and the IPV6_JOIN_GROUP /// option is set to point to the ff02::1:2 multicast address.  Marcin Siodelski committed Jan 15, 2014 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194  /// /// @note This function is intended to be called internally by the /// @c IfaceMgr::openSockets6. It is not intended to be called from any /// other function. /// /// @param iface Interface on which socket should be open. /// @param addr Link-local address to bind the socket to. /// @param port Port number to bind socket to. /// @param error_handler Error handler function to be called when an /// error occurs during opening a socket, or NULL if exception should /// be thrown upon error. bool openMulticastSocket(Iface& iface,  Tomek Mrugalski committed Feb 03, 2014 1195  const isc::asiolink::IOAddress& addr,  Marcin Siodelski committed Jan 15, 2014 1196  const uint16_t port,  Francis Dupont committed Feb 09, 2017 1197  IfaceMgrErrorMsgCallback error_handler = 0);