iface_mgr.h 51 KB

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