iface_mgr.h 51 KB

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