4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief MulticastSocketProtocol non-inline non-template implementation */
26 #include "MulticastSocketProtocol.hh"
27 //#include "MulticastSocketProtocol.ih"
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <net/if.h> // for if_nametoindex
33 #include "../../../Utils/Exception.hh"
35 //#include "MulticastSocketProtocol.mpp"
37 ///////////////////////////////cc.p////////////////////////////////////////
39 ///////////////////////////////////////////////////////////////////////////
40 // senf::MulticastSocketProtocol
42 prefix_ void senf::MulticastSocketProtocol::broadcastEnabled(bool v)
46 if (::setsockopt(fd(), SOL_SOCKET, SO_BROADCAST, &ivalue, sizeof(ivalue)) < 0)
47 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(SO_BROADCAST)");
50 prefix_ bool senf::MulticastSocketProtocol::broadcastEnabled()
54 ::socklen_t len (sizeof(value));
55 if (::getsockopt(fd(), SOL_SOCKET, SO_BROADCAST, &value, &len) < 0)
56 SENF_THROW_SYSTEM_EXCEPTION("::getsockopt(SO_BROADCAST)");
60 prefix_ bool senf::MulticastSocketProtocol::mcLoop()
64 socklen_t len (sizeof(value));
65 if (::getsockopt(fd(),SOL_IP,IP_MULTICAST_LOOP,&value,&len) < 0)
66 SENF_THROW_SYSTEM_EXCEPTION("");
70 prefix_ void senf::MulticastSocketProtocol::mcLoop(bool value)
74 if (::setsockopt(fd(),SOL_IP,IP_MULTICAST_LOOP,&ivalue,sizeof(ivalue)) < 0)
75 SENF_THROW_SYSTEM_EXCEPTION("");
78 prefix_ void senf::MulticastSocketProtocol::mcIface(std::string const & iface)
81 struct ip_mreqn mreqn;
82 ::memset(&mreqn,sizeof(mreqn),0);
84 mreqn.imr_ifindex = if_nametoindex(iface.c_str());
85 if (mreqn.imr_ifindex == 0)
86 throw SystemException(EINVAL SENF_EXC_DEBUGINFO);
88 if (::setsockopt(fd(),SOL_IP,IP_MULTICAST_IF,&mreqn,sizeof(mreqn)) < 0)
89 SENF_THROW_SYSTEM_EXCEPTION("");
92 prefix_ unsigned senf::MulticastSocketProtocol::mcTTL()
96 socklen_t len (sizeof(value));
97 if (::getsockopt(fd(),SOL_IP,IP_MULTICAST_TTL,&value,&len) < 0)
98 SENF_THROW_SYSTEM_EXCEPTION("");
102 prefix_ void senf::MulticastSocketProtocol::mcTTL(unsigned value)
105 if (::setsockopt(fd(),SOL_IP,IP_MULTICAST_TTL,&value,sizeof(value)) < 0)
106 SENF_THROW_SYSTEM_EXCEPTION("");
109 ///////////////////////////////////////////////////////////////////////////
110 // senf::INet4MulticastSocketProtocol
112 prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address const & mcAddr)
115 struct ip_mreqn mreqn;
116 mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
117 mreqn.imr_address.s_addr = htons(INADDR_ANY);
118 mreqn.imr_ifindex = 0;
119 if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
120 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP)");
123 prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address const & mcAddr,
124 INet4Address const & localAddr)
127 struct ip_mreqn mreqn;
128 mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
129 mreqn.imr_address.s_addr = localAddr.inaddr();
130 mreqn.imr_ifindex = 0;
131 if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
132 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP");
135 prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address const & mcAddr,
136 std::string const & iface)
139 struct ip_mreqn mreqn;
140 mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
141 mreqn.imr_address.s_addr = htons(INADDR_ANY);
142 mreqn.imr_ifindex = if_nametoindex(iface.c_str());
143 if (mreqn.imr_ifindex == 0)
144 throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
145 if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
146 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP");
149 prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address const & mcAddr)
152 struct ip_mreqn mreqn;
153 mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
154 mreqn.imr_address.s_addr = htons(INADDR_ANY);
155 mreqn.imr_ifindex = 0;
156 if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
157 SENF_THROW_SYSTEM_EXCEPTION("");
160 prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address const & mcAddr,
161 INet4Address const & localAddr)
164 struct ip_mreqn mreqn;
165 mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
166 mreqn.imr_address.s_addr = localAddr.inaddr();
167 mreqn.imr_ifindex = 0;
168 if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
169 SENF_THROW_SYSTEM_EXCEPTION("");
172 prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address const & mcAddr,
173 std::string const & iface)
176 struct ip_mreqn mreqn;
177 mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
178 mreqn.imr_address.s_addr = htons(INADDR_ANY);
179 mreqn.imr_ifindex = if_nametoindex(iface.c_str());
180 if (mreqn.imr_ifindex == 0)
181 throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
182 if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
183 SENF_THROW_SYSTEM_EXCEPTION("");
187 void mc4SSMSourceRequest(int operation, int fd, senf::INet4Address const & group,
188 senf::INet4Address const & source, std::string const & iface)
190 struct group_source_req req;
191 ::memset(&req, 0, sizeof(req));
192 req.gsr_interface = if_nametoindex(iface.c_str());
193 if (req.gsr_interface == 0)
194 throw senf::SystemException("::if_nametoindex()", ENOENT SENF_EXC_DEBUGINFO);
195 req.gsr_group.ss_family = AF_INET;
196 reinterpret_cast<struct sockaddr_in&>(req.gsr_group).sin_addr.s_addr = group.inaddr();
197 req.gsr_source.ss_family = AF_INET;
198 reinterpret_cast<struct sockaddr_in&>(req.gsr_source).sin_addr.s_addr = source.inaddr();
199 if (::setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &req, sizeof(req)) < 0)
200 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt()");
204 prefix_ void senf::INet4MulticastSocketProtocol::mcJoinSSMSource(INet4Address const & group,
205 INet4Address const & source,
206 std::string const & iface)
209 mc4SSMSourceRequest(MCAST_JOIN_SOURCE_GROUP, fd(), group, source, iface);
212 prefix_ void senf::INet4MulticastSocketProtocol::mcLeaveSSMSource(INet4Address const & group,
213 INet4Address const & source,
214 std::string const & iface)
217 mc4SSMSourceRequest(MCAST_LEAVE_SOURCE_GROUP, fd(), group, source, iface);
220 ///////////////////////////////////////////////////////////////////////////
221 // senf::INet6MulticastSocketProtocol
223 prefix_ void senf::INet6MulticastSocketProtocol::mcAddMembership(INet6Address const & mcAddr)
226 if (mcAddr.inet4Mapped()) {
227 struct ip_mreqn mreqn;
228 mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
229 mreqn.imr_address.s_addr = htons(INADDR_ANY);
230 mreqn.imr_ifindex = 0;
231 if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
232 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP)");
235 struct ipv6_mreq mreqn;
236 std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
237 mreqn.ipv6mr_interface = 0;
238 if (::setsockopt(fd(),SOL_IPV6,IPV6_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
239 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IPV6_ADD_MEMBERSHIP");
243 prefix_ void senf::INet6MulticastSocketProtocol::mcAddMembership(INet6Address const & mcAddr,
244 std::string const & iface)
247 if (mcAddr.inet4Mapped()) {
248 struct ip_mreqn mreqn;
249 mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
250 mreqn.imr_address.s_addr = htons(INADDR_ANY);
251 mreqn.imr_ifindex = if_nametoindex(iface.c_str());
252 if (mreqn.imr_ifindex == 0)
253 throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
254 if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
255 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP");
258 struct ipv6_mreq mreqn;
259 std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
260 mreqn.ipv6mr_interface = if_nametoindex(iface.c_str());
261 if (mreqn.ipv6mr_interface == 0)
262 throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
263 if (::setsockopt(fd(),SOL_IPV6,IPV6_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
264 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IPV6_ADD_MEMBERSHIP");
268 prefix_ void senf::INet6MulticastSocketProtocol::mcDropMembership(INet6Address const & mcAddr)
271 if (mcAddr.inet4Mapped()) {
272 struct ip_mreqn mreqn;
273 mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
274 mreqn.imr_address.s_addr = htons(INADDR_ANY);
275 mreqn.imr_ifindex = 0;
276 if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
277 SENF_THROW_SYSTEM_EXCEPTION("");
280 struct ipv6_mreq mreqn;
281 std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
282 mreqn.ipv6mr_interface = 0;
283 if (::setsockopt(fd(),SOL_IPV6,IPV6_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
284 SENF_THROW_SYSTEM_EXCEPTION("");
289 senf::INet6MulticastSocketProtocol::mcDropMembership(INet6Address const & mcAddr,
290 std::string const & iface)
293 if (mcAddr.inet4Mapped()) {
294 struct ip_mreqn mreqn;
295 mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
296 mreqn.imr_address.s_addr = htons(INADDR_ANY);
297 mreqn.imr_ifindex = if_nametoindex(iface.c_str());
298 if (mreqn.imr_ifindex == 0)
299 throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
300 if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
301 SENF_THROW_SYSTEM_EXCEPTION("");
304 struct ipv6_mreq mreqn;
305 std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
306 mreqn.ipv6mr_interface = if_nametoindex(iface.c_str());
307 if (mreqn.ipv6mr_interface == 0)
308 throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
309 if (::setsockopt(fd(),SOL_IPV6,IPV6_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
310 SENF_THROW_SYSTEM_EXCEPTION("");
316 void mc6SSMSourceRequest(int operation, int fd, senf::INet6Address const & group,
317 senf::INet6Address const & source, int ifacei)
319 struct group_source_req req;
320 ::memset(&req, 0, sizeof(req));
321 req.gsr_interface = ifacei;
322 req.gsr_group.ss_family = AF_INET6;
323 std::copy(group.begin(), group.end(),
324 reinterpret_cast<struct sockaddr_in6&>(req.gsr_group).sin6_addr.s6_addr);
325 req.gsr_source.ss_family = AF_INET6;
326 std::copy(source.begin(), source.end(),
327 reinterpret_cast<struct sockaddr_in6&>(req.gsr_source).sin6_addr.s6_addr);
328 if (::setsockopt(fd, SOL_IPV6, MCAST_JOIN_SOURCE_GROUP, &req, sizeof(req)) < 0)
329 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt()");
332 void mc6SSMSourceRequest(int operation, int fd, senf::INet6Address const & group,
333 senf::INet6Address const & source, std::string const & iface)
336 if (! iface.empty()) {
337 ifacei = if_nametoindex(iface.c_str());
339 throw senf::SystemException("::if_nametoindex()", ENOENT SENF_EXC_DEBUGINFO);
341 mc6SSMSourceRequest(operation, fd, group, source, ifacei);
346 prefix_ void senf::INet6MulticastSocketProtocol::mcJoinSSMSource(INet6Address const & group,
347 INet6Address const & source,
348 std::string const & iface)
351 mc6SSMSourceRequest(MCAST_JOIN_SOURCE_GROUP, fd(), group, source, iface);
354 prefix_ void senf::INet6MulticastSocketProtocol::mcJoinSSMSource(INet6Address const & group,
355 INet6Address const & source,
359 mc6SSMSourceRequest(MCAST_JOIN_SOURCE_GROUP, fd(), group, source, ifacei);
362 prefix_ void senf::INet6MulticastSocketProtocol::mcLeaveSSMSource(INet6Address const & group,
363 INet6Address const & source,
364 std::string const & iface)
367 mc6SSMSourceRequest(MCAST_LEAVE_SOURCE_GROUP, fd(), group, source, iface);
371 ///////////////////////////////cc.e////////////////////////////////////////
373 //#include "MulticastSocketProtocol.mpp"
379 // comment-column: 40
380 // c-file-style: "senf"
381 // indent-tabs-mode: nil
382 // ispell-local-dictionary: "american"
383 // compile-command: "scons -u test"