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)); \
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)
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();
161 if (a->get() == addr) {
170 list<SocketInfo>::iterator sock =
sockets_.begin();
172 if (sock->sockfd_ == sockfd) {
175 if (sock->fallbackfd_ >= 0) {
176 close(sock->fallbackfd_);
190 allow_loopback_(false) {
197 }
catch (
const std::exception& ex) {
208 }
catch (
const std::exception& ex) {
215 if (a.get() == addr) {
217 <<
" already defined on the " <<
name_ <<
" interface.");
230 if (addr.get().isV4()) {
231 address = addr.get();
242 if (address == addr.get()) {
256 for (AddressCollection::iterator addr_it =
addrs_.begin();
257 addr_it !=
addrs_.end(); ++addr_it) {
258 if (address == addr_it->get()) {
259 addr_it->unspecified(!active);
264 " found on the interface " <<
getName());
269 for (AddressCollection::iterator addr_it =
addrs_.begin();
270 addr_it !=
addrs_.end(); ++addr_it) {
271 addr_it->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());
329 std::lock_guard<std::mutex> lock(callbacks_mutex_);
333 if (s.socket_ == socketfd) {
334 s.callback_ = callback;
343 callbacks_.push_back(x);
348 std::lock_guard<std::mutex> lock(callbacks_mutex_);
349 deleteExternalSocketInternal(socketfd);
353IfaceMgr::deleteExternalSocketInternal(
int socketfd) {
354 for (SocketCallbackInfoContainer::iterator s = callbacks_.begin();
355 s != callbacks_.end(); ++s) {
356 if (s->socket_ == socketfd) {
365 std::lock_guard<std::mutex> lock(callbacks_mutex_);
366 std::vector<int> bad_fds;
369 if (fcntl(s.socket_, F_GETFD) < 0 && (errno == EBADF)) {
370 bad_fds.push_back(s.socket_);
374 for (
auto bad_fd : bad_fds) {
375 deleteExternalSocketInternal(bad_fd);
378 return (bad_fds.size());
383 std::lock_guard<std::mutex> lock(callbacks_mutex_);
390 if (!packet_filter) {
403 "it is not allowed to set new packet"
404 <<
" filter when there are open IPv4 sockets - need"
405 <<
" to close them first");
408 packet_filter_ = packet_filter;
413 if (!packet_filter) {
421 "it is not allowed to set new packet"
422 <<
" filter when there are open IPv6 sockets - need"
423 <<
" to close them first");
426 packet_filter6_ = packet_filter;
435 if (sock.family_ == family) {
456 if (sock.addr_ == addr) {
458 }
else if (sock.addr_.isV6Zero()) {
465 if (addr == a.get()) {
481 const string v4addr(
"127.0.0.1"), v6addr(
"::1");
487 if (if_nametoindex(
"lo") > 0) {
490 }
else if (if_nametoindex(
"lo0") > 0) {
496 "Interface detection on this OS is not supported.");
499 IfacePtr iface(
new Iface(ifaceName, if_nametoindex(ifaceName.c_str())));
500 iface->flag_up_ =
true;
501 iface->flag_running_ =
true;
507 iface->flag_loopback_ =
false;
508 iface->flag_multicast_ =
true;
509 iface->flag_broadcast_ =
true;
510 iface->setHWType(HWTYPE_ETHERNET);
526 if (iface->inactive4_) {
537 if (iface->flag_loopback_ && !allow_loopback_) {
539 "must not open socket on the loopback"
540 " interface " << iface->getName());
545 if (!iface->flag_up_) {
547 "the interface " << iface->getName()
552 if (!iface->flag_running_) {
554 "the interface " << iface->getName()
555 <<
" is not running");
560 if (!iface->getAddress4(out_address)) {
562 "the interface " << iface->getName()
563 <<
" has no usable IPv4 addresses configured");
570 if (addr.unspecified() || !addr.get().isV4()) {
577 if (iface->flag_broadcast_ && use_bcast) {
593 "Binding socket to an interface is not"
594 " supported on this OS; therefore only"
595 " one socket listening to broadcast traffic"
596 " can be opened. Sockets will not be opened"
597 " on remaining interfaces");
604 openSocket(iface->getName(), addr.get(), port,
true,
true);
607 "failed to open socket on interface "
608 << iface->getName() <<
", reason: "
622 openSocket(iface->getName(), addr.get(), port,
false,
false);
625 "failed to open socket on interface "
626 << iface->getName() <<
", reason: "
655 if (iface->inactive6_) {
666 if (iface->flag_loopback_ && !allow_loopback_) {
668 "must not open socket on the loopback"
669 " interface " << iface->getName());
672 }
else if (!iface->flag_up_) {
674 "the interface " << iface->getName()
677 }
else if (!iface->flag_running_) {
679 "the interface " << iface->getName()
680 <<
" is not running");
693 "Failed to open unicast socket on interface "
694 << iface->getName() <<
", reason: "
706 if (!addr.get().isV6()) {
715 if (!addr.get().isV6LinkLocal()){
722 if (openMulticastSocket(*iface, addr, port, error_handler)) {
752 dhcp_receiver_->start(std::bind(&IfaceMgr::receiveDHCP4Packets,
this));
762 dhcp_receiver_->start(std::bind(&IfaceMgr::receiveDHCP6Packets,
this));
773 if ((existing->getName() == iface->getName()) ||
774 (existing->getIndex() == iface->getIndex())) {
776 " when " << existing->getFullName() <<
788 out <<
"Detected interface " << iface->getFullName()
789 <<
", hwtype=" << iface->getHWType()
790 <<
", mac=" << iface->getPlainMac();
791 out <<
", flags=" << hex << iface->flags_ << dec <<
"("
792 << (iface->flag_loopback_?
"LOOPBACK ":
"")
793 << (iface->flag_up_?
"UP ":
"")
794 << (iface->flag_running_?
"RUNNING ":
"")
795 << (iface->flag_multicast_?
"MULTICAST ":
"")
796 << (iface->flag_broadcast_?
"BROADCAST ":
"")
798 out <<
" " << addrs.size() <<
" addr(s):";
801 out <<
" " << addr.get().toText();
809 return (getIfaceInternal(ifindex, MultiThreadingMgr::instance().getMode()));
815 return (getIfaceInternal(ifname, MultiThreadingMgr::instance().getMode()));
819IfaceCollection::getIfaceInternal(uint32_t ifindex,
bool need_lock) {
821 lock_guard<mutex> lock(mutex_);
822 if (cache_ && (cache_->getIndex() == ifindex)) {
826 if (cache_ && (cache_->getIndex() == ifindex)) {
830 const auto& idx = ifaces_container_.get<1>();
831 auto it = idx.find(ifindex);
832 if (it == idx.end()) {
836 lock_guard<mutex> lock(mutex_);
840 lock_guard<mutex> lock(mutex_);
847IfaceCollection::getIfaceInternal(
const std::string& ifname,
bool need_lock) {
849 lock_guard<mutex> lock(mutex_);
850 if (cache_ && (cache_->getName() == ifname)) {
854 if (cache_ && (cache_->getName() == ifname)) {
858 const auto& idx = ifaces_container_.get<2>();
859 auto it = idx.find(ifname);
860 if (it == idx.end()) {
864 lock_guard<mutex> lock(mutex_);
868 lock_guard<mutex> lock(mutex_);
876 if ((ifindex < 0) || (ifindex > std::numeric_limits<int32_t>::max())) {
884 if (ifname.empty()) {
892 if (pkt->indexSet()) {
927 iface->clearUnicasts();
932 const uint16_t port,
const bool receive_bcast,
933 const bool send_bcast) {
939 return openSocket4(*iface, addr, port, receive_bcast, send_bcast);
941 }
else if (addr.
isV6()) {
942 return openSocket6(*iface, addr, port, receive_bcast);
952 const uint8_t family) {
955 if ((iface->getFullName() != ifname) &&
956 (iface->getName() != ifname)) {
963 Iface::AddressCollection::iterator addr_it = addrs.begin();
964 while (addr_it != addrs.end()) {
965 if (addr_it->get().getFamily() == family) {
968 return (
openSocket(iface->getName(), *addr_it, port,
false));
974 if (addr_it == addrs.end()) {
976 std::string family_name(
"AF_INET");
977 if (family == AF_INET6) {
978 family_name =
"AF_INET6";
982 << ifname <<
", port: " << port <<
", address "
983 " family: " << family_name);
992 const uint16_t port) {
1002 if (a.get() == addr) {
1005 return (
openSocket(iface->getName(), a, port,
false));
1015 const uint16_t port) {
1018 IOAddress local_address(getLocalAddress(remote_addr, port));
1026IfaceMgr::getLocalAddress(
const IOAddress& remote_addr,
const uint16_t port) {
1028 boost::scoped_ptr<const UDPEndpoint>
1031 if (!remote_endpoint) {
1036 boost::asio::io_service io_service;
1037 boost::asio::ip::udp::socket sock(io_service);
1039 boost::system::error_code err_code;
1042 if (remote_addr.
isV4() &&
1055 sock.open(boost::asio::ip::udp::v4(), err_code);
1057 const char* errstr = strerror(errno);
1061 sock.set_option(boost::asio::socket_base::broadcast(
true), err_code);
1064 isc_throw(Unexpected,
"failed to enable broadcast on the socket");
1069 sock.connect(remote_endpoint->getASIOEndpoint(), err_code);
1072 isc_throw(Unexpected,
"failed to connect to remote endpoint.");
1076 boost::asio::ip::udp::socket::endpoint_type local_endpoint =
1077 sock.local_endpoint();
1078 boost::asio::ip::address local_address(local_endpoint.address());
1089 const uint16_t port,
const bool receive_bcast,
1090 const bool send_bcast) {
1094 receive_bcast, send_bcast);
1097 return (
info.sockfd_);
1105 << pkt->getIface() <<
") specified.");
1110 return (packet_filter6_->send(*iface,
getSocket(pkt), pkt) == 0);
1118 << pkt->getIface() <<
") specified.");
1123 return (packet_filter_->send(*iface,
getSocket(pkt).sockfd_, pkt) == 0);
1136 if (timeout_usec >= 1000000) {
1138 " one million microseconds");
1148 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1149 if (!callbacks_.empty()) {
1158 addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::READY), maxfd, &sockets);
1169 struct timeval select_timeout;
1171 select_timeout.tv_sec = timeout_sec;
1172 select_timeout.tv_usec = timeout_usec;
1174 select_timeout.tv_sec = 0;
1175 select_timeout.tv_usec = 0;
1181 int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1186 }
else if (result < 0) {
1194 if (errno == EINTR) {
1196 }
else if (errno == EBADF) {
1199 "SELECT interrupted by one invalid sockets, purged "
1200 << cnt <<
" socket descriptors");
1210 string msg = dhcp_receiver_->getLastError();
1219 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1221 if (!FD_ISSET(s.socket_, &sockets)) {
1250 dhcp_receiver_->clearReady(WatchedThread::READY);
1258 if (timeout_usec >= 1000000) {
1260 " one million microseconds");
1262 boost::scoped_ptr<SocketInfo> candidate;
1274 if (s.addr_.isV4()) {
1283 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1284 if (!callbacks_.empty()) {
1292 struct timeval select_timeout;
1293 select_timeout.tv_sec = timeout_sec;
1294 select_timeout.tv_usec = timeout_usec;
1299 int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1305 }
else if (result < 0) {
1313 if (errno == EINTR) {
1315 }
else if (errno == EBADF) {
1318 "SELECT interrupted by one invalid sockets, purged "
1319 << cnt <<
" socket descriptors");
1329 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1331 if (!FD_ISSET(s.socket_, &sockets)) {
1360 if (FD_ISSET(s.sockfd_, &sockets)) {
1371 if (!candidate || !recv_if) {
1377 return (packet_filter_->receive(*recv_if, *candidate));
1395 FD_SET(fd, sockets);
1404 if (timeout_usec >= 1000000) {
1406 " one million microseconds");
1409 boost::scoped_ptr<SocketInfo> candidate;
1421 if (s.addr_.isV6()) {
1430 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1431 if (!callbacks_.empty()) {
1439 struct timeval select_timeout;
1440 select_timeout.tv_sec = timeout_sec;
1441 select_timeout.tv_usec = timeout_usec;
1446 int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1452 }
else if (result < 0) {
1460 if (errno == EINTR) {
1462 }
else if (errno == EBADF) {
1465 "SELECT interrupted by one invalid sockets, purged "
1466 << cnt <<
" socket descriptors");
1476 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1478 if (!FD_ISSET(s.socket_, &sockets)) {
1506 if (FD_ISSET(s.sockfd_, &sockets)) {
1520 return (packet_filter6_->receive(*candidate));
1526 if (timeout_usec >= 1000000) {
1528 " one million microseconds");
1538 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1539 if (!callbacks_.empty()) {
1548 addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::READY), maxfd, &sockets);
1559 struct timeval select_timeout;
1561 select_timeout.tv_sec = timeout_sec;
1562 select_timeout.tv_usec = timeout_usec;
1564 select_timeout.tv_sec = 0;
1565 select_timeout.tv_usec = 0;
1571 int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1576 }
else if (result < 0) {
1584 if (errno == EINTR) {
1586 }
else if (errno == EBADF) {
1589 "SELECT interrupted by one invalid sockets, purged "
1590 << cnt <<
" socket descriptors");
1600 string msg = dhcp_receiver_->getLastError();
1609 std::lock_guard<std::mutex> lock(callbacks_mutex_);
1611 if (!FD_ISSET(s.socket_, &sockets)) {
1640 dhcp_receiver_->clearReady(WatchedThread::READY);
1647IfaceMgr::receiveDHCP4Packets() {
1654 addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::TERMINATE), maxfd, &sockets);
1660 if (s.addr_.isV4()) {
1669 if (dhcp_receiver_->shouldTerminate()) {
1680 int result = select(maxfd + 1, &rd_set, 0, 0, 0);
1683 if (dhcp_receiver_->shouldTerminate()) {
1691 }
else if (result < 0) {
1693 if (errno != EINTR) {
1695 dhcp_receiver_->setError(strerror(errno));
1706 for (SocketInfo s : iface->getSockets()) {
1707 if (FD_ISSET(s.sockfd_, &sockets)) {
1708 receiveDHCP4Packet(*iface, s);
1710 if (dhcp_receiver_->shouldTerminate()) {
1721IfaceMgr::receiveDHCP6Packets() {
1728 addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::TERMINATE), maxfd, &sockets);
1732 for (SocketInfo s : iface->getSockets()) {
1734 if (s.addr_.isV6()) {
1743 if (dhcp_receiver_->shouldTerminate()) {
1754 int result = select(maxfd + 1, &rd_set, 0, 0, 0);
1757 if (dhcp_receiver_->shouldTerminate()) {
1764 }
else if (result < 0) {
1766 if (errno != EINTR) {
1768 dhcp_receiver_->setError(strerror(errno));
1779 for (SocketInfo s : iface->getSockets()) {
1780 if (FD_ISSET(s.sockfd_, &sockets)) {
1781 receiveDHCP6Packet(s);
1783 if (dhcp_receiver_->shouldTerminate()) {
1793IfaceMgr::receiveDHCP4Packet(Iface& iface,
const SocketInfo& socket_info) {
1796 int result = ioctl(socket_info.sockfd_, FIONREAD, &len);
1799 dhcp_receiver_->setError(strerror(errno));
1810 pkt = packet_filter_->receive(iface, socket_info);
1811 }
catch (
const std::exception& ex) {
1812 dhcp_receiver_->setError(strerror(errno));
1814 dhcp_receiver_->setError(
"packet filter receive() failed");
1819 dhcp_receiver_->markReady(WatchedThread::READY);
1824IfaceMgr::receiveDHCP6Packet(
const SocketInfo& socket_info) {
1827 int result = ioctl(socket_info.sockfd_, FIONREAD, &len);
1830 dhcp_receiver_->setError(strerror(errno));
1841 pkt = packet_filter6_->receive(socket_info);
1842 }
catch (
const std::exception& ex) {
1843 dhcp_receiver_->setError(ex.what());
1845 dhcp_receiver_->setError(
"packet filter receive() failed");
1850 dhcp_receiver_->markReady(WatchedThread::READY);
1864 Iface::SocketCollection::const_iterator candidate = socket_collection.end();
1866 Iface::SocketCollection::const_iterator s;
1867 for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
1872 if (s->family_ != AF_INET6) {
1877 if (s->addr_.isV6Multicast()) {
1881 if (s->addr_ == pkt->getLocalAddr()) {
1884 return (s->sockfd_);
1888 if (candidate == socket_collection.end()) {
1894 if ( (pkt->getRemoteAddr().isV6LinkLocal() &&
1895 s->addr_.isV6LinkLocal()) ||
1896 (!pkt->getRemoteAddr().isV6LinkLocal() &&
1897 !s->addr_.isV6LinkLocal()) ) {
1903 if (candidate != socket_collection.end()) {
1904 return (candidate->sockfd_);
1908 <<
" does not have any suitable IPv6 sockets open.");
1922 Iface::SocketCollection::const_iterator candidate = socket_collection.end();
1923 Iface::SocketCollection::const_iterator s;
1924 for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
1925 if (s->family_ == AF_INET) {
1926 if (s->addr_ == pkt->getLocalAddr()) {
1930 if (candidate == socket_collection.end()) {
1936 if (candidate == socket_collection.end()) {
1938 <<
" does not have any suitable IPv4 sockets open.");
1941 return (*candidate);
1948 " while DHCP receiver thread is running");
1951 bool enable_queue =
false;
1952 if (queue_control) {
1963 if (family == AF_INET) {
1964 packet_queue_mgr4_->createPacketQueue(queue_control);
1966 packet_queue_mgr6_->createPacketQueue(queue_control);
1970 if (family == AF_INET) {
1971 packet_queue_mgr4_->destroyPacketQueue();
1973 packet_queue_mgr6_->destroyPacketQueue();
1977 return(enable_queue);
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.
void clear()
Clear the collection.
void push_back(const IfacePtr &iface)
Adds an interface to the collection.
IfacePtr getIface(uint32_t ifindex)
Lookup by interface index.
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.
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 openSockets6(const uint16_t port=DHCP6_SERVER_PORT, IfaceMgrErrorMsgCallback error_handler=0)
Opens IPv6 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.
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.
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.
IfaceCollection ifaces_
List of available interfaces.
void startDHCPReceiver(const uint16_t family)
Starts DHCP packet receiver.
void clearUnicasts()
Clears unicast addresses on all interfaces.
void detectIfaces()
Detects network interfaces.
bool openSockets4(const uint16_t port=DHCP4_SERVER_PORT, const bool use_bcast=true, IfaceMgrErrorMsgCallback error_handler=0)
Opens IPv4 sockets on detected interfaces.
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.
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.
IfacePtr getIface(int ifindex)
Returns interface specified interface index.
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).
AddressCollection addrs_
List of assigned addresses.
std::string getFullName() const
Returns full interface name as "ifname/ifindex" string.
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.
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.
void addSocket(const SocketInfo &sock)
Adds socket descriptor to an interface.
int ifindex_
Interface index (a value that uniquely identifies 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, 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.
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.