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;
 
   71        isc_throw(BadValue, 
"Interface name must not be empty");
 
 
   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 (
unsigned 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.");
 
 
  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;
 
  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_);
 
  880    return (
ifaces_.getIface(ifindex));
 
 
  885    if (ifname.empty()) {
 
  888    return (
ifaces_.getIface(ifname));
 
 
  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>
 
 1032    if (!remote_endpoint) {
 
 1037    boost::asio::io_context 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);
 
 1073        isc_throw(Unexpected, 
"failed to connect to remote endpoint.");
 
 1077    boost::asio::ip::udp::socket::endpoint_type local_endpoint =
 
 1078        sock.local_endpoint();
 
 1079    boost::asio::ip::address local_address(local_endpoint.address());
 
 1085    return IOAddress(local_address);
 
 1090                      const bool receive_bcast, 
const bool send_bcast) {
 
 1093                                                 receive_bcast, send_bcast);
 
 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)) {
 
 
 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)) {
 
 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)) {
 
 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)) {
 
 
 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.
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.
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.
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 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.
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.