Browse Source

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

Marcin Siodelski 12 years ago
parent
commit
3c941835b8

+ 3 - 60
src/lib/dhcp/iface_mgr.cc

@@ -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.");
     }

+ 23 - 0
src/lib/dhcp/iface_mgr.h

@@ -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

+ 59 - 0
src/lib/dhcp/iface_mgr_bsd.cc

@@ -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)
 {

+ 59 - 0
src/lib/dhcp/iface_mgr_linux.cc

@@ -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

+ 59 - 0
src/lib/dhcp/iface_mgr_sun.cc

@@ -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)
 {