Commit 3c941835 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[991] Moved IfaceMgr::send to OS specific files.

parent 7e9c676a
......@@ -124,7 +124,8 @@ bool IfaceMgr::Iface::delSocket(uint16_t sockfd) {
IfaceMgr::IfaceMgr()
:control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
control_buf_(new char[control_buf_len_]),
session_socket_(INVALID_SOCKET), session_callback_(NULL)
session_socket_(INVALID_SOCKET), session_callback_(NULL),
socket_handler_(new SocketHandler())
{
try {
......@@ -511,64 +512,6 @@ IfaceMgr::getLocalAddress(const IOAddress& remote_addr, const uint16_t port) {
return IOAddress(local_address);
}
int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port,
bool receive_bcast, bool send_bcast) {
struct sockaddr_in addr4;
memset(&addr4, 0, sizeof(sockaddr));
addr4.sin_family = AF_INET;
addr4.sin_port = htons(port);
// If we are to receive broadcast messages we have to bind
// to "ANY" address.
addr4.sin_addr.s_addr = receive_bcast ? INADDR_ANY : htonl(addr);
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
}
if (receive_bcast) {
// Bind to device so as we receive traffic on a specific interface.
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.getName().c_str(),
iface.getName().length() + 1) < 0) {
close(sock);
isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
<< "on socket " << sock);
}
}
if (send_bcast) {
// Enable sending to broadcast address.
int flag = 1;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag)) < 0) {
close(sock);
isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
<< "on socket " << sock);
}
}
if (bind(sock, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {
close(sock);
isc_throw(SocketConfigError, "Failed to bind socket " << sock << " to " << addr.toText()
<< "/port=" << port);
}
// if there is no support for IP_PKTINFO, we are really out of luck
// it will be difficult to undersand, where this packet came from
#if defined(IP_PKTINFO)
int flag = 1;
if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)) != 0) {
close(sock);
isc_throw(SocketConfigError, "setsockopt: IP_PKTINFO: failed.");
}
#endif
SocketInfo info(sock, addr, port);
iface.addSocket(info);
return (sock);
}
int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
......@@ -588,7 +531,7 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
// TODO: use sockcreator once it becomes available
// make a socket
int sock = socket(AF_INET6, SOCK_DGRAM, 0);
int sock = socket_handler_->openSocket(AF_INET6, SOCK_DGRAM, 0);
if (sock < 0) {
isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
}
......
......@@ -38,6 +38,13 @@ public:
isc::Exception(file, line, what) { };
};
/// @brief IfaceMgr exception thrown when invalid socket handler supplied.
class InvalidSocketHandler : public Exception {
public:
InvalidSocketHandler(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) { };
};
/// @brief IfaceMgr exception thrown thrown when socket opening
/// or configuration failed.
class SocketConfigError : public Exception {
......@@ -62,6 +69,13 @@ public:
isc::Exception(file, line, what) { };
};
class SocketHandler {
public:
virtual int openSocket(int socket_family, int socket_type, int protocol) {
return socket(socket_family, socket_type, protocol);
}
};
/// @brief handles network interfaces, transmission and reception
///
/// IfaceMgr is an interface manager class that detects available network
......@@ -544,6 +558,13 @@ public:
session_callback_ = callback;
}
void setSocketHandler(const boost::shared_ptr<SocketHandler>& handler) {
if (!handler) {
isc_throw(InvalidSocketHandler, "NULL socket handler spcified");
}
socket_handler_ = handler;
}
/// A value of socket descriptor representing "not specified" state.
static const int INVALID_SOCKET = -1;
......@@ -691,6 +712,8 @@ private:
isc::asiolink::IOAddress
getLocalAddress(const isc::asiolink::IOAddress& remote_addr,
const uint16_t port);
boost::shared_ptr<SocketHandler> socket_handler_;
};
}; // namespace isc::dhcp
......
......@@ -39,6 +39,65 @@ IfaceMgr::isDirectResponseSupported() {
return (false);
}
int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port,
bool receive_bcast, bool send_bcast) {
struct sockaddr_in addr4;
memset(&addr4, 0, sizeof(sockaddr));
addr4.sin_family = AF_INET;
addr4.sin_port = htons(port);
// If we are to receive broadcast messages we have to bind
// to "ANY" address.
addr4.sin_addr.s_addr = receive_bcast ? INADDR_ANY : htonl(addr);
int sock = socket_handler_->openSocket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
}
if (receive_bcast) {
// Bind to device so as we receive traffic on a specific interface.
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.getName().c_str(),
iface.getName().length() + 1) < 0) {
close(sock);
isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
<< "on socket " << sock);
}
}
if (send_bcast) {
// Enable sending to broadcast address.
int flag = 1;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag)) < 0) {
close(sock);
isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
<< "on socket " << sock);
}
}
if (bind(sock, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {
close(sock);
isc_throw(SocketConfigError, "Failed to bind socket " << sock << " to " << addr.toText()
<< "/port=" << port);
}
// if there is no support for IP_PKTINFO, we are really out of luck
// it will be difficult to undersand, where this packet came from
#if defined(IP_PKTINFO)
int flag = 1;
if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)) != 0) {
close(sock);
isc_throw(SocketConfigError, "setsockopt: IP_PKTINFO: failed.");
}
#endif
SocketInfo info(sock, addr, port);
iface.addSocket(info);
return (sock);
}
bool
IfaceMgr::send(const Pkt4Ptr& pkt)
{
......
......@@ -499,6 +499,65 @@ IfaceMgr::isDirectResponseSupported() {
return (false);
}
int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port,
bool receive_bcast, bool send_bcast) {
struct sockaddr_in addr4;
memset(&addr4, 0, sizeof(sockaddr));
addr4.sin_family = AF_INET;
addr4.sin_port = htons(port);
// If we are to receive broadcast messages we have to bind
// to "ANY" address.
addr4.sin_addr.s_addr = receive_bcast ? INADDR_ANY : htonl(addr);
int sock = socket_handler_->openSocket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
}
if (receive_bcast) {
// Bind to device so as we receive traffic on a specific interface.
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.getName().c_str(),
iface.getName().length() + 1) < 0) {
close(sock);
isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
<< "on socket " << sock);
}
}
if (send_bcast) {
// Enable sending to broadcast address.
int flag = 1;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag)) < 0) {
close(sock);
isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
<< "on socket " << sock);
}
}
if (bind(sock, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {
close(sock);
isc_throw(SocketConfigError, "Failed to bind socket " << sock << " to " << addr.toText()
<< "/port=" << port);
}
// if there is no support for IP_PKTINFO, we are really out of luck
// it will be difficult to undersand, where this packet came from
#if defined(IP_PKTINFO)
int flag = 1;
if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)) != 0) {
close(sock);
isc_throw(SocketConfigError, "setsockopt: IP_PKTINFO: failed.");
}
#endif
SocketInfo info(sock, addr, port);
iface.addSocket(info);
return (sock);
}
/// @brief sets flag_*_ fields.
///
/// This implementation is OS-specific as bits have different meaning
......
......@@ -39,6 +39,65 @@ IfaceMgr::isDirectResposeSupported() {
return (false);
}
int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port,
bool receive_bcast, bool send_bcast) {
struct sockaddr_in addr4;
memset(&addr4, 0, sizeof(sockaddr));
addr4.sin_family = AF_INET;
addr4.sin_port = htons(port);
// If we are to receive broadcast messages we have to bind
// to "ANY" address.
addr4.sin_addr.s_addr = receive_bcast ? INADDR_ANY : htonl(addr);
int sock = socket_handler_->openSocket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
}
if (receive_bcast) {
// Bind to device so as we receive traffic on a specific interface.
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.getName().c_str(),
iface.getName().length() + 1) < 0) {
close(sock);
isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
<< "on socket " << sock);
}
}
if (send_bcast) {
// Enable sending to broadcast address.
int flag = 1;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag)) < 0) {
close(sock);
isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
<< "on socket " << sock);
}
}
if (bind(sock, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {
close(sock);
isc_throw(SocketConfigError, "Failed to bind socket " << sock << " to " << addr.toText()
<< "/port=" << port);
}
// if there is no support for IP_PKTINFO, we are really out of luck
// it will be difficult to undersand, where this packet came from
#if defined(IP_PKTINFO)
int flag = 1;
if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)) != 0) {
close(sock);
isc_throw(SocketConfigError, "setsockopt: IP_PKTINFO: failed.");
}
#endif
SocketInfo info(sock, addr, port);
iface.addSocket(info);
return (sock);
}
bool
IfaceMgr::send(const Pkt4Ptr& pkt)
{
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment