Commit d9b1da77 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[991] Moved Iface class out of IfaceMgr.

parent f5a9aeba
......@@ -287,9 +287,9 @@ Dhcpv4Srv::generateServerID() {
continue;
}
const IfaceMgr::AddressCollection addrs = iface->getAddresses();
const Iface::AddressCollection addrs = iface->getAddresses();
for (IfaceMgr::AddressCollection::const_iterator addr = addrs.begin();
for (Iface::AddressCollection::const_iterator addr = addrs.begin();
addr != addrs.end(); ++addr) {
if (addr->getFamily() != AF_INET) {
continue;
......
......@@ -48,7 +48,7 @@ IfaceMgr::instance() {
return (iface_mgr);
}
IfaceMgr::Iface::Iface(const std::string& name, int ifindex)
Iface::Iface(const std::string& name, int ifindex)
:name_(name), ifindex_(ifindex), mac_len_(0), hardware_type_(0),
flag_loopback_(false), flag_up_(false), flag_running_(false),
flag_multicast_(false), flag_broadcast_(false), flags_(0)
......@@ -57,7 +57,7 @@ IfaceMgr::Iface::Iface(const std::string& name, int ifindex)
}
void
IfaceMgr::Iface::closeSockets() {
Iface::closeSockets() {
for (SocketCollection::iterator sock = sockets_.begin();
sock != sockets_.end(); ++sock) {
close(sock->sockfd_);
......@@ -66,14 +66,14 @@ IfaceMgr::Iface::closeSockets() {
}
std::string
IfaceMgr::Iface::getFullName() const {
Iface::getFullName() const {
ostringstream tmp;
tmp << name_ << "/" << ifindex_;
return (tmp.str());
}
std::string
IfaceMgr::Iface::getPlainMac() const {
Iface::getPlainMac() const {
ostringstream tmp;
tmp.fill('0');
tmp << hex;
......@@ -87,18 +87,18 @@ IfaceMgr::Iface::getPlainMac() const {
return (tmp.str());
}
void IfaceMgr::Iface::setMac(const uint8_t* mac, size_t len) {
if (len > IfaceMgr::MAX_MAC_LEN) {
void Iface::setMac(const uint8_t* mac, size_t len) {
if (len > MAX_MAC_LEN) {
isc_throw(OutOfRange, "Interface " << getFullName()
<< " was detected to have link address of length "
<< len << ", but maximum supported length is "
<< IfaceMgr::MAX_MAC_LEN);
<< MAX_MAC_LEN);
}
mac_len_ = len;
memcpy(mac_, mac, len);
}
bool IfaceMgr::Iface::delAddress(const isc::asiolink::IOAddress& addr) {
bool Iface::delAddress(const isc::asiolink::IOAddress& addr) {
for (AddressCollection::iterator a = addrs_.begin();
a!=addrs_.end(); ++a) {
if (*a==addr) {
......@@ -109,7 +109,7 @@ bool IfaceMgr::Iface::delAddress(const isc::asiolink::IOAddress& addr) {
return (false);
}
bool IfaceMgr::Iface::delSocket(uint16_t sockfd) {
bool Iface::delSocket(uint16_t sockfd) {
list<SocketInfo>::iterator sock = sockets_.begin();
while (sock!=sockets_.end()) {
if (sock->sockfd_ == sockfd) {
......@@ -209,8 +209,8 @@ bool IfaceMgr::openSockets4(const uint16_t port) {
continue;
}
AddressCollection addrs = iface->getAddresses();
for (AddressCollection::iterator addr = addrs.begin();
Iface::AddressCollection addrs = iface->getAddresses();
for (Iface::AddressCollection::iterator addr = addrs.begin();
addr != addrs.end();
++addr) {
......@@ -246,8 +246,8 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
continue;
}
AddressCollection addrs = iface->getAddresses();
for (AddressCollection::iterator addr = addrs.begin();
Iface::AddressCollection addrs = iface->getAddresses();
for (Iface::AddressCollection::iterator addr = addrs.begin();
addr != addrs.end();
++addr) {
......@@ -308,7 +308,7 @@ IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
iface!=ifaces_.end();
++iface) {
const AddressCollection& addrs = iface->getAddresses();
const Iface::AddressCollection& addrs = iface->getAddresses();
out << "Detected interface " << iface->getFullName()
<< ", hwtype=" << iface->getHWType()
......@@ -322,7 +322,7 @@ IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
<< ")" << endl;
out << " " << addrs.size() << " addr(s):";
for (AddressCollection::const_iterator addr = addrs.begin();
for (Iface::AddressCollection::const_iterator addr = addrs.begin();
addr != addrs.end(); ++addr) {
out << " " << addr->toText();
}
......@@ -330,7 +330,7 @@ IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
}
}
IfaceMgr::Iface*
Iface*
IfaceMgr::getIface(int ifindex) {
for (IfaceCollection::iterator iface=ifaces_.begin();
iface!=ifaces_.end();
......@@ -342,7 +342,7 @@ IfaceMgr::getIface(int ifindex) {
return (NULL); // not found
}
IfaceMgr::Iface*
Iface*
IfaceMgr::getIface(const std::string& ifname) {
for (IfaceCollection::iterator iface=ifaces_.begin();
iface!=ifaces_.end();
......@@ -387,8 +387,8 @@ int IfaceMgr::openSocketFromIface(const std::string& ifname,
// Interface is now detected. Search for address on interface
// that matches address family (v6 or v4).
AddressCollection addrs = iface->getAddresses();
AddressCollection::iterator addr_it = addrs.begin();
Iface::AddressCollection addrs = iface->getAddresses();
Iface::AddressCollection::iterator addr_it = addrs.begin();
while (addr_it != addrs.end()) {
if (addr_it->getFamily() == family) {
// We have interface and address so let's open socket.
......@@ -424,9 +424,9 @@ int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
iface != ifaces_.end();
++iface) {
AddressCollection addrs = iface->getAddresses();
Iface::AddressCollection addrs = iface->getAddresses();
for (AddressCollection::iterator addr_it = addrs.begin();
for (Iface::AddressCollection::iterator addr_it = addrs.begin();
addr_it != addrs.end();
++addr_it) {
......@@ -581,7 +581,7 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
}
}
SocketInfo info(sock, addr, port);
Iface::SocketInfo info(sock, addr, port);
iface.addSocket(info);
return (sock);
......@@ -696,7 +696,7 @@ IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
isc_throw(BadValue, "fractional timeout must be shorter than"
" one million microseconds");
}
const SocketInfo* candidate = 0;
const Iface::SocketInfo* candidate = 0;
IfaceCollection::const_iterator iface;
fd_set sockets;
int maxfd = 0;
......@@ -709,8 +709,8 @@ IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
/// provided set to indicated which sockets have something to read.
for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
const SocketCollection& socket_collection = iface->getSockets();
for (SocketCollection::const_iterator s = socket_collection.begin();
const Iface::SocketCollection& socket_collection = iface->getSockets();
for (Iface::SocketCollection::const_iterator s = socket_collection.begin();
s != socket_collection.end(); ++s) {
// Only deal with IPv4 addresses.
......@@ -765,8 +765,8 @@ IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
// Let's find out which interface/socket has the data
for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
const SocketCollection& socket_collection = iface->getSockets();
for (SocketCollection::const_iterator s = socket_collection.begin();
const Iface::SocketCollection& socket_collection = iface->getSockets();
for (Iface::SocketCollection::const_iterator s = socket_collection.begin();
s != socket_collection.end(); ++s) {
if (FD_ISSET(s->sockfd_, &sockets)) {
candidate = &(*s);
......@@ -850,7 +850,7 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
" one million microseconds");
}
const SocketInfo* candidate = 0;
const Iface::SocketInfo* candidate = 0;
fd_set sockets;
int maxfd = 0;
stringstream names;
......@@ -862,8 +862,8 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
/// provided set to indicated which sockets have something to read.
IfaceCollection::const_iterator iface;
for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
const SocketCollection& socket_collection = iface->getSockets();
for (SocketCollection::const_iterator s = socket_collection.begin();
const Iface::SocketCollection& socket_collection = iface->getSockets();
for (Iface::SocketCollection::const_iterator s = socket_collection.begin();
s != socket_collection.end(); ++s) {
// Only deal with IPv6 addresses.
......@@ -918,8 +918,8 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
// Let's find out which interface/socket has the data
for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
const SocketCollection& socket_collection = iface->getSockets();
for (SocketCollection::const_iterator s = socket_collection.begin();
const Iface::SocketCollection& socket_collection = iface->getSockets();
for (Iface::SocketCollection::const_iterator s = socket_collection.begin();
s != socket_collection.end(); ++s) {
if (FD_ISSET(s->sockfd_, &sockets)) {
candidate = &(*s);
......@@ -1039,8 +1039,8 @@ uint16_t IfaceMgr::getSocket(const isc::dhcp::Pkt6& pkt) {
<< pkt.getIface());
}
const SocketCollection& socket_collection = iface->getSockets();
SocketCollection::const_iterator s;
const Iface::SocketCollection& socket_collection = iface->getSockets();
Iface::SocketCollection::const_iterator s;
for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
if ((s->family_ == AF_INET6) &&
(!s->addr_.getAddress().to_v6().is_multicast())) {
......@@ -1062,8 +1062,8 @@ uint16_t IfaceMgr::getSocket(isc::dhcp::Pkt4 const& pkt) {
<< pkt.getIface());
}
const SocketCollection& socket_collection = iface->getSockets();
SocketCollection::const_iterator s;
const Iface::SocketCollection& socket_collection = iface->getSockets();
Iface::SocketCollection::const_iterator s;
for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
if (s->family_ == AF_INET) {
return (s->sockfd_);
......
......@@ -70,31 +70,19 @@ public:
isc::Exception(file, line, what) { };
};
/// @brief handles network interfaces, transmission and reception
/// @brief represents a single network interface
///
/// IfaceMgr is an interface manager class that detects available network
/// interfaces, configured addresses, link-local addresses, and provides
/// API for using sockets.
///
class IfaceMgr : public boost::noncopyable {
/// Iface structure represents network interface with all useful
/// information, like name, interface index, MAC address and
/// list of assigned addresses
class Iface {
public:
/// type that defines list of addresses
typedef std::vector<isc::asiolink::IOAddress> AddressCollection;
/// defines callback used when commands are received over control session
typedef void (*SessionCallback) (void);
/// maximum MAC address length (Infiniband uses 20 bytes)
static const unsigned int MAX_MAC_LEN = 20;
/// @brief Packet reception buffer size
///
/// RFC3315 states that server responses may be
/// fragmented if they are over MTU. There is no
/// text whether client's packets may be larger
/// than 1500. For now, we can assume that
/// we don't support packets larger than 1500.
static const uint32_t RCVBUFSIZE = 1500;
/// type that defines list of addresses
typedef std::vector<isc::asiolink::IOAddress> AddressCollection;
/// Holds information about socket.
struct SocketInfo {
......@@ -117,189 +105,202 @@ public:
/// @todo: Add SocketCollectionConstIter type
typedef std::list<SocketInfo> SocketCollection;
/// @brief Iface constructor.
///
/// Creates Iface object that represents network interface.
///
/// @param name name of the interface
/// @param ifindex interface index (unique integer identifier)
Iface(const std::string& name, int ifindex);
/// @brief Closes all open sockets on interface.
void closeSockets();
/// @brief represents a single network interface
/// @brief Returns full interface name as "ifname/ifindex" string.
///
/// Iface structure represents network interface with all useful
/// information, like name, interface index, MAC address and
/// list of assigned addresses
class Iface {
public:
/// @brief Iface constructor.
///
/// Creates Iface object that represents network interface.
///
/// @param name name of the interface
/// @param ifindex interface index (unique integer identifier)
Iface(const std::string& name, int ifindex);
/// @return string with interface name
std::string getFullName() const;
/// @brief Closes all open sockets on interface.
void closeSockets();
/// @brief Returns link-layer address a plain text.
///
/// @return MAC address as a plain text (string)
std::string getPlainMac() const;
/// @brief Returns full interface name as "ifname/ifindex" string.
///
/// @return string with interface name
std::string getFullName() const;
/// @brief Sets MAC address of the interface.
///
/// @param mac pointer to MAC address buffer
/// @param macLen length of mac address
void setMac(const uint8_t* mac, size_t macLen);
/// @brief Returns link-layer address a plain text.
///
/// @return MAC address as a plain text (string)
std::string getPlainMac() const;
/// @brief Returns MAC length.
///
/// @return length of MAC address
size_t getMacLen() const { return mac_len_; }
/// @brief Sets MAC address of the interface.
///
/// @param mac pointer to MAC address buffer
/// @param macLen length of mac address
void setMac(const uint8_t* mac, size_t macLen);
/// @brief Returns pointer to MAC address.
///
/// Note: Returned pointer is only valid as long as the interface object
/// that returned it.
const uint8_t* getMac() const { return mac_; }
/// @brief Returns MAC length.
///
/// @return length of MAC address
size_t getMacLen() const { return mac_len_; }
/// @brief Sets flag_*_ fields based on bitmask value returned by OS
///
/// Note: Implementation of this method is OS-dependent as bits have
/// different meaning on each OS.
///
/// @param flags bitmask value returned by OS in interface detection
void setFlags(uint32_t flags);
/// @brief Returns pointer to MAC address.
///
/// Note: Returned pointer is only valid as long as the interface object
/// that returned it.
const uint8_t* getMac() const { return mac_; }
/// @brief Returns interface index.
///
/// @return interface index
uint16_t getIndex() const { return ifindex_; }
/// @brief Sets flag_*_ fields based on bitmask value returned by OS
///
/// Note: Implementation of this method is OS-dependent as bits have
/// different meaning on each OS.
///
/// @param flags bitmask value returned by OS in interface detection
void setFlags(uint32_t flags);
/// @brief Returns interface name.
///
/// @return interface name
std::string getName() const { return name_; };
/// @brief Returns interface index.
///
/// @return interface index
uint16_t getIndex() const { return ifindex_; }
/// @brief Sets up hardware type of the interface.
///
/// @param type hardware type
void setHWType(uint16_t type ) { hardware_type_ = type; }
/// @brief Returns interface name.
///
/// @return interface name
std::string getName() const { return name_; };
/// @brief Returns hardware type of the interface.
///
/// @return hardware type
uint16_t getHWType() const { return hardware_type_; }
/// @brief Sets up hardware type of the interface.
///
/// @param type hardware type
void setHWType(uint16_t type ) { hardware_type_ = type; }
/// @brief Returns all interfaces available on an interface.
///
/// Care should be taken to not use this collection after Iface object
/// ceases to exist. That is easy in most cases as Iface objects are
/// created by IfaceMgr that is a singleton an is expected to be
/// available at all time. We may revisit this if we ever decide to
/// implement dynamic interface detection, but such fancy feature would
/// mostly be useful for clients with wifi/vpn/virtual interfaces.
///
/// @return collection of addresses
const AddressCollection& getAddresses() const { return addrs_; }
/// @brief Returns hardware type of the interface.
///
/// @return hardware type
uint16_t getHWType() const { return hardware_type_; }
/// @brief Adds an address to an interface.
///
/// This only adds an address to collection, it does not physically
/// configure address on actual network interface.
///
/// @param addr address to be added
void addAddress(const isc::asiolink::IOAddress& addr) {
addrs_.push_back(addr);
}
/// @brief Returns all interfaces available on an interface.
///
/// Care should be taken to not use this collection after Iface object
/// ceases to exist. That is easy in most cases as Iface objects are
/// created by IfaceMgr that is a singleton an is expected to be
/// available at all time. We may revisit this if we ever decide to
/// implement dynamic interface detection, but such fancy feature would
/// mostly be useful for clients with wifi/vpn/virtual interfaces.
///
/// @return collection of addresses
const AddressCollection& getAddresses() const { return addrs_; }
/// @brief Deletes an address from an interface.
///
/// This only deletes address from collection, it does not physically
/// remove address configuration from actual network interface.
///
/// @param addr address to be removed.
///
/// @return true if removal was successful (address was in collection),
/// false otherwise
bool delAddress(const isc::asiolink::IOAddress& addr);
/// @brief Adds an address to an interface.
///
/// This only adds an address to collection, it does not physically
/// configure address on actual network interface.
///
/// @param addr address to be added
void addAddress(const isc::asiolink::IOAddress& addr) {
addrs_.push_back(addr);
}
/// @brief Adds socket descriptor to an interface.
///
/// @param sock SocketInfo structure that describes socket.
void addSocket(const SocketInfo& sock) {
sockets_.push_back(sock);
}
/// @brief Deletes an address from an interface.
///
/// This only deletes address from collection, it does not physically
/// remove address configuration from actual network interface.
///
/// @param addr address to be removed.
///
/// @return true if removal was successful (address was in collection),
/// false otherwise
bool delAddress(const isc::asiolink::IOAddress& addr);
/// @brief Closes socket.
///
/// Closes socket and removes corresponding SocketInfo structure
/// from an interface.
///
/// @param sockfd socket descriptor to be closed/removed.
/// @return true if there was such socket, false otherwise
bool delSocket(uint16_t sockfd);
/// @brief Adds socket descriptor to an interface.
///
/// @param sock SocketInfo structure that describes socket.
void addSocket(const SocketInfo& sock)
{ sockets_.push_back(sock); }
/// @brief Returns collection of all sockets added to interface.
///
/// When new socket is created with @ref IfaceMgr::openSocket
/// it is added to sockets collection on particular interface.
/// If socket is opened by other means (e.g. function that does
/// not use @ref IfaceMgr::openSocket) it will not be available
/// in this collection. Note that functions like
/// @ref IfaceMgr::openSocketFromIface use
/// @ref IfaceMgr::openSocket internally.
/// The returned reference is only valid during the lifetime of
/// the IfaceMgr object that returned it.
///
/// @return collection of sockets added to interface
const SocketCollection& getSockets() const { return sockets_; }
/// @brief Closes socket.
///
/// Closes socket and removes corresponding SocketInfo structure
/// from an interface.
///
/// @param sockfd socket descriptor to be closed/removed.
/// @return true if there was such socket, false otherwise
bool delSocket(uint16_t sockfd);
protected:
/// socket used to sending data
SocketCollection sockets_;
/// @brief Returns collection of all sockets added to interface.
///
/// When new socket is created with @ref IfaceMgr::openSocket
/// it is added to sockets collection on particular interface.
/// If socket is opened by other means (e.g. function that does
/// not use @ref IfaceMgr::openSocket) it will not be available
/// in this collection. Note that functions like
/// @ref IfaceMgr::openSocketFromIface use
/// @ref IfaceMgr::openSocket internally.
/// The returned reference is only valid during the lifetime of
/// the IfaceMgr object that returned it.
///
/// @return collection of sockets added to interface
const SocketCollection& getSockets() const { return sockets_; }
/// network interface name
std::string name_;
protected:
/// socket used to sending data
SocketCollection sockets_;
/// interface index (a value that uniquely indentifies an interface)
int ifindex_;
/// network interface name
std::string name_;
/// list of assigned addresses
AddressCollection addrs_;
/// interface index (a value that uniquely indentifies an interface)
int ifindex_;
/// link-layer address
uint8_t mac_[MAX_MAC_LEN];
/// list of assigned addresses
AddressCollection addrs_;
/// length of link-layer address (usually 6)
size_t mac_len_;
/// link-layer address
uint8_t mac_[MAX_MAC_LEN];
/// hardware type
uint16_t hardware_type_;
/// length of link-layer address (usually 6)
size_t mac_len_;
public:
/// @todo: Make those fields protected once we start supporting more
/// than just Linux
/// hardware type
uint16_t hardware_type_;
/// specifies if selected interface is loopback
bool flag_loopback_;
public:
/// @todo: Make those fields protected once we start supporting more
/// than just Linux
/// specifies if selected interface is up
bool flag_up_;
/// specifies if selected interface is loopback
bool flag_loopback_;
/// flag specifies if selected interface is running
/// (e.g. cable plugged in, wifi associated)
bool flag_running_;
/// specifies if selected interface is up
bool flag_up_;
/// flag specifies if selected interface is multicast capable
bool flag_multicast_;
/// flag specifies if selected interface is running
/// (e.g. cable plugged in, wifi associated)
bool flag_running_;
/// flag specifies if selected interface is broadcast capable
bool flag_broadcast_;
/// flag specifies if selected interface is multicast capable
bool flag_multicast_;
/// interface flags (this value is as is returned by OS,
/// it may mean different things on different OSes)
uint32_t flags_;
};
/// flag specifies if selected interface is broadcast capable
bool flag_broadcast_;
/// @brief handles network interfaces, transmission and reception
///
/// IfaceMgr is an interface manager class that detects available network
/// interfaces, configured addresses, link-local addresses, and provides
/// API for using sockets.
///
class IfaceMgr : public boost::noncopyable {
public:
/// defines callback used when commands are received over control session
typedef void (*SessionCallback) (void);
/// interface flags (this value is as is returned by OS,
/// it may mean different things on different OSes)
uint32_t flags_;