Socket/Protocols/INet: Extend INet6SocketAddress syntax to support more flexible...
g0dil [Fri, 2 May 2008 15:43:57 +0000 (15:43 +0000)]
Socket/Protocols/INet: Add (linux specific) support for v6 mapped v4 multicast addresses

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@835 270642c3-0616-0410-b53a-bc976706d245

Socket/Protocols/INet/INet6Address.cci
Socket/Protocols/INet/INet6Address.hh
Socket/Protocols/INet/INetAddressing.cc
Socket/Protocols/INet/MulticastSocketProtocol.cc
Socket/Protocols/INet/MulticastSocketProtocol.hh
senf.dict

index 408d0ac..1e71471 100644 (file)
@@ -127,7 +127,7 @@ prefix_ bool senf::INet6Address::unicast()
 prefix_ bool senf::INet6Address::multicast()
     const
 {
-    return (*this)[0] == 0xFFu;
+    return (*this)[0] == 0xFFu || inet4Mapped() && inet4address().multicast();
 }
 
 prefix_ senf::INet6Address::ScopeId senf::INet6Address::scope()
index 1beecf9..383f87f 100644 (file)
@@ -216,6 +216,12 @@ namespace senf {
 
         bool unicast() const;           ///< \c true, if address is unicast
         bool multicast() const;         ///< \c true, if address is multicast
+                                        /**< To support a linux specific extension, INet4 multicast
+                                             addressed mapped to INet6 are also interpreted as
+                                             multicast addresses. This is NOT part of the standard,
+                                             however the standard officially only allows unicast v4
+                                             addresses to be mapped to v6 so this does not collide
+                                             with any standard conforming use. */
 
         ScopeId scope() const;          ///< Get address's scope
                                         /**< The scope of an address is one of the \ref ScopeId
index d49f4de..d3c4e36 100644 (file)
@@ -89,12 +89,12 @@ prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr,
     //             or: host ":" port
     //             or: port
 
-    static boost::regex const addressRx ("(?:(?:\\[([a-f0-9A-F:]+)(?:%(.+))?\\]|(.+)):)?([0-9]+)");
+    static boost::regex const addressRx ("(?:(?:\\[([^%]+)(?:%(.+))?\\]|(.+)):)?([0-9]+)");
     // Subexpression numbers:
-    enum { NumericAddr = 1,
-           ZoneId      = 2,
-           Hostname    = 3,
-           Port        = 4 };
+    enum { Address  = 1,
+           ZoneId   = 2,
+           Hostname = 3,
+           Port     = 4 };
     
     boost::smatch match;
     if (! regex_match(addr, match, addressRx))
@@ -105,9 +105,9 @@ prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr,
 
     sockaddr_.sin6_port = htons(boost::lexical_cast<boost::uint16_t>(match[Port]));
 
-    if (match[NumericAddr].matched || match[Hostname].matched) {
+    if (match[Address].matched || match[Hostname].matched) {
         INet6Address a (INet6Address::from_string(
-                            match[NumericAddr].matched ? match[NumericAddr] : match[Hostname],
+                            match[Address].matched ? match[Address] : match[Hostname],
                             resolve));
         std::copy(a.begin(), a.end(), &sockaddr_.sin6_addr.s6_addr[0]);
     }
index 535dc2f..dca071e 100644 (file)
@@ -121,7 +121,7 @@ prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address co
 }
 
 prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address const & mcAddr,
-                                                           INet4Address const & localAddr)
+                                                                 INet4Address const & localAddr)
     const
 {
     struct ip_mreqn mreqn;
@@ -133,7 +133,7 @@ prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address co
 }
 
 prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address const & mcAddr,
-                                                           std::string const & iface)
+                                                                 std::string const & iface)
     const
 {
     struct ip_mreqn mreqn;
@@ -158,7 +158,7 @@ prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address c
 }
 
 prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address const & mcAddr,
-                                                            INet4Address const & localAddr)
+                                                                  INet4Address const & localAddr)
     const
 {
     struct ip_mreqn mreqn;
@@ -170,7 +170,7 @@ prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address c
 }
 
 prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address const & mcAddr,
-                                                            std::string const & iface)
+                                                                  std::string const & iface)
     const
 {
     struct ip_mreqn mreqn;
@@ -189,47 +189,91 @@ prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address c
 prefix_ void senf::INet6MulticastSocketProtocol::mcAddMembership(INet6Address const & mcAddr)
     const
 {
-    struct ipv6_mreq mreqn;
-    std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
-    mreqn.ipv6mr_interface = 0;
-    if (::setsockopt(fd(),SOL_IPV6,IPV6_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
-        SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IPV6_ADD_MEMBERSHIP");
+    if (mcAddr.inet4Mapped()) {
+        struct ip_mreqn mreqn;
+        mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
+        mreqn.imr_address.s_addr = htons(INADDR_ANY);
+        mreqn.imr_ifindex = 0;
+        if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
+            SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP)");
+    }
+    else {
+        struct ipv6_mreq mreqn;
+        std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
+        mreqn.ipv6mr_interface = 0;
+        if (::setsockopt(fd(),SOL_IPV6,IPV6_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
+            SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IPV6_ADD_MEMBERSHIP");
+    }
 }
 
 prefix_ void senf::INet6MulticastSocketProtocol::mcAddMembership(INet6Address const & mcAddr,
-                                                           std::string const & iface)
+                                                                 std::string const & iface)
 {
-    struct ipv6_mreq mreqn;
-    std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
-    mreqn.ipv6mr_interface = if_nametoindex(iface.c_str());
-    if (mreqn.ipv6mr_interface == 0)
-        throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
-    if (::setsockopt(fd(),SOL_IPV6,IPV6_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
-        SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IPV6_ADD_MEMBERSHIP");
+    if (mcAddr.inet4Mapped()) {
+        struct ip_mreqn mreqn;
+        mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
+        mreqn.imr_address.s_addr = htons(INADDR_ANY);
+        mreqn.imr_ifindex = if_nametoindex(iface.c_str());
+        if (mreqn.imr_ifindex == 0)
+            throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
+        if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
+            SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP");
+    }
+    else {
+        struct ipv6_mreq mreqn;
+        std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
+        mreqn.ipv6mr_interface = if_nametoindex(iface.c_str());
+        if (mreqn.ipv6mr_interface == 0)
+            throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
+        if (::setsockopt(fd(),SOL_IPV6,IPV6_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
+            SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IPV6_ADD_MEMBERSHIP");
+    }
 }
 
 prefix_ void senf::INet6MulticastSocketProtocol::mcDropMembership(INet6Address const & mcAddr)
     const
 {
-    struct ipv6_mreq mreqn;
-    std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
-    mreqn.ipv6mr_interface = 0;
-    if (::setsockopt(fd(),SOL_IPV6,IPV6_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
-        SENF_THROW_SYSTEM_EXCEPTION("");
+    if (mcAddr.inet4Mapped()) {
+        struct ip_mreqn mreqn;
+        mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
+        mreqn.imr_address.s_addr = htons(INADDR_ANY);
+        mreqn.imr_ifindex = 0;
+        if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
+            SENF_THROW_SYSTEM_EXCEPTION("");
+    }
+    else {
+        struct ipv6_mreq mreqn;
+        std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
+        mreqn.ipv6mr_interface = 0;
+        if (::setsockopt(fd(),SOL_IPV6,IPV6_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
+            SENF_THROW_SYSTEM_EXCEPTION("");
+    }
 }
 
 prefix_ void
 senf::INet6MulticastSocketProtocol::mcDropMembership(INet6Address const & mcAddr,
-                                               std::string const & iface)
+                                                     std::string const & iface)
     const
 {
-    struct ipv6_mreq mreqn;
-    std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
-    mreqn.ipv6mr_interface = if_nametoindex(iface.c_str());
-    if (mreqn.ipv6mr_interface == 0)
-        throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
-    if (::setsockopt(fd(),SOL_IPV6,IPV6_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
-        SENF_THROW_SYSTEM_EXCEPTION("");
+    if (mcAddr.inet4Mapped()) {
+        struct ip_mreqn mreqn;
+        mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
+        mreqn.imr_address.s_addr = htons(INADDR_ANY);
+        mreqn.imr_ifindex = if_nametoindex(iface.c_str());
+        if (mreqn.imr_ifindex == 0)
+            throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
+        if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
+            SENF_THROW_SYSTEM_EXCEPTION("");
+    }
+    else {
+        struct ipv6_mreq mreqn;
+        std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
+        mreqn.ipv6mr_interface = if_nametoindex(iface.c_str());
+        if (mreqn.ipv6mr_interface == 0)
+            throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
+        if (::setsockopt(fd(),SOL_IPV6,IPV6_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
+            SENF_THROW_SYSTEM_EXCEPTION("");
+    }
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index e8249ce..0de6997 100644 (file)
@@ -128,6 +128,9 @@ namespace senf {
     };
 
     /** \brief Multicast protocol facet for INet6 addressable multicast enabled sockets
+
+        This implementation supports INet6 mapped INet4 multicast addresses. This is a linux
+        specific extension and NOT part of the relevant RFCs.
      */
     class INet6MulticastSocketProtocol
         : public MulticastSocketProtocol
@@ -139,14 +142,6 @@ namespace senf {
                                              groups received. The group is joined on the default
                                              interface.
                                              \param[in] mcAddr address of group to join */
-        void mcAddMembership(INet6Address const & mcAddr, INet6Address const & localAddr) 
-            const;
-                                        ///< join multicast group on a specific interface
-                                        /**< This member will add \a mcAddr to the list of multicast
-                                             groups received. The group is joined on the interface
-                                             with the given local address.
-                                             \param[in] mcAddr address of group to join
-                                             \param[in] localAddr address of interface to join on */
         void mcAddMembership(INet6Address const & mcAddr, std::string const & iface);
                                         ///< join multicast group on a specific interface
                                         /**< This member will add \a mcAddr to the list of multicast
@@ -161,15 +156,6 @@ namespace senf {
                                              multicast groups received. The group is left from the
                                              default interface.
                                              \param[in] mcAddr address of group to leave */
-        void mcDropMembership(INet6Address const & mcAddr, INet6Address const & localAddr) 
-            const;
-                                        ///< leave multicast group on a specific interface
-                                        /**< This member will remove \a mcAddr from the list of
-                                             multicast groups received. The group is left from the
-                                             interface with the given local address.
-                                             \param[in] mcAddr address of group to leave
-                                             \param[in] localAddr address of interface to leave
-                                                 from */
         void mcDropMembership(INet6Address const & mcAddr, std::string const & iface) 
             const;
                                         ///< leave multicast group on a specific interface
index f02a484..e8d5956 100644 (file)
--- a/senf.dict
+++ b/senf.dict
@@ -41,6 +41,7 @@ BerliOS
 bitfield
 bool
 boostfn
+broadcastEnabled
 bund
 calculateChecksum
 callables
@@ -209,6 +210,7 @@ iberty
 IDE
 IdleEvent
 ietf
+iface
 ifndef
 ih
 impl
@@ -262,9 +264,11 @@ libSocket
 libUtils
 LINKFLAGS
 LinkScope
+linux
 ListB
 ListN
 ListPolicy
+localAddr
 localhost
 loopback
 mac
@@ -272,6 +276,10 @@ MACAddress
 MACAddressParser
 mainpage
 manualparse
+mcAddMembership
+mcAddr
+mcDropMembership
+mcLoop
 mem
 memberfn
 mixin
@@ -279,6 +287,7 @@ mkdir
 MPEGDVBBundle
 mpp
 multicast
+MulticastSocketProtocol
 MyClass
 mycommand
 mydir
@@ -412,6 +421,7 @@ RegistrationProxy
 repos
 rerference
 rfc
+RFCs
 RO
 RP
 SafePacketParser