MulticastSocketProtocol.cc

Go to the documentation of this file.
00001 // $Id: MulticastSocketProtocol.cc 1742 2010-11-04 14:51:56Z g0dil $
00002 //
00003 // Copyright (C) 2007
00004 // Fraunhofer (FOKUS)
00005 // Competence Center NETwork research (NET), St. Augustin, GERMANY
00006 //     Stefan Bund <g0dil@berlios.de>
00007 //
00008 // This program is free software; you can redistribute it and/or modify
00009 // it under the terms of the GNU General Public License as published by
00010 // the Free Software Foundation; either version 2 of the License, or
00011 // (at your option) any later version.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the
00020 // Free Software Foundation, Inc.,
00021 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00026 #include "MulticastSocketProtocol.hh"
00027 //#include "MulticastSocketProtocol.ih"
00028 
00029 // Custom includes
00030 #include <sys/socket.h>
00031 #include <netinet/in.h>
00032 #include <net/if.h> // for if_nametoindex
00033 #include <senf/Utils/Exception.hh>
00034 
00035 //#include "MulticastSocketProtocol.mpp"
00036 #define prefix_
00037 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00038 
00039 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00040 // senf::MulticastSocketProtocol
00041 
00042 prefix_ void senf::MulticastSocketProtocol::broadcastEnabled(bool v)
00043     const
00044 {
00045     int ivalue (v);
00046     if (::setsockopt(fd(), SOL_SOCKET, SO_BROADCAST, &ivalue, sizeof(ivalue)) < 0)
00047         SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(SO_BROADCAST)");
00048 }
00049 
00050 prefix_ bool senf::MulticastSocketProtocol::broadcastEnabled()
00051     const
00052 {
00053     int value (0);
00054     ::socklen_t len (sizeof(value));
00055     if (::getsockopt(fd(), SOL_SOCKET, SO_BROADCAST, &value, &len) < 0)
00056         SENF_THROW_SYSTEM_EXCEPTION("::getsockopt(SO_BROADCAST)");
00057     return value;
00058 }
00059 
00060 prefix_ bool senf::MulticastSocketProtocol::mcLoop()
00061     const
00062 {
00063     int value (0);
00064     socklen_t len (sizeof(value));
00065     if (::getsockopt(fd(),SOL_IP,IP_MULTICAST_LOOP,&value,&len) < 0)
00066         SENF_THROW_SYSTEM_EXCEPTION("");
00067     return value;
00068 }
00069 
00070 prefix_ void senf::MulticastSocketProtocol::mcLoop(bool value)
00071     const
00072 {
00073     int ivalue (value);
00074     if (::setsockopt(fd(),SOL_IP,IP_MULTICAST_LOOP,&ivalue,sizeof(ivalue)) < 0)
00075         SENF_THROW_SYSTEM_EXCEPTION("");
00076 }
00077 
00078 prefix_ void senf::MulticastSocketProtocol::mcIface(std::string const & iface)
00079     const
00080 {
00081     struct ip_mreqn mreqn;
00082     ::memset(&mreqn, 0, sizeof(mreqn));
00083     if (!iface.empty()) {
00084         mreqn.imr_ifindex = if_nametoindex(iface.c_str());
00085         if (mreqn.imr_ifindex == 0)
00086             throw SystemException(EINVAL SENF_EXC_DEBUGINFO);
00087     }
00088     if (::setsockopt(fd(),SOL_IP,IP_MULTICAST_IF,&mreqn,sizeof(mreqn)) < 0)
00089         SENF_THROW_SYSTEM_EXCEPTION("");
00090 }
00091 
00092 prefix_ unsigned senf::MulticastSocketProtocol::mcTTL()
00093     const
00094 {
00095     int value (0);
00096     socklen_t len (sizeof(value));
00097     if (::getsockopt(fd(),SOL_IP,IP_MULTICAST_TTL,&value,&len) < 0)
00098         SENF_THROW_SYSTEM_EXCEPTION("");
00099     return value;
00100 }
00101 
00102 prefix_ void senf::MulticastSocketProtocol::mcTTL(unsigned value)
00103     const
00104 {
00105     if (::setsockopt(fd(),SOL_IP,IP_MULTICAST_TTL,&value,sizeof(value)) < 0)
00106         SENF_THROW_SYSTEM_EXCEPTION("");
00107 }
00108 
00109 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00110 // senf::INet4MulticastSocketProtocol
00111 
00112 prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address const & mcAddr)
00113     const
00114 {
00115     struct ip_mreqn mreqn;
00116     mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
00117     mreqn.imr_address.s_addr = htons(INADDR_ANY);
00118     mreqn.imr_ifindex = 0;
00119     if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00120         SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP)");
00121 }
00122 
00123 prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address const & mcAddr,
00124                                                                  INet4Address const & localAddr)
00125     const
00126 {
00127     struct ip_mreqn mreqn;
00128     mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
00129     mreqn.imr_address.s_addr = localAddr.inaddr();
00130     mreqn.imr_ifindex = 0;
00131     if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00132         SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP");
00133 }
00134 
00135 prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address const & mcAddr,
00136                                                                  std::string const & iface)
00137     const
00138 {
00139     struct ip_mreqn mreqn;
00140     mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
00141     mreqn.imr_address.s_addr = htons(INADDR_ANY);
00142     mreqn.imr_ifindex = if_nametoindex(iface.c_str());
00143     if (mreqn.imr_ifindex == 0)
00144         throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
00145     if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00146         SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP");
00147 }
00148 
00149 prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address const & mcAddr)
00150     const
00151 {
00152     struct ip_mreqn mreqn;
00153     mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
00154     mreqn.imr_address.s_addr = htons(INADDR_ANY);
00155     mreqn.imr_ifindex = 0;
00156     if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00157         SENF_THROW_SYSTEM_EXCEPTION("");
00158 }
00159 
00160 prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address const & mcAddr,
00161                                                                   INet4Address const & localAddr)
00162     const
00163 {
00164     struct ip_mreqn mreqn;
00165     mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
00166     mreqn.imr_address.s_addr = localAddr.inaddr();
00167     mreqn.imr_ifindex = 0;
00168     if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00169         SENF_THROW_SYSTEM_EXCEPTION("");
00170 }
00171 
00172 prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address const & mcAddr,
00173                                                                   std::string const & iface)
00174     const
00175 {
00176     struct ip_mreqn mreqn;
00177     mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
00178     mreqn.imr_address.s_addr = htons(INADDR_ANY);
00179     mreqn.imr_ifindex = if_nametoindex(iface.c_str());
00180     if (mreqn.imr_ifindex == 0)
00181         throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
00182     if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00183         SENF_THROW_SYSTEM_EXCEPTION("");
00184 }
00185 
00186 namespace {
00187     void mc4SSMSourceRequest(int operation, int fd, senf::INet4Address const & group,
00188                               senf::INet4Address const & source, std::string const & iface)
00189     {
00190         struct group_source_req req;
00191         ::memset(&req, 0, sizeof(req));
00192         req.gsr_interface = if_nametoindex(iface.c_str());
00193         if (req.gsr_interface == 0)
00194             throw senf::SystemException("::if_nametoindex()", ENOENT SENF_EXC_DEBUGINFO);
00195         req.gsr_group.ss_family = AF_INET;
00196         reinterpret_cast<struct sockaddr_in&>(req.gsr_group).sin_addr.s_addr = group.inaddr();
00197         req.gsr_source.ss_family = AF_INET;
00198         reinterpret_cast<struct sockaddr_in&>(req.gsr_source).sin_addr.s_addr = source.inaddr();
00199         if (::setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &req, sizeof(req)) < 0)
00200             SENF_THROW_SYSTEM_EXCEPTION("::setsockopt()");
00201     }
00202 }
00203 
00204 prefix_ void senf::INet4MulticastSocketProtocol::mcJoinSSMSource(INet4Address const & group,
00205                                                                  INet4Address const & source,
00206                                                                  std::string const & iface)
00207     const
00208 {
00209     mc4SSMSourceRequest(MCAST_JOIN_SOURCE_GROUP, fd(), group, source, iface);
00210 }
00211 
00212 prefix_ void senf::INet4MulticastSocketProtocol::mcLeaveSSMSource(INet4Address const & group,
00213                                                                   INet4Address const & source,
00214                                                                   std::string const & iface)
00215     const
00216 {
00217     mc4SSMSourceRequest(MCAST_LEAVE_SOURCE_GROUP, fd(), group, source, iface);
00218 }
00219 
00220 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00221 // senf::INet6MulticastSocketProtocol
00222 
00223 prefix_ void senf::INet6MulticastSocketProtocol::mcAddMembership(INet6Address const & mcAddr)
00224     const
00225 {
00226     if (mcAddr.inet4Mapped()) {
00227         struct ip_mreqn mreqn;
00228         mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
00229         mreqn.imr_address.s_addr = htons(INADDR_ANY);
00230         mreqn.imr_ifindex = 0;
00231         if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00232             SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP)");
00233     }
00234     else {
00235         struct ipv6_mreq mreqn;
00236         std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
00237         mreqn.ipv6mr_interface = 0;
00238         if (::setsockopt(fd(),SOL_IPV6,IPV6_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00239             SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IPV6_ADD_MEMBERSHIP");
00240     }
00241 }
00242 
00243 prefix_ void senf::INet6MulticastSocketProtocol::mcAddMembership(INet6Address const & mcAddr,
00244                                                                  std::string const & iface)
00245     const
00246 {
00247     if (mcAddr.inet4Mapped()) {
00248         struct ip_mreqn mreqn;
00249         mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
00250         mreqn.imr_address.s_addr = htons(INADDR_ANY);
00251         mreqn.imr_ifindex = if_nametoindex(iface.c_str());
00252         if (mreqn.imr_ifindex == 0)
00253             throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
00254         if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00255             SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP");
00256     }
00257     else {
00258         struct ipv6_mreq mreqn;
00259         std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
00260         mreqn.ipv6mr_interface = if_nametoindex(iface.c_str());
00261         if (mreqn.ipv6mr_interface == 0)
00262             throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
00263         if (::setsockopt(fd(),SOL_IPV6,IPV6_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00264             SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IPV6_ADD_MEMBERSHIP");
00265     }
00266 }
00267 
00268 prefix_ void senf::INet6MulticastSocketProtocol::mcDropMembership(INet6Address const & mcAddr)
00269     const
00270 {
00271     if (mcAddr.inet4Mapped()) {
00272         struct ip_mreqn mreqn;
00273         mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
00274         mreqn.imr_address.s_addr = htons(INADDR_ANY);
00275         mreqn.imr_ifindex = 0;
00276         if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00277             SENF_THROW_SYSTEM_EXCEPTION("");
00278     }
00279     else {
00280         struct ipv6_mreq mreqn;
00281         std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
00282         mreqn.ipv6mr_interface = 0;
00283         if (::setsockopt(fd(),SOL_IPV6,IPV6_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00284             SENF_THROW_SYSTEM_EXCEPTION("");
00285     }
00286 }
00287 
00288 prefix_ void
00289 senf::INet6MulticastSocketProtocol::mcDropMembership(INet6Address const & mcAddr,
00290                                                      std::string const & iface)
00291     const
00292 {
00293     if (mcAddr.inet4Mapped()) {
00294         struct ip_mreqn mreqn;
00295         mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
00296         mreqn.imr_address.s_addr = htons(INADDR_ANY);
00297         mreqn.imr_ifindex = if_nametoindex(iface.c_str());
00298         if (mreqn.imr_ifindex == 0)
00299             throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
00300         if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00301             SENF_THROW_SYSTEM_EXCEPTION("");
00302     }
00303     else {
00304         struct ipv6_mreq mreqn;
00305         std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
00306         mreqn.ipv6mr_interface = if_nametoindex(iface.c_str());
00307         if (mreqn.ipv6mr_interface == 0)
00308             throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
00309         if (::setsockopt(fd(),SOL_IPV6,IPV6_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
00310             SENF_THROW_SYSTEM_EXCEPTION("");
00311     }
00312 }
00313 
00314 namespace {
00315 
00316     void mc6SSMSourceRequest(int operation, int fd, senf::INet6Address const & group,
00317                              senf::INet6Address const & source, int ifacei)
00318     {
00319         struct group_source_req req;
00320         ::memset(&req, 0, sizeof(req));
00321         req.gsr_interface = ifacei;
00322         req.gsr_group.ss_family = AF_INET6;
00323         std::copy(group.begin(), group.end(),
00324                   reinterpret_cast<struct sockaddr_in6&>(req.gsr_group).sin6_addr.s6_addr);
00325         req.gsr_source.ss_family = AF_INET6;
00326         std::copy(source.begin(), source.end(),
00327                   reinterpret_cast<struct sockaddr_in6&>(req.gsr_source).sin6_addr.s6_addr);
00328         if (::setsockopt(fd, SOL_IPV6, MCAST_JOIN_SOURCE_GROUP, &req, sizeof(req)) < 0)
00329             SENF_THROW_SYSTEM_EXCEPTION("::setsockopt()");
00330     }
00331 
00332     void mc6SSMSourceRequest(int operation, int fd, senf::INet6Address const & group,
00333                              senf::INet6Address const & source, std::string const & iface)
00334     {
00335         int ifacei (0);
00336         if (! iface.empty()) {
00337             ifacei = if_nametoindex(iface.c_str());
00338             if (ifacei == 0)
00339                 throw senf::SystemException("::if_nametoindex()", ENOENT SENF_EXC_DEBUGINFO);
00340         }
00341         mc6SSMSourceRequest(operation, fd, group, source, ifacei);
00342     }
00343 
00344 }
00345 
00346 prefix_ void senf::INet6MulticastSocketProtocol::mcJoinSSMSource(INet6Address const & group,
00347                                                                  INet6Address const & source,
00348                                                                  std::string const & iface)
00349     const
00350 {
00351     mc6SSMSourceRequest(MCAST_JOIN_SOURCE_GROUP, fd(), group, source, iface);
00352 }
00353 
00354 prefix_ void senf::INet6MulticastSocketProtocol::mcJoinSSMSource(INet6Address const & group,
00355                                                                  INet6Address const & source,
00356                                                                  int ifacei)
00357     const
00358 {
00359     mc6SSMSourceRequest(MCAST_JOIN_SOURCE_GROUP, fd(), group, source, ifacei);
00360 }
00361 
00362 prefix_ void senf::INet6MulticastSocketProtocol::mcLeaveSSMSource(INet6Address const & group,
00363                                                                   INet6Address const & source,
00364                                                                   std::string const & iface)
00365     const
00366 {
00367     mc6SSMSourceRequest(MCAST_LEAVE_SOURCE_GROUP, fd(), group, source, iface);
00368 }
00369 
00370 
00371 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00372 #undef prefix_
00373 //#include "MulticastSocketProtocol.mpp"
00374 
00375 
00376 // Local Variables:
00377 // mode: c++
00378 // fill-column: 100
00379 // comment-column: 40
00380 // c-file-style: "senf"
00381 // indent-tabs-mode: nil
00382 // ispell-local-dictionary: "american"
00383 // compile-command: "scons -u test"
00384 // End: