From: g0dil Date: Fri, 2 May 2008 15:43:57 +0000 (+0000) Subject: Socket/Protocols/INet: Extend INet6SocketAddress syntax to support more flexible... X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=3cb0a2ff50b8f1111da34b696e64fb1b037cd683;p=senf.git Socket/Protocols/INet: Extend INet6SocketAddress syntax to support more flexible syntax variantes (embedded v4 address, hostname + zoneid ...) 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 --- diff --git a/Socket/Protocols/INet/INet6Address.cci b/Socket/Protocols/INet/INet6Address.cci index 408d0ac..1e71471 100644 --- a/Socket/Protocols/INet/INet6Address.cci +++ b/Socket/Protocols/INet/INet6Address.cci @@ -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() diff --git a/Socket/Protocols/INet/INet6Address.hh b/Socket/Protocols/INet/INet6Address.hh index 1beecf9..383f87f 100644 --- a/Socket/Protocols/INet/INet6Address.hh +++ b/Socket/Protocols/INet/INet6Address.hh @@ -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 diff --git a/Socket/Protocols/INet/INetAddressing.cc b/Socket/Protocols/INet/INetAddressing.cc index d49f4de..d3c4e36 100644 --- a/Socket/Protocols/INet/INetAddressing.cc +++ b/Socket/Protocols/INet/INetAddressing.cc @@ -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(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]); } diff --git a/Socket/Protocols/INet/MulticastSocketProtocol.cc b/Socket/Protocols/INet/MulticastSocketProtocol.cc index 535dc2f..dca071e 100644 --- a/Socket/Protocols/INet/MulticastSocketProtocol.cc +++ b/Socket/Protocols/INet/MulticastSocketProtocol.cc @@ -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//////////////////////////////////////// diff --git a/Socket/Protocols/INet/MulticastSocketProtocol.hh b/Socket/Protocols/INet/MulticastSocketProtocol.hh index e8249ce..0de6997 100644 --- a/Socket/Protocols/INet/MulticastSocketProtocol.hh +++ b/Socket/Protocols/INet/MulticastSocketProtocol.hh @@ -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 diff --git a/senf.dict b/senf.dict index f02a484..e8d5956 100644 --- 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