Browse Source

[3251] Add control whether socket is to join multicast group.

Marcin Siodelski 11 years ago
parent
commit
33003d2af6

+ 7 - 5
src/lib/dhcp/iface_mgr.cc

@@ -596,7 +596,7 @@ int IfaceMgr::openSocket(const std::string& ifname, const IOAddress& addr,
         return openSocket4(*iface, addr, port, receive_bcast, send_bcast);
 
     } else if (addr.isV6()) {
-        return openSocket6(*iface, addr, port);
+        return openSocket6(*iface, addr, port, receive_bcast);
 
     } else {
         isc_throw(BadValue, "Failed to detect family of address: "
@@ -625,7 +625,7 @@ int IfaceMgr::openSocketFromIface(const std::string& ifname,
             if (addr_it->getFamily() == family) {
                 // We have interface and address so let's open socket.
                 // This may cause isc::Unexpected exception.
-                return (openSocket(iface->getName(), *addr_it, port));
+                return (openSocket(iface->getName(), *addr_it, port, false));
             }
             ++addr_it;
         }
@@ -669,7 +669,7 @@ int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
             if (*addr_it == addr) {
                 // Open socket using local interface, address and port.
                 // This may cause isc::Unexpected exception.
-                return (openSocket(iface->getName(), *addr_it, port));
+                return (openSocket(iface->getName(), *addr_it, port, false));
             }
         }
     }
@@ -749,9 +749,11 @@ IfaceMgr::getLocalAddress(const IOAddress& remote_addr, const uint16_t port) {
 
 
 int
-IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
+IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port,
+                      const bool join_multicast) {
     // Assuming that packet filter is not NULL, because its modifier checks it.
-    SocketInfo info = packet_filter6_->openSocket(iface, addr, port);
+    SocketInfo info = packet_filter6_->openSocket(iface, addr, port,
+                                                  join_multicast);
     iface.addSocket(info);
 
     return (info.sockfd_);

+ 19 - 9
src/lib/dhcp/iface_mgr.h

@@ -552,8 +552,8 @@ public:
     /// @param ifname name of the interface
     /// @param addr address to be bound.
     /// @param port UDP port.
-    /// @param receive_bcast configure IPv4 socket to receive broadcast messages.
-    /// This parameter is ignored for IPv6 sockets.
+    /// @param receive_bcast configure IPv4 socket to receive broadcast
+    /// messages or IPv6 socket to join multicast group.
     /// @param send_bcast configure IPv4 socket to send broadcast messages.
     /// This parameter is ignored for IPv6 sockets.
     ///
@@ -575,11 +575,13 @@ public:
     /// Instead, the method searches through the addresses on the specified
     /// interface and selects one that matches the address family.
     ///
+    /// @note This method does not join the socket to the multicast group.
+    ///
     /// @param ifname name of the interface
     /// @param port UDP port
     /// @param family address family (AF_INET or AF_INET6)
-    /// @return socket descriptor, if socket creation, binding and multicast
-    /// group join were all successful.
+    /// @return socket descriptor, if socket creation and binding was
+    /// successful.
     /// @throw isc::Unexpected if failed to create and bind socket.
     /// @throw isc::BadValue if there is no address on specified interface
     /// that belongs to given family.
@@ -592,10 +594,12 @@ public:
     /// This methods differs from \ref openSocket in that it does not require
     /// the specification of the interface to which the socket will be bound.
     ///
+    /// @note This method does not join the socket to the multicast group.
+    ///
     /// @param addr address to be bound
     /// @param port UDP port
-    /// @return socket descriptor, if socket creation, binding and multicast
-    /// group join were all successful.
+    /// @return socket descriptor, if socket creation and binding was
+    /// successful.
     /// @throw isc::Unexpected if failed to create and bind socket
     /// @throw isc::BadValue if specified address is not available on
     /// any interface
@@ -609,10 +613,12 @@ public:
     /// identified, \ref openSocket is called to open a socket and bind it to
     /// the interface, address and port.
     ///
+    /// @note This method does not join the socket to a multicast group.
+    ///
     /// @param remote_addr remote address to connect to
     /// @param port UDP port
-    /// @return socket descriptor, if socket creation, binding and multicast
-    /// group join were all successful.
+    /// @return socket descriptor, if socket creation and binding was
+    /// successful.
     /// @throw isc::Unexpected if failed to create and bind socket
     int openSocketFromRemoteAddress(const isc::asiolink::IOAddress& remote_addr,
                                     const uint16_t port);
@@ -853,9 +859,13 @@ protected:
     /// @param iface reference to interface structure.
     /// @param addr an address the created socket should be bound to
     /// @param port a port that created socket should be bound to
+    /// @param join_multicast A boolean parameter which indicates whether
+    /// socket should join All_DHCP_Relay_Agents_and_servers multicast
+    /// group.
     ///
     /// @return socket descriptor
-    int openSocket6(Iface& iface, const isc::asiolink::IOAddress& addr, uint16_t port);
+    int openSocket6(Iface& iface, const isc::asiolink::IOAddress& addr,
+                    uint16_t port, const bool join_multicast);
 
     /// @brief Detects network interfaces.
     ///

+ 5 - 1
src/lib/dhcp/pkt_filter6.h

@@ -79,11 +79,15 @@ public:
     /// @param iface Interface descriptor.
     /// @param addr Address on the interface to be used to send packets.
     /// @param port Port number.
+    /// @param join_multicast A boolean parameter which indicates whether
+    /// socket should join All_DHCP_Relay_Agents_and_servers multicast
+    /// group.
     ///
     /// @return A structure describing a primary and fallback socket.
     virtual SocketInfo openSocket(const Iface& iface,
                                   const isc::asiolink::IOAddress& addr,
-                                  const uint16_t port) = 0;
+                                  const uint16_t port,
+                                  const bool join_multicast) = 0;
 
     /// @brief Receive DHCPv6 message on the interface.
     ///

+ 3 - 2
src/lib/dhcp/pkt_filter_inet6.cc

@@ -32,7 +32,8 @@ PktFilterInet6::PktFilterInet6()
 SocketInfo
 PktFilterInet6::openSocket(const Iface& iface,
                            const isc::asiolink::IOAddress& addr,
-                           const uint16_t port) {
+                           const uint16_t port,
+                           const bool join_multicast) {
     struct sockaddr_in6 addr6;
     memset(&addr6, 0, sizeof(addr6));
     addr6.sin6_family = AF_INET6;
@@ -90,7 +91,7 @@ PktFilterInet6::openSocket(const Iface& iface,
         // are link and site-scoped, so there is no sense to join those groups
         // with global addresses.
 
-        if (!joinMulticast(sock, iface.getName(),
+        if (join_multicast && !joinMulticast(sock, iface.getName(),
                            std::string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS))) {
             close(sock);
             isc_throw(SocketConfigError, "Failed to join " << ALL_DHCP_RELAY_AGENTS_AND_SERVERS

+ 5 - 1
src/lib/dhcp/pkt_filter_inet6.h

@@ -42,13 +42,17 @@ public:
     /// @param iface Interface descriptor.
     /// @param addr Address on the interface to be used to send packets.
     /// @param port Port number.
+    /// @param join_multicast A boolean parameter which indicates whether
+    /// socket should join All_DHCP_Relay_Agents_and_servers multicast
+    /// group.
     ///
     /// @return A structure describing a primary and fallback socket.
     /// @throw isc::dhcp::SocketConfigError if error occured when opening
     /// or configuring a socket.
     virtual SocketInfo openSocket(const Iface& iface,
                                   const isc::asiolink::IOAddress& addr,
-                                  const uint16_t port);
+                                  const uint16_t port,
+                                  const bool join_multicast);
 
     /// @brief Receive DHCPv6 message on the interface.
     ///

+ 1 - 1
src/lib/dhcp/tests/pkt_filter6_test_utils.cc

@@ -182,7 +182,7 @@ PktFilter6Stub::PktFilter6Stub()
 
 SocketInfo
 PktFilter6Stub::openSocket(const Iface&, const isc::asiolink::IOAddress& addr,
-                           const uint16_t port) {
+                           const uint16_t port, const bool) {
     ++open_socket_count_;
     return (SocketInfo(addr, port, 0));
 }

+ 5 - 1
src/lib/dhcp/tests/pkt_filter6_test_utils.h

@@ -113,11 +113,15 @@ public:
     /// @param iface Interface descriptor.
     /// @param addr Address on the interface to be used to send packets.
     /// @param port Port number.
+    /// @param join_multicast A boolean parameter which indicates whether
+    /// socket should join All_DHCP_Relay_Agents_and_servers multicast
+    /// group.
     ///
     /// @return A structure describing a primary and fallback socket.
     virtual SocketInfo openSocket(const Iface& iface,
                                   const isc::asiolink::IOAddress& addr,
-                                  const uint16_t port);
+                                  const uint16_t port,
+                                  const bool join_multicast);
 
     /// @brief Simulate reception of the DHCPv6 message.
     ///

+ 3 - 3
src/lib/dhcp/tests/pkt_filter_inet6_unittest.cc

@@ -49,7 +49,7 @@ TEST_F(PktFilterInet6Test, openSocket) {
 
     // Try to open socket.
     PktFilterInet6 pkt_filter;
-    sock_info_ = pkt_filter.openSocket(iface, addr, PORT);
+    sock_info_ = pkt_filter.openSocket(iface, addr, PORT, true);
     // For the packet filter in use, the fallback socket shouldn't be opened.
     // Fallback is typically opened for raw IPv4 sockets.
     EXPECT_LT(sock_info_.fallbackfd_, 0);
@@ -70,7 +70,7 @@ TEST_F(PktFilterInet6Test, send) {
     // Open socket. We don't check that the socket has appropriate
     // options and family set because we have checked that in the
     // openSocket test already.
-    sock_info_ = pkt_filter.openSocket(iface, addr, PORT);
+    sock_info_ = pkt_filter.openSocket(iface, addr, PORT, true);
     ASSERT_GE(sock_info_.sockfd_, 0);
 
     // Send the packet over the socket.
@@ -118,7 +118,7 @@ TEST_F(PktFilterInet6Test, receive) {
     // Open socket. We don't check that the socket has appropriate
     // options and family set because we have checked that in the
     // openSocket test already.
-    sock_info_ = pkt_filter.openSocket(iface, addr, PORT + 1);
+    sock_info_ = pkt_filter.openSocket(iface, addr, PORT + 1, true);
     ASSERT_GE(sock_info_.sockfd_, 0);
 
     // Send a DHCPv6 message to the local loopback address and server's port.