24#include <boost/scoped_ptr.hpp>
34#include <netinet/in.h>
43namespace ph = std::placeholders;
66 isc_throw(BadValue,
"Interface name must not be empty");
90 if ((family != AF_INET) && (family != AF_INET6)) {
92 <<
" specified when requested to close all sockets"
93 <<
" which belong to this family");
97 SocketCollection::iterator sock =
sockets_.begin();
99 if (sock->family_ == family) {
102 close(sock->sockfd_);
104 if (sock->fallbackfd_ >= 0) {
105 close(sock->fallbackfd_);
130 for (
unsigned i = 0; i <
mac_len_; i++) {
132 tmp << static_cast<int>(
mac_[i]);
143 <<
" was detected to have link address of length "
144 << len <<
", but maximum supported length is "
149 memcpy(
mac_, mac, len);
154 for (AddressCollection::iterator a =
addrs_.begin(); a !=
addrs_.end(); ++a) {
155 if (a->get() == addr) {
164 list<SocketInfo>::iterator sock =
sockets_.begin();
166 if (sock->sockfd_ == sockfd) {
169 if (sock->fallbackfd_ >= 0) {
170 close(sock->fallbackfd_);
183 test_mode_(false), check_thread_id_(true), allow_loopback_(false) {
184 id_ = std::this_thread::get_id();
191 }
catch (
const std::exception& ex) {
204 }
catch (
const std::exception& ex) {
218 if (a.get() == addr) {
220 <<
" already defined on the " <<
name_ <<
" interface.");
233 if (addr.get().isV4()) {
234 address = addr.get();
245 if (address == addr.get()) {
261 for (
auto& addr :
addrs_) {
262 if (address == addr.get()) {
263 addr.unspecified(!active);
268 " found on the interface " <<
getName());
273 for (
auto& addr :
addrs_) {
274 addr.unspecified(!active);
282 if (!addr.unspecified() && addr.get().isV4()) {
297 iface->closeSockets();
303 dhcp_receiver_->stop();
306 dhcp_receiver_.reset();
323 return (packet_filter_->isDirectResponseSupported());
328 return (packet_filter_->isSocketReceivedTimeSupported());
337 if (check_thread_id_ && std::this_thread::get_id() !=
id_) {
340 .arg(std::this_thread::get_id())
346 std::lock_guard<std::mutex> lock(callbacks_mutex_);
347 auto& idx = callbacks_.get<1>();
348 auto it = idx.find(socketfd);
349 if (it != idx.end()) {
359 callbacks_.push_back(x);
364 std::lock_guard<std::mutex> lock(callbacks_mutex_);
365 deleteExternalSocketInternal(socketfd);
369IfaceMgr::deleteExternalSocketInternal(
int socketfd) {
370 if (check_thread_id_ && std::this_thread::get_id() !=
id_) {
373 .arg(std::this_thread::get_id())
376 auto& idx = callbacks_.get<1>();
377 auto it = idx.find(socketfd);
378 if (it == idx.end()) {
388 std::lock_guard<std::mutex> lock(callbacks_mutex_);
389 auto const& idx = callbacks_.get<1>();
390 auto const it = idx.find(fd);
391 return (it != idx.end());
396 std::lock_guard<std::mutex> lock(callbacks_mutex_);
397 auto const& idx = callbacks_.get<1>();
398 auto const it = idx.find(fd);
399 if (it != idx.end()) {
400 return (it->unusable_);
408 if (check_thread_id_ && std::this_thread::get_id() !=
id_) {
410 .arg(std::this_thread::get_id())
413 std::lock_guard<std::mutex> lock(callbacks_mutex_);
420 if (!packet_filter) {
433 "it is not allowed to set new packet"
434 <<
" filter when there are open IPv4 sockets - need"
435 <<
" to close them first");
438 packet_filter_ = packet_filter;
443 if (!packet_filter) {
451 "it is not allowed to set new packet"
452 <<
" filter when there are open IPv6 sockets - need"
453 <<
" to close them first");
456 packet_filter6_ = packet_filter;
463 for (
const SocketInfo& sock : iface->getSockets()) {
465 if (sock.family_ == family) {
483 for (
const SocketInfo& sock : iface->getSockets()) {
486 if (sock.addr_ == addr) {
488 }
else if (sock.addr_.isV6Zero() && !unicast) {
495 if (addr == a.get()) {
512 const bool skip_opened) {
518 iface->clearErrors();
522 if (iface->inactive4_) {
533 if (iface->flag_loopback_ && !allow_loopback_) {
535 "must not open socket on the loopback"
536 " interface " << iface->getName());
540 if (!iface->flag_up_) {
542 "the interface " << iface->getName()
547 if (!iface->flag_running_) {
549 "the interface " << iface->getName()
550 <<
" is not running");
555 if (!iface->getAddress4(out_address)) {
557 "the interface " << iface->getName()
558 <<
" has no usable IPv4 addresses configured");
564 if (addr.unspecified() || !addr.get().isV4()) {
571 bool is_open_as_broadcast = iface->flag_broadcast_ && use_bcast;
588 "Binding socket to an interface is not"
589 " supported on this OS; therefore only"
590 " one socket listening to broadcast traffic"
591 " can be opened. Sockets will not be opened"
592 " on remaining interfaces");
604 is_open_as_broadcast,
605 is_open_as_broadcast);
608 "Failed to open socket on interface "
616 if (is_open_as_broadcast) {
642 const bool skip_opened) {
647 iface->clearErrors();
651 if (iface->inactive6_) {
662 if (iface->flag_loopback_ && !allow_loopback_) {
664 "must not open socket on the loopback"
665 " interface " << iface->getName());
667 }
else if (!iface->flag_up_) {
669 "the interface " << iface->getName()
672 }
else if (!iface->flag_running_) {
674 "the interface " << iface->getName()
675 <<
" is not running");
688 !iface->getSockets().size()) {
693 "Failed to open unicast socket on interface "
695 <<
", reason: " << ex.
what());
705 if (!addr.get().isV6()) {
714 if (!addr.get().isV6LinkLocal()){
729 !iface->getSockets().size()) {
733 IfaceMgr::openMulticastSocket(*iface, addr, port);
736 "Failed to open multicast socket on interface "
737 << iface->getName() <<
", reason: " << ex.
what());
769 dhcp_receiver_->start(std::bind(&IfaceMgr::receiveDHCP4Packets,
this));
779 dhcp_receiver_->start(std::bind(&IfaceMgr::receiveDHCP6Packets,
this));
790 if ((existing->getName() == iface->getName()) ||
791 (existing->getIndex() == iface->getIndex())) {
793 " when " << existing->getFullName() <<
805 out <<
"Detected interface " << iface->getFullName()
806 <<
", hwtype=" << iface->getHWType()
807 <<
", mac=" << iface->getPlainMac();
808 out <<
", flags=" << hex << iface->flags_ << dec <<
"("
809 << (iface->flag_loopback_?
"LOOPBACK ":
"")
810 << (iface->flag_up_?
"UP ":
"")
811 << (iface->flag_running_?
"RUNNING ":
"")
812 << (iface->flag_multicast_?
"MULTICAST ":
"")
813 << (iface->flag_broadcast_?
"BROADCAST ":
"")
815 out <<
" " << addrs.size() <<
" addr(s):";
818 out <<
" " << addr.get().toText();
835IfaceCollection::getIfaceInternal(
const unsigned int ifindex,
const bool need_lock) {
840 lock_guard<mutex> lock(mutex_);
841 if (cache_ && (cache_->getIndex() == ifindex)) {
845 if (cache_ && (cache_->getIndex() == ifindex)) {
849 auto const& idx = ifaces_container_.get<1>();
850 auto it = idx.find(ifindex);
851 if (it == idx.end()) {
855 lock_guard<mutex> lock(mutex_);
865IfaceCollection::getIfaceInternal(
const std::string& ifname,
const bool need_lock) {
867 lock_guard<mutex> lock(mutex_);
868 if (cache_ && (cache_->getName() == ifname)) {
872 if (cache_ && (cache_->getName() == ifname)) {
876 auto const& idx = ifaces_container_.get<2>();
877 auto it = idx.find(ifname);
878 if (it == idx.end()) {
882 lock_guard<mutex> lock(mutex_);
893 return (
ifaces_.getIface(ifindex));
898 if (ifname.empty()) {
901 return (
ifaces_.getIface(ifname));
906 if (pkt->indexSet()) {
924IfaceMgr::handleClosedExternalSocket(SocketCallbackInfoIterator it) {
926 if (fcntl(it->socket_, F_GETFD) < 0 && (errno == EBADF)) {
927 SocketCallbackInfo x(*it);
929 callbacks_.replace(it, x);
935IfaceMgr::handleClosedExternalSockets() {
936 std::lock_guard<std::mutex> lock(callbacks_mutex_);
937 for (
auto it = callbacks_.begin(); it != callbacks_.end(); ++it) {
941 handleClosedExternalSocket(it);
948 socklen_t opt_size =
sizeof(
error);
950 if (getsockopt(s.sockfd_, SOL_SOCKET, SO_ERROR,
951 reinterpret_cast<char*
>(&
error), &opt_size) < 0) {
952 if ((errno == ENOTSOCK) || (errno == ENOPROTOOPT)) {
956 isc_throw(BadValue,
"Can't get socket error fd: "
957 << s.sockfd_ <<
" - error: " << strerror(errno));
962 .arg(iface->getFullName())
963 .arg(strerror(
error));
970 for (
const SocketInfo& sock : iface->getSockets()) {
985 iface->clearUnicasts();
990 const uint16_t port,
const bool receive_bcast,
991 const bool send_bcast) {
997 return openSocket4(*iface, addr, port, receive_bcast, send_bcast);
999 }
else if (addr.
isV6()) {
1000 return openSocket6(*iface, addr, port, receive_bcast);
1009 const uint16_t port,
1010 const uint8_t family) {
1013 if ((iface->getFullName() != ifname) &&
1014 (iface->getName() != ifname)) {
1021 Iface::AddressCollection::iterator addr_it = addrs.begin();
1022 while (addr_it != addrs.end()) {
1023 if (addr_it->get().getFamily() == family) {
1026 return (
openSocket(iface->getName(), *addr_it, port,
false));
1032 if (addr_it == addrs.end()) {
1034 std::string family_name(
"AF_INET");
1035 if (family == AF_INET6) {
1036 family_name =
"AF_INET6";
1040 << ifname <<
", port: " << port <<
", address "
1041 " family: " << family_name);
1050 const uint16_t port) {
1060 if (a.get() == addr) {
1063 return (
openSocket(iface->getName(), a, port,
false));
1073 const uint16_t port) {
1076 IOAddress local_address(getLocalAddress(remote_addr, port));
1084IfaceMgr::getLocalAddress(
const IOAddress& remote_addr,
const uint16_t port) {
1086 boost::scoped_ptr<const UDPEndpoint>
1089 if (!remote_endpoint) {
1094 boost::asio::io_context io_service;
1095 boost::asio::ip::udp::socket sock(io_service);
1097 boost::system::error_code err_code;
1100 if (remote_addr.
isV4() &&
1113 sock.open(boost::asio::ip::udp::v4(), err_code);
1115 const char* errstr = strerror(errno);
1119 sock.set_option(boost::asio::socket_base::broadcast(
true), err_code);
1127 sock.connect(remote_endpoint->getASIOEndpoint(), err_code);
1130 isc_throw(Unexpected,
"failed to connect to remote endpoint.");
1134 boost::asio::ip::udp::socket::endpoint_type local_endpoint =
1135 sock.local_endpoint();
1136 boost::asio::ip::address local_address(local_endpoint.address());
1142 return IOAddress(local_address);
1147 const bool receive_bcast,
const bool send_bcast) {
1150 receive_bcast, send_bcast);
1153 return (
info.sockfd_);
1161 << pkt->getIface() <<
") specified.");
1166 return (packet_filter6_->send(*iface,
getSocket(pkt), pkt) == 0);
1174 << pkt->getIface() <<
") specified.");
1179 return (packet_filter_->send(*iface,
getSocket(pkt).sockfd_, pkt) == 0);
1192 if (timeout_usec >= 1000000) {
1194 " one million microseconds");
1197 fd_event_handler_->clear();
1201 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1202 if (!callbacks_.empty()) {
1203 for (
auto it = callbacks_.begin(); it != callbacks_.end(); ++it) {
1204 if (it->unusable_) {
1207 handleClosedExternalSocket(it);
1209 fd_event_handler_->add(it->socket_);
1234 int result = fd_event_handler_->waitEvent(timeout_sec, timeout_usec);
1239 }
else if (result < 0) {
1247 if (errno == EINTR) {
1249 }
else if (errno == EBADF) {
1250 handleClosedExternalSockets();
1259 std::lock_guard<std::mutex> lk(receiver_mutex_);
1262 string msg = dhcp_receiver_->getLastError();
1269 boost::scoped_ptr<SocketCallbackInfo> ex_sock;
1272 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1273 for (
auto it = callbacks_.begin(); it != callbacks_.end(); ++it) {
1274 if (it->unusable_) {
1277 handleClosedExternalSocket(it);
1278 if (fd_event_handler_->readReady(it->socket_) ||
1279 fd_event_handler_->hasError(it->socket_)) {
1283 if (it->callback_) {
1293 if (ex_sock && ex_sock->callback_) {
1297 ex_sock->callback_(ex_sock->socket_);
1305 std::lock_guard<std::mutex> lk(receiver_mutex_);
1316 if (timeout_usec >= 1000000) {
1318 " one million microseconds");
1321 fd_event_handler_->clear();
1329 for (
const SocketInfo& s : iface->getSockets()) {
1331 if (s.addr_.isV4()) {
1333 fd_event_handler_->add(s.sockfd_);
1340 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1341 if (!callbacks_.empty()) {
1342 for (
auto it = callbacks_.begin(); it != callbacks_.end(); ++it) {
1343 if (it->unusable_) {
1346 handleClosedExternalSocket(it);
1348 fd_event_handler_->add(it->socket_);
1356 int result = fd_event_handler_->waitEvent(timeout_sec, timeout_usec);
1361 }
else if (result < 0) {
1369 if (errno == EINTR) {
1371 }
else if (errno == EBADF) {
1372 handleClosedExternalSockets();
1379 boost::scoped_ptr<SocketCallbackInfo> ex_sock;
1382 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1383 for (
auto it = callbacks_.begin(); it != callbacks_.end(); ++it) {
1384 if (it->unusable_) {
1387 handleClosedExternalSocket(it);
1388 if (fd_event_handler_->readReady(it->socket_) ||
1389 fd_event_handler_->hasError(it->socket_)) {
1393 if (it->callback_) {
1403 if (ex_sock && ex_sock->callback_) {
1407 ex_sock->callback_(ex_sock->socket_);
1415 boost::scoped_ptr<SocketInfo> candidate;
1418 for (
const SocketInfo& s : iface->getSockets()) {
1419 if (!fd_event_handler_->readReady(s.sockfd_) &&
1420 !fd_event_handler_->hasError(s.sockfd_)) {
1423 if (fd_event_handler_->hasError(s.sockfd_)) {
1424 handleIfaceSocketError(iface, s);
1435 if (!candidate || !recv_if) {
1442 if (ioctl(candidate->sockfd_, FIONREAD, &len) < 0) {
1451 return (packet_filter_->receive(*recv_if, *candidate));
1466 if (timeout_usec >= 1000000) {
1468 " one million microseconds");
1471 fd_event_handler_->clear();
1479 for (
const SocketInfo& s : iface->getSockets()) {
1481 if (s.addr_.isV6()) {
1483 fd_event_handler_->add(s.sockfd_);
1490 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1491 if (!callbacks_.empty()) {
1492 for (
auto it = callbacks_.begin(); it != callbacks_.end(); ++it) {
1493 if (it->unusable_) {
1496 handleClosedExternalSocket(it);
1498 fd_event_handler_->add(it->socket_);
1506 int result = fd_event_handler_->waitEvent(timeout_sec, timeout_usec);
1511 }
else if (result < 0) {
1519 if (errno == EINTR) {
1521 }
else if (errno == EBADF) {
1522 handleClosedExternalSockets();
1529 boost::scoped_ptr<SocketCallbackInfo> ex_sock;
1532 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1533 for (
auto it = callbacks_.begin(); it != callbacks_.end(); ++it) {
1534 if (it->unusable_) {
1537 handleClosedExternalSocket(it);
1538 if (fd_event_handler_->readReady(it->socket_) ||
1539 fd_event_handler_->hasError(it->socket_)) {
1543 if (it->callback_) {
1553 if (ex_sock && ex_sock->callback_) {
1557 ex_sock->callback_(ex_sock->socket_);
1565 boost::scoped_ptr<SocketInfo> candidate;
1567 for (
const SocketInfo& s : iface->getSockets()) {
1568 if (!fd_event_handler_->readReady(s.sockfd_) &&
1569 !fd_event_handler_->hasError(s.sockfd_)) {
1572 if (fd_event_handler_->hasError(s.sockfd_)) {
1573 handleIfaceSocketError(iface, s);
1590 if (ioctl(candidate->sockfd_, FIONREAD, &len) < 0) {
1599 return (packet_filter6_->receive(*candidate));
1605 if (timeout_usec >= 1000000) {
1607 " one million microseconds");
1610 fd_event_handler_->clear();
1614 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1615 if (!callbacks_.empty()) {
1616 for (
auto it = callbacks_.begin(); it != callbacks_.end(); ++it) {
1617 if (it->unusable_) {
1620 handleClosedExternalSocket(it);
1622 fd_event_handler_->add(it->socket_);
1647 int result = fd_event_handler_->waitEvent(timeout_sec, timeout_usec);
1652 }
else if (result < 0) {
1660 if (errno == EINTR) {
1662 }
else if (errno == EBADF) {
1663 handleClosedExternalSockets();
1672 std::lock_guard<std::mutex> lk(receiver_mutex_);
1675 string msg = dhcp_receiver_->getLastError();
1682 boost::scoped_ptr<SocketCallbackInfo> ex_sock;
1685 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1686 for (
auto it = callbacks_.begin(); it != callbacks_.end(); ++it) {
1687 if (it->unusable_) {
1690 handleClosedExternalSocket(it);
1691 if (fd_event_handler_->readReady(it->socket_) ||
1692 fd_event_handler_->hasError(it->socket_)) {
1696 if (it->callback_) {
1706 if (ex_sock && ex_sock->callback_) {
1710 ex_sock->callback_(ex_sock->socket_);
1718 std::lock_guard<std::mutex> lk(receiver_mutex_);
1728IfaceMgr::receiveDHCP4Packets() {
1729 receiver_fd_event_handler_->clear();
1736 for (
const SocketInfo& s : iface->getSockets()) {
1738 if (s.addr_.isV4()) {
1740 receiver_fd_event_handler_->add(s.sockfd_);
1748 if (dhcp_receiver_->shouldTerminate()) {
1756 int result = receiver_fd_event_handler_->waitEvent(0, 0,
false);
1759 if (dhcp_receiver_->shouldTerminate()) {
1766 }
else if (result < 0) {
1768 if (errno != EINTR) {
1770 std::lock_guard<std::mutex> lk(receiver_mutex_);
1772 dhcp_receiver_->setError(strerror(errno));
1784 for (
const SocketInfo& s : iface->getSockets()) {
1785 if (!receiver_fd_event_handler_->readReady(s.sockfd_) &&
1786 !receiver_fd_event_handler_->hasError(s.sockfd_)) {
1789 if (receiver_fd_event_handler_->hasError(s.sockfd_)) {
1790 handleIfaceSocketError(iface, s);
1792 receiveDHCP4Packet(*iface, s);
1794 if (dhcp_receiver_->shouldTerminate()) {
1799 }
catch (
const std::exception& ex) {
1800 std::lock_guard<std::mutex> lk(receiver_mutex_);
1801 dhcp_receiver_->setError(
string(ex.what()) +
" error: " + strerror(errno));
1803 std::lock_guard<std::mutex> lk(receiver_mutex_);
1804 dhcp_receiver_->setError(
"receive failed");
1810IfaceMgr::receiveDHCP6Packets() {
1811 receiver_fd_event_handler_->clear();
1818 for (
const SocketInfo& s : iface->getSockets()) {
1820 if (s.addr_.isV6()) {
1822 receiver_fd_event_handler_->add(s.sockfd_);
1830 if (dhcp_receiver_->shouldTerminate()) {
1838 int result = receiver_fd_event_handler_->waitEvent(0, 0,
false);
1841 if (dhcp_receiver_->shouldTerminate()) {
1848 }
else if (result < 0) {
1850 if (errno != EINTR) {
1852 std::lock_guard<std::mutex> lk(receiver_mutex_);
1854 dhcp_receiver_->setError(strerror(errno));
1866 for (
const SocketInfo& s : iface->getSockets()) {
1867 if (!receiver_fd_event_handler_->readReady(s.sockfd_) &&
1868 !receiver_fd_event_handler_->hasError(s.sockfd_)) {
1871 if (receiver_fd_event_handler_->hasError(s.sockfd_)) {
1872 handleIfaceSocketError(iface, s);
1874 receiveDHCP6Packet(s);
1876 if (dhcp_receiver_->shouldTerminate()) {
1881 }
catch (
const std::exception& ex) {
1882 std::lock_guard<std::mutex> lk(receiver_mutex_);
1883 dhcp_receiver_->setError(
string(ex.what()) +
" error: " + strerror(errno));
1885 std::lock_guard<std::mutex> lk(receiver_mutex_);
1886 dhcp_receiver_->setError(
"receive failed");
1892IfaceMgr::receiveDHCP4Packet(
Iface& iface,
const SocketInfo& socket_info) {
1895 int result = ioctl(socket_info.sockfd_, FIONREAD, &len);
1897 std::lock_guard<std::mutex> lk(receiver_mutex_);
1899 dhcp_receiver_->setError(strerror(errno));
1910 pkt = packet_filter_->receive(iface, socket_info);
1911 }
catch (
const std::exception& ex) {
1912 std::lock_guard<std::mutex> lk(receiver_mutex_);
1913 dhcp_receiver_->setError(strerror(errno));
1915 std::lock_guard<std::mutex> lk(receiver_mutex_);
1916 dhcp_receiver_->setError(
"packet filter receive() failed");
1920 std::lock_guard<std::mutex> lk(receiver_mutex_);
1927IfaceMgr::receiveDHCP6Packet(
const SocketInfo& socket_info) {
1930 int result = ioctl(socket_info.sockfd_, FIONREAD, &len);
1932 std::lock_guard<std::mutex> lk(receiver_mutex_);
1934 dhcp_receiver_->setError(strerror(errno));
1945 pkt = packet_filter6_->receive(socket_info);
1946 }
catch (
const std::exception& ex) {
1947 std::lock_guard<std::mutex> lk(receiver_mutex_);
1948 dhcp_receiver_->setError(ex.what());
1950 std::lock_guard<std::mutex> lk(receiver_mutex_);
1951 dhcp_receiver_->setError(
"packet filter receive() failed");
1955 std::lock_guard<std::mutex> lk(receiver_mutex_);
1970 Iface::SocketCollection::const_iterator candidate = socket_collection.end();
1972 Iface::SocketCollection::const_iterator s;
1973 for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
1978 if (s->family_ != AF_INET6) {
1983 if (s->addr_.isV6Multicast()) {
1987 if (s->addr_ == pkt->getLocalAddr()) {
1990 return (s->sockfd_);
1994 if (candidate == socket_collection.end()) {
2000 if ((pkt->getRemoteAddr().isV6LinkLocal() &&
2001 s->addr_.isV6LinkLocal()) ||
2002 (!pkt->getRemoteAddr().isV6LinkLocal() &&
2003 !s->addr_.isV6LinkLocal())) {
2009 if (candidate != socket_collection.end()) {
2010 return (candidate->sockfd_);
2014 <<
" does not have any suitable IPv6 sockets open.");
2028 Iface::SocketCollection::const_iterator candidate = socket_collection.end();
2029 Iface::SocketCollection::const_iterator s;
2030 for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
2031 if (s->family_ == AF_INET) {
2032 if (s->addr_ == pkt->getLocalAddr()) {
2036 if (candidate == socket_collection.end()) {
2042 if (candidate == socket_collection.end()) {
2044 <<
" does not have any suitable IPv4 sockets open.");
2047 return (*candidate);
2054 " while DHCP receiver thread is running");
2057 bool enable_queue =
false;
2058 if (queue_control) {
2069 if (family == AF_INET) {
2070 packet_queue_mgr4_->createPacketQueue(queue_control);
2072 packet_queue_mgr6_->createPacketQueue(queue_control);
2076 if (family == AF_INET) {
2077 packet_queue_mgr4_->destroyPacketQueue();
2079 packet_queue_mgr6_->destroyPacketQueue();
2083 return (enable_queue);
2088 errors_.push_back(message);
2103 if (test_mode_ && update_only) {
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
A generic exception that is thrown when an unexpected error condition occurs.
The IOAddress class represents an IP addresses (version agnostic)
uint32_t toUint32() const
Converts IPv4 address to uint32_t.
bool isV6() const
Convenience function to check for an IPv6 address.
bool isV4() const
Convenience function to check for an IPv4 address.
static const IOEndpoint * create(const int protocol, const IOAddress &address, const unsigned short port)
A polymorphic factory of endpoint from address and port.
The UDPEndpoint class is a concrete derived class of IOEndpoint that represents an endpoint of a UDP ...
static bool getBoolean(isc::data::ConstElementPtr scope, const std::string &name)
Returns a boolean parameter from a scope.
IfacePtr getIface(const unsigned int ifindex)
Lookup by interface index.
IfaceMgr exception thrown thrown when interface detection fails.
Handles network interfaces, transmission and reception.
void clearIfaces()
Removes detected interfaces.
bool isExternalSocket(int fd)
Checks if socket's file description is registered.
void deleteExternalSocket(int socketfd)
Deletes external socket.
Pkt6Ptr receive6Indirect(uint32_t timeout_sec, uint32_t timeout_usec=0)
Receive IPv6 packets indirectly or data from external sockets.
bool openSockets4(const uint16_t port=DHCP4_SERVER_PORT, const bool use_bcast=true, IfaceMgrErrorMsgCallback error_handler=0, const bool skip_opened=false)
Opens IPv4 sockets on detected interfaces.
std::function< void(int fd)> SocketCallback
Defines callback used when data is received over external sockets.
int openSocket(const std::string &ifname, const isc::asiolink::IOAddress &addr, const uint16_t port, const bool receive_bcast=false, const bool send_bcast=false)
Opens UDP/IP socket and binds it to address, interface and port.
int openSocketFromAddress(const isc::asiolink::IOAddress &addr, const uint16_t port)
Opens UDP/IP socket and binds to address specified.
void printIfaces(std::ostream &out=std::cout)
Debugging method that prints out all available interfaces.
IfacePtr getIface(const unsigned int ifindex)
Returns interface specified interface index.
int openSocket4(Iface &iface, const isc::asiolink::IOAddress &addr, const uint16_t port, const bool receive_bcast=false, const bool send_bcast=false)
Opens IPv4 socket.
bool openSockets6(const uint16_t port=DHCP6_SERVER_PORT, IfaceMgrErrorMsgCallback error_handler=0, const bool skip_opened=false)
Opens IPv6 sockets on detected interfaces.
BoundAddresses bound_address_
Unordered set of IPv4 bound addresses.
void setPacketFilter(const PktFilterPtr &packet_filter)
Set packet filter object to handle sending and receiving DHCPv4 messages.
int openSocketFromIface(const std::string &ifname, const uint16_t port, const uint8_t family)
Opens UDP/IP socket and binds it to interface specified.
Pkt6Ptr receive6(uint32_t timeout_sec, uint32_t timeout_usec=0)
Receive IPv4 packets or data from external sockets.
void detectIfaces(bool update_only=false)
Detects network interfaces.
IfaceCollection ifaces_
List of available interfaces.
void startDHCPReceiver(const uint16_t family)
Starts DHCP packet receiver.
void clearUnicasts()
Clears unicast addresses on all interfaces.
virtual bool isSocketReceivedTimeSupported() const
Check if the socket received time is supported.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
void initializeFDEventHandler()
Initialize the FD event handler;.
bool isDHCPReceiverRunning() const
Returns true if there is a receiver exists and its thread is currently running.
bool hasOpenSocket(const uint16_t family) const
Checks if there is at least one socket of the specified family open.
virtual ~IfaceMgr()
Destructor.
void collectBoundAddresses()
Collect the addresses all sockets are bound to.
int openSocket6(Iface &iface, const isc::asiolink::IOAddress &addr, uint16_t port, const bool join_multicast)
Opens IPv6 socket.
bool configureDHCPPacketQueue(const uint16_t family, data::ConstElementPtr queue_control)
Configures DHCP packet queue.
int openSocketFromRemoteAddress(const isc::asiolink::IOAddress &remote_addr, const uint16_t port)
Opens UDP/IP socket to be used to connect to remote address.
Pkt6Ptr receive6Direct(uint32_t timeout_sec, uint32_t timeout_usec=0)
Receive IPv6 packets directly or data from external sockets.
bool checkDetectIfaces(bool update_only)
Check if the specific system calls used to detect interfaces should be executed.
bool isDirectResponseSupported() const
Check if packet be sent directly to the client having no address.
void clearBoundAddresses()
Clears the addresses all sockets are bound to.
void addExternalSocket(int socketfd, SocketCallback callback)
Adds external socket and a callback.
void addInterface(const IfacePtr &iface)
Adds an interface to list of known interfaces.
IfaceMgr()
Protected constructor.
bool send(const Pkt6Ptr &pkt)
Sends an IPv6 packet.
Pkt4Ptr receive4Indirect(uint32_t timeout_sec, uint32_t timeout_usec=0)
Receive IPv4 packets indirectly or data from external sockets.
void closeSockets()
Closes all open sockets.
PacketQueue6Ptr getPacketQueue6()
Fetches the DHCPv6 receiver packet queue.
bool isExternalSocketUnusable(int fd)
Checks if socket's file description is registered.
static const IfaceMgrPtr & instancePtr()
Returns pointer to the sole instance of the interface manager.
void deleteAllExternalSockets()
Deletes all external sockets.
void stopDHCPReceiver()
Stops the DHCP packet receiver.
std::thread::id id_
Main thread ID.
Pkt4Ptr receive4Direct(uint32_t timeout_sec, uint32_t timeout_usec=0)
Receive IPv4 packets directly or data from external sockets.
PacketQueue4Ptr getPacketQueue4()
Fetches the DHCPv4 receiver packet queue.
uint16_t getSocket(const isc::dhcp::Pkt6Ptr &pkt)
Return most suitable socket for transmitting specified IPv6 packet.
Pkt4Ptr receive4(uint32_t timeout_sec, uint32_t timeout_usec=0)
Receive IPv4 packets or data from external sockets.
IfaceMgr exception thrown when there is no suitable interface.
Represents a single network interface.
std::string getPlainMac() const
Returns link-layer address a plain text.
uint64_t flags_
Interface flags (this value is as is returned by OS, it may mean different things on different OSes).
bool inactive4_
Indicates that IPv4 sockets should (true) or should not (false) be opened on this interface.
size_t mac_len_
Length of link-layer address (usually 6).
void clearErrors()
Clears all errors.
AddressCollection addrs_
List of assigned addresses.
ErrorBuffer const & getErrors() const
Get the consistent list of error messages.
std::vector< std::string > ErrorBuffer
Type definition for a list of error messages.
std::string getFullName() const
Returns full interface name as "ifname/ifindex" string.
unsigned int ifindex_
Interface index (a value that uniquely identifies an interface).
std::string name_
Network interface name.
uint16_t hardware_type_
Hardware type.
SocketCollection sockets_
Socket used to send data.
const AddressCollection & getAddresses() const
Returns all addresses available on an interface.
bool flag_multicast_
Flag specifies if selected interface is multicast capable.
void setActive(const isc::asiolink::IOAddress &address, const bool active)
Activates or deactivates address for the interface.
void addError(std::string const &message)
Add an error to the list of messages.
std::string getName() const
Returns interface name.
Iface(const std::string &name, unsigned int ifindex)
Iface constructor.
bool delAddress(const isc::asiolink::IOAddress &addr)
Deletes an address from an interface.
bool hasAddress(const isc::asiolink::IOAddress &address) const
Check if the interface has the specified address assigned.
void setMac(const uint8_t *mac, size_t macLen)
Sets MAC address of the interface.
bool flag_running_
Flag specifies if selected interface is running (e.g.
bool delSocket(uint16_t sockfd)
Closes socket.
std::list< Address > AddressCollection
Type that defines list of addresses.
bool inactive6_
Indicates that IPv6 sockets should (true) or should not (false) be opened on this interface.
std::list< SocketInfo > SocketCollection
Type that holds a list of socket information.
static const unsigned int MAX_MAC_LEN
Maximum MAC address length (Infiniband uses 20 bytes)
bool flag_loopback_
Specifies if selected interface is loopback.
void addUnicast(const isc::asiolink::IOAddress &addr)
Adds unicast the server should listen on.
unsigned int countActive4() const
Returns a number of activated IPv4 addresses on the interface.
uint8_t mac_[MAX_MAC_LEN]
Link-layer address.
util::Optional< asiolink::IOAddress > Address
Address type.
void addAddress(const isc::asiolink::IOAddress &addr)
Adds an address to an interface.
void closeSockets()
Closes all open sockets on interface.
void addSocket(const SocketInfo &sock)
Adds socket descriptor to an interface.
bool flag_up_
Specifies if selected interface is up.
bool flag_broadcast_
Flag specifies if selected interface is broadcast capable.
AddressCollection unicasts_
List of unicast addresses the server should listen on.
bool getAddress4(isc::asiolink::IOAddress &address) const
Returns IPv4 address assigned to the interface.
Exception thrown when invalid packet filter object specified.
Exception thrown when it is not allowed to set new Packet Filter.
Packet Queue Manager for DHCPv4 servers.
Packet Queue Manager for DHCPv6 servers.
A DHCPv6 packet handling class using datagram sockets.
Packet handling class using AF_INET socket family.
Exception thrown when a call to select is interrupted by a signal.
IfaceMgr exception thrown thrown when socket opening or configuration failed.
IfaceMgr exception thrown when there is an error detected for the respective socket file descriptor.
IfaceMgr exception thrown when there is no suitable socket found.
IfaceMgr exception thrown thrown when error occurred during reading data from socket.
static FDEventHandlerPtr factoryFDEventHandler()
Return an FDEventhandler.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
A template representing an optional value.
Provides a thread and controls for monitoring its activities.
#define DHCP_IPV4_BROADCAST_ADDRESS
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define IFACEMGR_ERROR(ex_type, handler, iface, stream)
A macro which handles an error in IfaceMgr.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
boost::shared_ptr< const Element > ConstElementPtr
const isc::log::MessageID DHCP_RECEIVE4_UNKNOWN
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
const isc::log::MessageID DHCP_RECEIVE6_UNKNOWN
boost::shared_ptr< IfaceMgr > IfaceMgrPtr
Type definition for the pointer to the IfaceMgr.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
boost::shared_ptr< PktFilter > PktFilterPtr
Pointer to a PktFilter object.
boost::shared_ptr< Iface > IfacePtr
Type definition for the pointer to an Iface object.
const isc::log::MessageID DHCP_DELETE_EXTERNAL_SOCKET_NOT_FOUND
std::function< void(const std::string &errmsg)> IfaceMgrErrorMsgCallback
This type describes the callback function invoked when error occurs in the IfaceMgr.
const isc::log::MessageID DHCP_ADD_EXTERNAL_SOCKET_ALREADY_EXISTS
const isc::log::MessageID DHCP_ADD_EXTERNAL_SOCKET_BAD_THREAD
constexpr unsigned int UNSET_IFINDEX
A value used to signal that the interface index was not set.
const isc::log::MessageID DHCP_DELETE_EXTERNAL_SOCKET_BAD_THREAD
const isc::log::MessageID DHCP_DELETE_ALL_EXTERNAL_SOCKETS_BAD_THREAD
isc::log::Logger dhcp_logger("dhcp")
DHCP library Logger.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
boost::shared_ptr< PktFilter6 > PktFilter6Ptr
Pointer to a PktFilter object.
const isc::log::MessageID DHCP_IFACE_SOCKET_ERROR
Defines the logger used by the top-level component of kea-lfc.
Keeps callback information for external sockets.
SocketCallback callback_
A callback that will be called when data arrives over socket_.
Holds information about socket.