21 #include <boost/scoped_ptr.hpp>
30 #include <arpa/inet.h>
31 #include <netinet/in.h>
33 #include <sys/ioctl.h>
34 #include <sys/select.h>
37 #define FD_COPY(orig, copy) \
39 memmove(copy, orig, sizeof(fd_set)); \
53 IfaceMgr::instance() {
54 return (*instancePtr());
58 IfaceMgr::instancePtr() {
63 Iface::Iface(
const std::string& name,
unsigned int ifindex)
64 :
name_(name), ifindex_(ifindex), mac_len_(0), hardware_type_(0),
65 flag_loopback_(false), flag_up_(false), flag_running_(false),
66 flag_multicast_(false), flag_broadcast_(false), flags_(0),
67 inactive4_(false), inactive6_(false) {
94 if ((family != AF_INET) && (family != AF_INET6)) {
96 <<
" specified when requested to close all sockets"
97 <<
" which belong to this family");
101 SocketCollection::iterator sock =
sockets_.begin();
103 if (sock->family_ == family) {
106 close(sock->sockfd_);
108 if (sock->fallbackfd_ >= 0) {
109 close(sock->fallbackfd_);
134 for (
int i = 0; i <
mac_len_; i++) {
136 tmp << static_cast<int>(
mac_[i]);
147 <<
" was detected to have link address of length "
148 << len <<
", but maximum supported length is "
153 memcpy(
mac_, mac, len);
158 for (AddressCollection::iterator a =
addrs_.begin();
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_);
189 allow_loopback_(false) {
196 }
catch (
const std::exception& ex) {
207 }
catch (
const std::exception& ex) {
214 if (a.get() == addr) {
216 <<
" already defined on the " <<
name_ <<
" interface.");
229 if (addr.get().isV4()) {
230 address = addr.get();
241 if (address == addr.get()) {
257 for (AddressCollection::iterator addr_it =
addrs_.begin();
258 addr_it !=
addrs_.end(); ++addr_it) {
259 if (address == addr_it->get()) {
260 addr_it->unspecified(!active);
265 " found on the interface " <<
getName());
270 for (AddressCollection::iterator addr_it =
addrs_.begin();
271 addr_it !=
addrs_.end(); ++addr_it) {
272 addr_it->unspecified(!active);
280 if (!addr.unspecified() && addr.get().isV4()) {
295 iface->closeSockets();
301 dhcp_receiver_->stop();
304 dhcp_receiver_.reset();
321 return (packet_filter_->isDirectResponseSupported());
330 std::lock_guard<std::mutex> lock(callbacks_mutex_);
334 if (s.socket_ == socketfd) {
335 s.callback_ = callback;
344 callbacks_.push_back(x);
349 std::lock_guard<std::mutex> lock(callbacks_mutex_);
350 deleteExternalSocketInternal(socketfd);
354 IfaceMgr::deleteExternalSocketInternal(
int socketfd) {
355 for (SocketCallbackInfoContainer::iterator s = callbacks_.begin();
356 s != callbacks_.end(); ++s) {
357 if (s->socket_ == socketfd) {
366 std::lock_guard<std::mutex> lock(callbacks_mutex_);
367 std::vector<int> bad_fds;
370 if (fcntl(s.socket_, F_GETFD) < 0 && (errno == EBADF)) {
371 bad_fds.push_back(s.socket_);
375 for (
auto bad_fd : bad_fds) {
376 deleteExternalSocketInternal(bad_fd);
379 return (bad_fds.size());
384 std::lock_guard<std::mutex> lock(callbacks_mutex_);
391 if (!packet_filter) {
404 "it is not allowed to set new packet"
405 <<
" filter when there are open IPv4 sockets - need"
406 <<
" to close them first");
409 packet_filter_ = packet_filter;
414 if (!packet_filter) {
422 "it is not allowed to set new packet"
423 <<
" filter when there are open IPv6 sockets - need"
424 <<
" to close them first");
427 packet_filter6_ = packet_filter;
436 if (sock.family_ == family) {
457 if (sock.addr_ == addr) {
459 }
else if (sock.addr_.isV6Zero()) {
466 if (addr == a.get()) {
482 const string v4addr(
"127.0.0.1"), v6addr(
"::1");
488 if (if_nametoindex(
"lo") > 0) {
491 }
else if (if_nametoindex(
"lo0") > 0) {
497 "Interface detection on this OS is not supported.");
500 IfacePtr iface(
new Iface(ifaceName, if_nametoindex(ifaceName.c_str())));
501 iface->flag_up_ =
true;
502 iface->flag_running_ =
true;
508 iface->flag_loopback_ =
false;
509 iface->flag_multicast_ =
true;
510 iface->flag_broadcast_ =
true;
511 iface->setHWType(HWTYPE_ETHERNET);
521 const bool skip_opened) {
527 iface->clearErrors();
531 if (iface->inactive4_) {
542 if (iface->flag_loopback_ && !allow_loopback_) {
544 "must not open socket on the loopback"
545 " interface " << iface->getName());
549 if (!iface->flag_up_) {
551 "the interface " << iface->getName()
556 if (!iface->flag_running_) {
558 "the interface " << iface->getName()
559 <<
" is not running");
564 if (!iface->getAddress4(out_address)) {
566 "the interface " << iface->getName()
567 <<
" has no usable IPv4 addresses configured");
573 if (addr.unspecified() || !addr.get().isV4()) {
580 bool is_open_as_broadcast = iface->flag_broadcast_ && use_bcast;
597 "Binding socket to an interface is not"
598 " supported on this OS; therefore only"
599 " one socket listening to broadcast traffic"
600 " can be opened. Sockets will not be opened"
601 " on remaining interfaces");
613 is_open_as_broadcast,
614 is_open_as_broadcast);
617 "Failed to open socket on interface "
625 if (is_open_as_broadcast) {
651 const bool skip_opened) {
656 iface->clearErrors();
660 if (iface->inactive6_) {
671 if (iface->flag_loopback_ && !allow_loopback_) {
673 "must not open socket on the loopback"
674 " interface " << iface->getName());
676 }
else if (!iface->flag_up_) {
678 "the interface " << iface->getName()
681 }
else if (!iface->flag_running_) {
683 "the interface " << iface->getName()
684 <<
" is not running");
697 !iface->getSockets().size()) {
702 "Failed to open unicast socket on interface "
704 <<
", reason: " << ex.
what());
715 if (!addr.get().isV6()) {
724 if (!addr.get().isV6LinkLocal()){
739 !iface->getSockets().size()) {
743 IfaceMgr::openMulticastSocket(*iface, addr, port);
746 "Failed to open multicast socket on interface "
747 << iface->getName() <<
", reason: " << ex.
what());
779 dhcp_receiver_->start(std::bind(&IfaceMgr::receiveDHCP4Packets,
this));
789 dhcp_receiver_->start(std::bind(&IfaceMgr::receiveDHCP6Packets,
this));
800 if ((existing->getName() == iface->getName()) ||
801 (existing->getIndex() == iface->getIndex())) {
803 " when " << existing->getFullName() <<
815 out <<
"Detected interface " << iface->getFullName()
816 <<
", hwtype=" << iface->getHWType()
817 <<
", mac=" << iface->getPlainMac();
818 out <<
", flags=" << hex << iface->flags_ << dec <<
"("
819 << (iface->flag_loopback_?
"LOOPBACK ":
"")
820 << (iface->flag_up_?
"UP ":
"")
821 << (iface->flag_running_?
"RUNNING ":
"")
822 << (iface->flag_multicast_?
"MULTICAST ":
"")
823 << (iface->flag_broadcast_?
"BROADCAST ":
"")
825 out <<
" " << addrs.size() <<
" addr(s):";
828 out <<
" " << addr.get().toText();
836 return (getIfaceInternal(ifindex, MultiThreadingMgr::instance().getMode()));
842 return (getIfaceInternal(ifname, MultiThreadingMgr::instance().getMode()));
846 IfaceCollection::getIfaceInternal(
const unsigned int ifindex,
const bool need_lock) {
851 lock_guard<mutex> lock(mutex_);
852 if (cache_ && (cache_->getIndex() == ifindex)) {
856 if (cache_ && (cache_->getIndex() == ifindex)) {
860 const auto& idx = ifaces_container_.get<1>();
861 auto it = idx.find(ifindex);
862 if (it == idx.end()) {
866 lock_guard<mutex> lock(mutex_);
876 IfaceCollection::getIfaceInternal(
const std::string& ifname,
const bool need_lock) {
878 lock_guard<mutex> lock(mutex_);
879 if (cache_ && (cache_->getName() == ifname)) {
883 if (cache_ && (cache_->getName() == ifname)) {
887 const auto& idx = ifaces_container_.get<2>();
888 auto it = idx.find(ifname);
889 if (it == idx.end()) {
893 lock_guard<mutex> lock(mutex_);
909 if (ifname.empty()) {
917 if (pkt->indexSet()) {
952 iface->clearUnicasts();
957 const uint16_t port,
const bool receive_bcast,
958 const bool send_bcast) {
964 return openSocket4(*iface, addr, port, receive_bcast, send_bcast);
966 }
else if (addr.
isV6()) {
967 return openSocket6(*iface, addr, port, receive_bcast);
977 const uint8_t family) {
980 if ((iface->getFullName() != ifname) &&
981 (iface->getName() != ifname)) {
988 Iface::AddressCollection::iterator addr_it = addrs.begin();
989 while (addr_it != addrs.end()) {
990 if (addr_it->get().getFamily() == family) {
993 return (
openSocket(iface->getName(), *addr_it, port,
false));
999 if (addr_it == addrs.end()) {
1001 std::string family_name(
"AF_INET");
1002 if (family == AF_INET6) {
1003 family_name =
"AF_INET6";
1007 << ifname <<
", port: " << port <<
", address "
1008 " family: " << family_name);
1017 const uint16_t port) {
1027 if (a.get() == addr) {
1030 return (
openSocket(iface->getName(), a, port,
false));
1040 const uint16_t port) {
1043 IOAddress local_address(getLocalAddress(remote_addr, port));
1051 IfaceMgr::getLocalAddress(
const IOAddress& remote_addr,
const uint16_t port) {
1053 boost::scoped_ptr<const UDPEndpoint>
1056 if (!remote_endpoint) {
1061 boost::asio::io_service io_service;
1062 boost::asio::ip::udp::socket sock(io_service);
1064 boost::system::error_code err_code;
1067 if (remote_addr.
isV4() &&
1080 sock.open(boost::asio::ip::udp::v4(), err_code);
1082 const char* errstr = strerror(errno);
1086 sock.set_option(boost::asio::socket_base::broadcast(
true), err_code);
1089 isc_throw(Unexpected,
"failed to enable broadcast on the socket");
1094 sock.connect(remote_endpoint->getASIOEndpoint(), err_code);
1097 isc_throw(Unexpected,
"failed to connect to remote endpoint.");
1101 boost::asio::ip::udp::socket::endpoint_type local_endpoint =
1102 sock.local_endpoint();
1103 boost::asio::ip::address local_address(local_endpoint.address());
1114 const bool receive_bcast,
const bool send_bcast) {
1117 receive_bcast, send_bcast);
1120 return (
info.sockfd_);
1128 << pkt->getIface() <<
") specified.");
1133 return (packet_filter6_->send(*iface,
getSocket(pkt), pkt) == 0);
1141 << pkt->getIface() <<
") specified.");
1146 return (packet_filter_->send(*iface,
getSocket(pkt).sockfd_, pkt) == 0);
1159 if (timeout_usec >= 1000000) {
1161 " one million microseconds");
1171 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1172 if (!callbacks_.empty()) {
1181 addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::READY), maxfd, &sockets);
1192 struct timeval select_timeout;
1194 select_timeout.tv_sec = timeout_sec;
1195 select_timeout.tv_usec = timeout_usec;
1197 select_timeout.tv_sec = 0;
1198 select_timeout.tv_usec = 0;
1204 int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1209 }
else if (result < 0) {
1217 if (errno == EINTR) {
1219 }
else if (errno == EBADF) {
1222 "SELECT interrupted by one invalid sockets, purged "
1223 << cnt <<
" socket descriptors");
1233 string msg = dhcp_receiver_->getLastError();
1242 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1244 if (!FD_ISSET(s.socket_, &sockets)) {
1273 dhcp_receiver_->clearReady(WatchedThread::READY);
1281 if (timeout_usec >= 1000000) {
1283 " one million microseconds");
1285 boost::scoped_ptr<SocketInfo> candidate;
1297 if (s.addr_.isV4()) {
1306 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1307 if (!callbacks_.empty()) {
1315 struct timeval select_timeout;
1316 select_timeout.tv_sec = timeout_sec;
1317 select_timeout.tv_usec = timeout_usec;
1322 int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1328 }
else if (result < 0) {
1336 if (errno == EINTR) {
1338 }
else if (errno == EBADF) {
1341 "SELECT interrupted by one invalid sockets, purged "
1342 << cnt <<
" socket descriptors");
1352 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1354 if (!FD_ISSET(s.socket_, &sockets)) {
1383 if (FD_ISSET(s.sockfd_, &sockets)) {
1394 if (!candidate || !recv_if) {
1400 return (packet_filter_->receive(*recv_if, *candidate));
1418 FD_SET(fd, sockets);
1427 if (timeout_usec >= 1000000) {
1429 " one million microseconds");
1432 boost::scoped_ptr<SocketInfo> candidate;
1444 if (s.addr_.isV6()) {
1453 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1454 if (!callbacks_.empty()) {
1462 struct timeval select_timeout;
1463 select_timeout.tv_sec = timeout_sec;
1464 select_timeout.tv_usec = timeout_usec;
1469 int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1475 }
else if (result < 0) {
1483 if (errno == EINTR) {
1485 }
else if (errno == EBADF) {
1488 "SELECT interrupted by one invalid sockets, purged "
1489 << cnt <<
" socket descriptors");
1499 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1501 if (!FD_ISSET(s.socket_, &sockets)) {
1529 if (FD_ISSET(s.sockfd_, &sockets)) {
1543 return (packet_filter6_->receive(*candidate));
1549 if (timeout_usec >= 1000000) {
1551 " one million microseconds");
1561 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1562 if (!callbacks_.empty()) {
1571 addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::READY), maxfd, &sockets);
1582 struct timeval select_timeout;
1584 select_timeout.tv_sec = timeout_sec;
1585 select_timeout.tv_usec = timeout_usec;
1587 select_timeout.tv_sec = 0;
1588 select_timeout.tv_usec = 0;
1594 int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1599 }
else if (result < 0) {
1607 if (errno == EINTR) {
1609 }
else if (errno == EBADF) {
1612 "SELECT interrupted by one invalid sockets, purged "
1613 << cnt <<
" socket descriptors");
1623 string msg = dhcp_receiver_->getLastError();
1632 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1634 if (!FD_ISSET(s.socket_, &sockets)) {
1663 dhcp_receiver_->clearReady(WatchedThread::READY);
1670 IfaceMgr::receiveDHCP4Packets() {
1677 addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::TERMINATE), maxfd, &sockets);
1683 if (s.addr_.isV4()) {
1692 if (dhcp_receiver_->shouldTerminate()) {
1703 int result = select(maxfd + 1, &rd_set, 0, 0, 0);
1706 if (dhcp_receiver_->shouldTerminate()) {
1714 }
else if (result < 0) {
1716 if (errno != EINTR) {
1718 dhcp_receiver_->setError(strerror(errno));
1729 for (SocketInfo s : iface->getSockets()) {
1730 if (FD_ISSET(s.sockfd_, &sockets)) {
1731 receiveDHCP4Packet(*iface, s);
1733 if (dhcp_receiver_->shouldTerminate()) {
1744 IfaceMgr::receiveDHCP6Packets() {
1751 addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::TERMINATE), maxfd, &sockets);
1755 for (SocketInfo s : iface->getSockets()) {
1757 if (s.addr_.isV6()) {
1766 if (dhcp_receiver_->shouldTerminate()) {
1777 int result = select(maxfd + 1, &rd_set, 0, 0, 0);
1780 if (dhcp_receiver_->shouldTerminate()) {
1787 }
else if (result < 0) {
1789 if (errno != EINTR) {
1791 dhcp_receiver_->setError(strerror(errno));
1802 for (SocketInfo s : iface->getSockets()) {
1803 if (FD_ISSET(s.sockfd_, &sockets)) {
1804 receiveDHCP6Packet(s);
1806 if (dhcp_receiver_->shouldTerminate()) {
1816 IfaceMgr::receiveDHCP4Packet(Iface& iface,
const SocketInfo& socket_info) {
1819 int result = ioctl(socket_info.sockfd_, FIONREAD, &len);
1822 dhcp_receiver_->setError(strerror(errno));
1833 pkt = packet_filter_->receive(iface, socket_info);
1834 }
catch (
const std::exception& ex) {
1835 dhcp_receiver_->setError(strerror(errno));
1837 dhcp_receiver_->setError(
"packet filter receive() failed");
1842 dhcp_receiver_->markReady(WatchedThread::READY);
1847 IfaceMgr::receiveDHCP6Packet(
const SocketInfo& socket_info) {
1850 int result = ioctl(socket_info.sockfd_, FIONREAD, &len);
1853 dhcp_receiver_->setError(strerror(errno));
1864 pkt = packet_filter6_->receive(socket_info);
1865 }
catch (
const std::exception& ex) {
1866 dhcp_receiver_->setError(ex.what());
1868 dhcp_receiver_->setError(
"packet filter receive() failed");
1873 dhcp_receiver_->markReady(WatchedThread::READY);
1887 Iface::SocketCollection::const_iterator candidate = socket_collection.end();
1889 Iface::SocketCollection::const_iterator s;
1890 for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
1895 if (s->family_ != AF_INET6) {
1900 if (s->addr_.isV6Multicast()) {
1904 if (s->addr_ == pkt->getLocalAddr()) {
1907 return (s->sockfd_);
1911 if (candidate == socket_collection.end()) {
1917 if ( (pkt->getRemoteAddr().isV6LinkLocal() &&
1918 s->addr_.isV6LinkLocal()) ||
1919 (!pkt->getRemoteAddr().isV6LinkLocal() &&
1920 !s->addr_.isV6LinkLocal()) ) {
1926 if (candidate != socket_collection.end()) {
1927 return (candidate->sockfd_);
1931 <<
" does not have any suitable IPv6 sockets open.");
1945 Iface::SocketCollection::const_iterator candidate = socket_collection.end();
1946 Iface::SocketCollection::const_iterator s;
1947 for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
1948 if (s->family_ == AF_INET) {
1949 if (s->addr_ == pkt->getLocalAddr()) {
1953 if (candidate == socket_collection.end()) {
1959 if (candidate == socket_collection.end()) {
1961 <<
" does not have any suitable IPv4 sockets open.");
1964 return (*candidate);
1971 " while DHCP receiver thread is running");
1974 bool enable_queue =
false;
1975 if (queue_control) {
1986 if (family == AF_INET) {
1987 packet_queue_mgr4_->createPacketQueue(queue_control);
1989 packet_queue_mgr6_->createPacketQueue(queue_control);
1993 if (family == AF_INET) {
1994 packet_queue_mgr4_->destroyPacketQueue();
1996 packet_queue_mgr6_->destroyPacketQueue();
2000 return (enable_queue);
2005 errors_.push_back(message);
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 when a function is not implemented.
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.
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.
Handles network interfaces, transmission and reception.
void clearIfaces()
Removes detected interfaces.
static void addFDtoSet(int fd, int &maxfd, fd_set *sockets)
Convenience method for adding an descriptor to a set.
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.
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.
void stubDetectIfaces()
Stub implementation of network interface detection.
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 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.
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.
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.
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.
void addSocket(const SocketInfo &sock)
Adds socket descriptor to an interface.
const AddressCollection & getAddresses() const
Returns all addresses available on an 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 DHPCv4 servers.
Packet Queue Manager for DHPCv6 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.
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.
SocketCallback callback_
A callback that will be called when data arrives over socket_.
int socket_
Socket descriptor of the external socket.
Holds information about socket.