21#include <boost/scoped_ptr.hpp>
31#include <netinet/in.h>
34#include <sys/select.h>
37#define FD_COPY(orig, copy) \
39 memmove(copy, orig, sizeof(fd_set)); \
48namespace ph = std::placeholders;
65 :
name_(name), ifindex_(ifindex), mac_len_(0), hardware_type_(0),
66 flag_loopback_(false), flag_up_(false), flag_running_(false),
67 flag_multicast_(false), flag_broadcast_(false), flags_(0),
68 inactive4_(false), inactive6_(false) {
95 if ((family != AF_INET) && (family != AF_INET6)) {
97 <<
" specified when requested to close all sockets"
98 <<
" which belong to this family");
102 SocketCollection::iterator sock =
sockets_.begin();
104 if (sock->family_ == family) {
107 close(sock->sockfd_);
109 if (sock->fallbackfd_ >= 0) {
110 close(sock->fallbackfd_);
135 for (
int i = 0; i <
mac_len_; i++) {
137 tmp << static_cast<int>(
mac_[i]);
148 <<
" was detected to have link address of length "
149 << len <<
", but maximum supported length is "
154 memcpy(
mac_, mac, len);
159 for (AddressCollection::iterator a =
addrs_.begin(); a !=
addrs_.end(); ++a) {
160 if (a->get() == addr) {
169 list<SocketInfo>::iterator sock =
sockets_.begin();
171 if (sock->sockfd_ == sockfd) {
174 if (sock->fallbackfd_ >= 0) {
175 close(sock->fallbackfd_);
188 test_mode_(false), allow_loopback_(false) {
195 }
catch (
const std::exception& ex) {
208 }
catch (
const std::exception& ex) {
215 if (a.get() == addr) {
217 <<
" already defined on the " <<
name_ <<
" interface.");
220 unicasts_.push_back(Optional<IOAddress>(addr));
230 if (addr.get().isV4()) {
231 address = addr.get();
242 if (address == addr.get()) {
258 for (
auto& addr :
addrs_) {
259 if (address == addr.get()) {
260 addr.unspecified(!active);
265 " found on the interface " <<
getName());
270 for (
auto& addr :
addrs_) {
271 addr.unspecified(!active);
279 if (!addr.unspecified() && addr.get().isV4()) {
294 iface->closeSockets();
300 dhcp_receiver_->stop();
303 dhcp_receiver_.reset();
320 return (packet_filter_->isDirectResponseSupported());
325 return (packet_filter_->isSocketReceivedTimeSupported());
334 std::lock_guard<std::mutex> lock(callbacks_mutex_);
338 if (s.socket_ == socketfd) {
339 s.callback_ = callback;
347 x.callback_ = callback;
348 callbacks_.push_back(x);
353 std::lock_guard<std::mutex> lock(callbacks_mutex_);
354 deleteExternalSocketInternal(socketfd);
358IfaceMgr::deleteExternalSocketInternal(
int socketfd) {
359 for (SocketCallbackInfoContainer::iterator s = callbacks_.begin();
360 s != callbacks_.end(); ++s) {
361 if (s->socket_ == socketfd) {
370 std::lock_guard<std::mutex> lock(callbacks_mutex_);
372 if (s.socket_ == fd) {
382 std::lock_guard<std::mutex> lock(callbacks_mutex_);
383 std::vector<int> bad_fds;
386 if (fcntl(s.socket_, F_GETFD) < 0 && (errno == EBADF)) {
387 bad_fds.push_back(s.socket_);
391 for (
auto bad_fd : bad_fds) {
392 deleteExternalSocketInternal(bad_fd);
395 return (bad_fds.size());
400 std::lock_guard<std::mutex> lock(callbacks_mutex_);
407 if (!packet_filter) {
420 "it is not allowed to set new packet"
421 <<
" filter when there are open IPv4 sockets - need"
422 <<
" to close them first");
425 packet_filter_ = packet_filter;
430 if (!packet_filter) {
438 "it is not allowed to set new packet"
439 <<
" filter when there are open IPv6 sockets - need"
440 <<
" to close them first");
443 packet_filter6_ = packet_filter;
450 for (
const SocketInfo& sock : iface->getSockets()) {
452 if (sock.family_ == family) {
470 for (
const SocketInfo& sock : iface->getSockets()) {
473 if (sock.addr_ == addr) {
475 }
else if (sock.addr_.isV6Zero()) {
482 if (addr == a.get()) {
499 const bool skip_opened) {
505 iface->clearErrors();
509 if (iface->inactive4_) {
520 if (iface->flag_loopback_ && !allow_loopback_) {
522 "must not open socket on the loopback"
523 " interface " << iface->getName());
527 if (!iface->flag_up_) {
529 "the interface " << iface->getName()
534 if (!iface->flag_running_) {
536 "the interface " << iface->getName()
537 <<
" is not running");
542 if (!iface->getAddress4(out_address)) {
544 "the interface " << iface->getName()
545 <<
" has no usable IPv4 addresses configured");
551 if (addr.unspecified() || !addr.get().isV4()) {
558 bool is_open_as_broadcast = iface->flag_broadcast_ && use_bcast;
575 "Binding socket to an interface is not"
576 " supported on this OS; therefore only"
577 " one socket listening to broadcast traffic"
578 " can be opened. Sockets will not be opened"
579 " on remaining interfaces");
591 is_open_as_broadcast,
592 is_open_as_broadcast);
595 "Failed to open socket on interface "
603 if (is_open_as_broadcast) {
629 const bool skip_opened) {
634 iface->clearErrors();
638 if (iface->inactive6_) {
649 if (iface->flag_loopback_ && !allow_loopback_) {
651 "must not open socket on the loopback"
652 " interface " << iface->getName());
654 }
else if (!iface->flag_up_) {
656 "the interface " << iface->getName()
659 }
else if (!iface->flag_running_) {
661 "the interface " << iface->getName()
662 <<
" is not running");
675 !iface->getSockets().size()) {
680 "Failed to open unicast socket on interface "
682 <<
", reason: " << ex.
what());
692 if (!addr.get().isV6()) {
701 if (!addr.get().isV6LinkLocal()){
716 !iface->getSockets().size()) {
720 IfaceMgr::openMulticastSocket(*iface, addr, port);
723 "Failed to open multicast socket on interface "
724 << iface->getName() <<
", reason: " << ex.
what());
756 dhcp_receiver_->start(std::bind(&IfaceMgr::receiveDHCP4Packets,
this));
766 dhcp_receiver_->start(std::bind(&IfaceMgr::receiveDHCP6Packets,
this));
777 if ((existing->getName() == iface->getName()) ||
778 (existing->getIndex() == iface->getIndex())) {
780 " when " << existing->getFullName() <<
792 out <<
"Detected interface " << iface->getFullName()
793 <<
", hwtype=" << iface->getHWType()
794 <<
", mac=" << iface->getPlainMac();
795 out <<
", flags=" << hex << iface->flags_ << dec <<
"("
796 << (iface->flag_loopback_?
"LOOPBACK ":
"")
797 << (iface->flag_up_?
"UP ":
"")
798 << (iface->flag_running_?
"RUNNING ":
"")
799 << (iface->flag_multicast_?
"MULTICAST ":
"")
800 << (iface->flag_broadcast_?
"BROADCAST ":
"")
802 out <<
" " << addrs.size() <<
" addr(s):";
805 out <<
" " << addr.get().toText();
822IfaceCollection::getIfaceInternal(
const unsigned int ifindex,
const bool need_lock) {
827 lock_guard<mutex> lock(mutex_);
828 if (cache_ && (cache_->getIndex() == ifindex)) {
832 if (cache_ && (cache_->getIndex() == ifindex)) {
836 auto const& idx = ifaces_container_.get<1>();
837 auto it = idx.find(ifindex);
838 if (it == idx.end()) {
842 lock_guard<mutex> lock(mutex_);
852IfaceCollection::getIfaceInternal(
const std::string& ifname,
const bool need_lock) {
854 lock_guard<mutex> lock(mutex_);
855 if (cache_ && (cache_->getName() == ifname)) {
859 if (cache_ && (cache_->getName() == ifname)) {
863 auto const& idx = ifaces_container_.get<2>();
864 auto it = idx.find(ifname);
865 if (it == idx.end()) {
869 lock_guard<mutex> lock(mutex_);
885 if (ifname.empty()) {
893 if (pkt->indexSet()) {
913 for (
const SocketInfo& sock : iface->getSockets()) {
928 iface->clearUnicasts();
933 const uint16_t port,
const bool receive_bcast,
934 const bool send_bcast) {
940 return openSocket4(*iface, addr, port, receive_bcast, send_bcast);
942 }
else if (addr.
isV6()) {
943 return openSocket6(*iface, addr, port, receive_bcast);
953 const uint8_t family) {
956 if ((iface->getFullName() != ifname) &&
957 (iface->getName() != ifname)) {
964 Iface::AddressCollection::iterator addr_it = addrs.begin();
965 while (addr_it != addrs.end()) {
966 if (addr_it->get().getFamily() == family) {
969 return (
openSocket(iface->getName(), *addr_it, port,
false));
975 if (addr_it == addrs.end()) {
977 std::string family_name(
"AF_INET");
978 if (family == AF_INET6) {
979 family_name =
"AF_INET6";
983 << ifname <<
", port: " << port <<
", address "
984 " family: " << family_name);
993 const uint16_t port) {
1003 if (a.get() == addr) {
1006 return (
openSocket(iface->getName(), a, port,
false));
1016 const uint16_t port) {
1019 IOAddress local_address(getLocalAddress(remote_addr, port));
1027IfaceMgr::getLocalAddress(
const IOAddress& remote_addr,
const uint16_t port) {
1029 boost::scoped_ptr<const UDPEndpoint>
1031 (UDPEndpoint::create(IPPROTO_UDP, remote_addr, port)));
1032 if (!remote_endpoint) {
1037 boost::asio::io_service io_service;
1038 boost::asio::ip::udp::socket sock(io_service);
1040 boost::system::error_code err_code;
1043 if (remote_addr.isV4() &&
1056 sock.open(boost::asio::ip::udp::v4(), err_code);
1058 const char* errstr = strerror(errno);
1062 sock.set_option(boost::asio::socket_base::broadcast(
true), err_code);
1070 sock.connect(remote_endpoint->getASIOEndpoint(), err_code);
1077 boost::asio::ip::udp::socket::endpoint_type local_endpoint =
1078 sock.local_endpoint();
1079 boost::asio::ip::address local_address(local_endpoint.address());
1090 const bool receive_bcast,
const bool send_bcast) {
1093 receive_bcast, send_bcast);
1094 iface.addSocket(
info);
1096 return (
info.sockfd_);
1104 << pkt->getIface() <<
") specified.");
1109 return (packet_filter6_->send(*iface,
getSocket(pkt), pkt) == 0);
1117 << pkt->getIface() <<
") specified.");
1122 return (packet_filter_->send(*iface,
getSocket(pkt).sockfd_, pkt) == 0);
1135 if (timeout_usec >= 1000000) {
1137 " one million microseconds");
1147 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1148 if (!callbacks_.empty()) {
1168 struct timeval select_timeout;
1170 select_timeout.tv_sec = timeout_sec;
1171 select_timeout.tv_usec = timeout_usec;
1173 select_timeout.tv_sec = 0;
1174 select_timeout.tv_usec = 0;
1180 int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1185 }
else if (result < 0) {
1193 if (errno == EINTR) {
1195 }
else if (errno == EBADF) {
1198 "SELECT interrupted by one invalid sockets, purged "
1199 << cnt <<
" socket descriptors");
1209 string msg = dhcp_receiver_->getLastError();
1218 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1220 if (!FD_ISSET(s.socket_, &sockets)) {
1235 if (ex_sock.callback_) {
1239 ex_sock.callback_(ex_sock.socket_);
1257 if (timeout_usec >= 1000000) {
1259 " one million microseconds");
1261 boost::scoped_ptr<SocketInfo> candidate;
1271 for (
const SocketInfo& s : iface->getSockets()) {
1273 if (s.addr_.isV4()) {
1282 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1283 if (!callbacks_.empty()) {
1291 struct timeval select_timeout;
1292 select_timeout.tv_sec = timeout_sec;
1293 select_timeout.tv_usec = timeout_usec;
1298 int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1304 }
else if (result < 0) {
1312 if (errno == EINTR) {
1314 }
else if (errno == EBADF) {
1317 "SELECT interrupted by one invalid sockets, purged "
1318 << cnt <<
" socket descriptors");
1328 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1330 if (!FD_ISSET(s.socket_, &sockets)) {
1345 if (ex_sock.callback_) {
1349 ex_sock.callback_(ex_sock.socket_);
1358 for (
const SocketInfo& s : iface->getSockets()) {
1359 if (FD_ISSET(s.sockfd_, &sockets)) {
1370 if (!candidate || !recv_if) {
1376 return (packet_filter_->receive(*recv_if, *candidate));
1394 FD_SET(fd, sockets);
1403 if (timeout_usec >= 1000000) {
1405 " one million microseconds");
1408 boost::scoped_ptr<SocketInfo> candidate;
1418 for (
const SocketInfo& s : iface->getSockets()) {
1420 if (s.addr_.isV6()) {
1429 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1430 if (!callbacks_.empty()) {
1438 struct timeval select_timeout;
1439 select_timeout.tv_sec = timeout_sec;
1440 select_timeout.tv_usec = timeout_usec;
1445 int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1451 }
else if (result < 0) {
1459 if (errno == EINTR) {
1461 }
else if (errno == EBADF) {
1464 "SELECT interrupted by one invalid sockets, purged "
1465 << cnt <<
" socket descriptors");
1475 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1477 if (!FD_ISSET(s.socket_, &sockets)) {
1492 if (ex_sock.callback_) {
1496 ex_sock.callback_(ex_sock.socket_);
1504 for (
const SocketInfo& s : iface->getSockets()) {
1505 if (FD_ISSET(s.sockfd_, &sockets)) {
1519 return (packet_filter6_->receive(*candidate));
1525 if (timeout_usec >= 1000000) {
1527 " one million microseconds");
1537 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1538 if (!callbacks_.empty()) {
1558 struct timeval select_timeout;
1560 select_timeout.tv_sec = timeout_sec;
1561 select_timeout.tv_usec = timeout_usec;
1563 select_timeout.tv_sec = 0;
1564 select_timeout.tv_usec = 0;
1570 int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1575 }
else if (result < 0) {
1583 if (errno == EINTR) {
1585 }
else if (errno == EBADF) {
1588 "SELECT interrupted by one invalid sockets, purged "
1589 << cnt <<
" socket descriptors");
1599 string msg = dhcp_receiver_->getLastError();
1608 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1610 if (!FD_ISSET(s.socket_, &sockets)) {
1625 if (ex_sock.callback_) {
1629 ex_sock.callback_(ex_sock.socket_);
1646IfaceMgr::receiveDHCP4Packets() {
1657 for (
const SocketInfo& s : iface->getSockets()) {
1659 if (s.addr_.isV4()) {
1668 if (dhcp_receiver_->shouldTerminate()) {
1679 int result = select(maxfd + 1, &rd_set, 0, 0, 0);
1682 if (dhcp_receiver_->shouldTerminate()) {
1690 }
else if (result < 0) {
1692 if (errno != EINTR) {
1694 dhcp_receiver_->setError(strerror(errno));
1705 for (
const SocketInfo& s : iface->getSockets()) {
1706 if (FD_ISSET(s.sockfd_, &sockets)) {
1707 receiveDHCP4Packet(*iface, s);
1709 if (dhcp_receiver_->shouldTerminate()) {
1720IfaceMgr::receiveDHCP6Packets() {
1731 for (
const SocketInfo& s : iface->getSockets()) {
1733 if (s.addr_.isV6()) {
1742 if (dhcp_receiver_->shouldTerminate()) {
1753 int result = select(maxfd + 1, &rd_set, 0, 0, 0);
1756 if (dhcp_receiver_->shouldTerminate()) {
1763 }
else if (result < 0) {
1765 if (errno != EINTR) {
1767 dhcp_receiver_->setError(strerror(errno));
1778 for (
const SocketInfo& s : iface->getSockets()) {
1779 if (FD_ISSET(s.sockfd_, &sockets)) {
1780 receiveDHCP6Packet(s);
1782 if (dhcp_receiver_->shouldTerminate()) {
1792IfaceMgr::receiveDHCP4Packet(Iface& iface,
const SocketInfo& socket_info) {
1795 int result = ioctl(socket_info.sockfd_, FIONREAD, &len);
1798 dhcp_receiver_->setError(strerror(errno));
1809 pkt = packet_filter_->receive(iface, socket_info);
1810 }
catch (
const std::exception& ex) {
1811 dhcp_receiver_->setError(strerror(errno));
1813 dhcp_receiver_->setError(
"packet filter receive() failed");
1823IfaceMgr::receiveDHCP6Packet(
const SocketInfo& socket_info) {
1826 int result = ioctl(socket_info.sockfd_, FIONREAD, &len);
1829 dhcp_receiver_->setError(strerror(errno));
1840 pkt = packet_filter6_->receive(socket_info);
1841 }
catch (
const std::exception& ex) {
1842 dhcp_receiver_->setError(ex.what());
1844 dhcp_receiver_->setError(
"packet filter receive() failed");
1862 Iface::SocketCollection::const_iterator candidate = socket_collection.end();
1864 Iface::SocketCollection::const_iterator s;
1865 for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
1870 if (s->family_ != AF_INET6) {
1875 if (s->addr_.isV6Multicast()) {
1879 if (s->addr_ == pkt->getLocalAddr()) {
1882 return (s->sockfd_);
1886 if (candidate == socket_collection.end()) {
1892 if ( (pkt->getRemoteAddr().isV6LinkLocal() &&
1893 s->addr_.isV6LinkLocal()) ||
1894 (!pkt->getRemoteAddr().isV6LinkLocal() &&
1895 !s->addr_.isV6LinkLocal()) ) {
1901 if (candidate != socket_collection.end()) {
1902 return (candidate->sockfd_);
1906 <<
" does not have any suitable IPv6 sockets open.");
1920 Iface::SocketCollection::const_iterator candidate = socket_collection.end();
1921 Iface::SocketCollection::const_iterator s;
1922 for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
1923 if (s->family_ == AF_INET) {
1924 if (s->addr_ == pkt->getLocalAddr()) {
1928 if (candidate == socket_collection.end()) {
1934 if (candidate == socket_collection.end()) {
1936 <<
" does not have any suitable IPv4 sockets open.");
1939 return (*candidate);
1946 " while DHCP receiver thread is running");
1949 bool enable_queue =
false;
1950 if (queue_control) {
1961 if (family == AF_INET) {
1962 packet_queue_mgr4_->createPacketQueue(queue_control);
1964 packet_queue_mgr6_->createPacketQueue(queue_control);
1968 if (family == AF_INET) {
1969 packet_queue_mgr4_->destroyPacketQueue();
1971 packet_queue_mgr6_->destroyPacketQueue();
1975 return (enable_queue);
1980 errors_.push_back(message);
1995 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.
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.
void clear()
Clear the collection.
void push_back(const IfacePtr &iface)
Adds an interface to the collection.
IfaceMgr exception thrown thrown when interface detection fails.
void clearIfaces()
Removes detected interfaces.
static void addFDtoSet(int fd, int &maxfd, fd_set *sockets)
Convenience method for adding an descriptor to a set.
bool isExternalSocket(int fd)
Checks if socket's file description is registered.
int purgeBadSockets()
Scans registered socket set and removes any that are invalid.
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.
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.
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.
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.
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.
SocketCollection sockets_
Socket used to send data.
const AddressCollection & getAddresses() const
Returns all addresses available on an interface.
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 delSocket(uint16_t sockfd)
Closes socket.
std::list< Address > AddressCollection
Type that defines list of addresses.
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)
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.
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 no suitable socket found.
IfaceMgr exception thrown thrown when error occurred during reading data from socket.
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 FD_COPY(orig, copy)
#define IFACEMGR_ERROR(ex_type, handler, iface, stream)
A macro which handles an error in IfaceMgr.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
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.
std::function< void(const std::string &errmsg) IfaceMgrErrorMsgCallback)
This type describes the callback function invoked when error occurs in the IfaceMgr.
constexpr unsigned int UNSET_IFINDEX
A value used to signal that the interface index was not set.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
boost::shared_ptr< PktFilter6 > PktFilter6Ptr
Pointer to a PktFilter object.
Defines the logger used by the top-level component of kea-lfc.
Keeps callback information for external sockets.
int socket_
Socket descriptor of the external socket.
Holds information about socket.