4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief MulticastSocketProtocol non-inline non-template implementation */
31 #include "MulticastSocketProtocol.hh"
32 //#include "MulticastSocketProtocol.ih"
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <net/if.h> // for if_nametoindex
38 #include <senf/Utils/Exception.hh>
40 //#include "MulticastSocketProtocol.mpp"
42 //-/////////////////////////////////////////////////////////////////////////////////////////////////
44 //-/////////////////////////////////////////////////////////////////////////////////////////////////
45 // senf::MulticastSocketProtocol
47 prefix_ void senf::MulticastSocketProtocol::broadcastEnabled(bool v)
51 if (::setsockopt(fd(), SOL_SOCKET, SO_BROADCAST, &ivalue, sizeof(ivalue)) < 0)
52 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(SO_BROADCAST)");
55 prefix_ bool senf::MulticastSocketProtocol::broadcastEnabled()
59 ::socklen_t len (sizeof(value));
60 if (::getsockopt(fd(), SOL_SOCKET, SO_BROADCAST, &value, &len) < 0)
61 SENF_THROW_SYSTEM_EXCEPTION("::getsockopt(SO_BROADCAST)");
65 prefix_ bool senf::MulticastSocketProtocol::mcLoop()
69 socklen_t len (sizeof(value));
70 if (::getsockopt(fd(),SOL_IP,IP_MULTICAST_LOOP,&value,&len) < 0)
71 SENF_THROW_SYSTEM_EXCEPTION("::getsockopt(IP_MULTICAST_LOOP)");
75 prefix_ void senf::MulticastSocketProtocol::mcLoop(bool value)
79 if (::setsockopt(fd(),SOL_IP,IP_MULTICAST_LOOP,&ivalue,sizeof(ivalue)) < 0)
80 SENF_THROW_SYSTEM_EXCEPTION("::getsockopt(IP_MULTICAST_LOOP)");
83 prefix_ void senf::MulticastSocketProtocol::mcIface(std::string const & iface)
86 struct ip_mreqn mreqn;
87 ::memset(&mreqn, 0, sizeof(mreqn));
89 mreqn.imr_ifindex = if_nametoindex(iface.c_str());
90 if (mreqn.imr_ifindex == 0)
91 throw SystemException(EINVAL SENF_EXC_DEBUGINFO);
93 if (::setsockopt(fd(),SOL_IP,IP_MULTICAST_IF,&mreqn,sizeof(mreqn)) < 0)
94 SENF_THROW_SYSTEM_EXCEPTION("::getsockopt(IP_MULTICAST_IF)");
97 prefix_ unsigned senf::MulticastSocketProtocol::mcTTL()
101 socklen_t len (sizeof(value));
102 if (::getsockopt(fd(),SOL_IP,IP_MULTICAST_TTL,&value,&len) < 0)
103 SENF_THROW_SYSTEM_EXCEPTION("::getsockopt(IP_MULTICAST_TTL)");
107 prefix_ void senf::MulticastSocketProtocol::mcTTL(unsigned value)
110 if (::setsockopt(fd(),SOL_IP,IP_MULTICAST_TTL,&value,sizeof(value)) < 0)
111 SENF_THROW_SYSTEM_EXCEPTION("::getsockopt(IP_MULTICAST_TTL");
114 //-/////////////////////////////////////////////////////////////////////////////////////////////////
115 // senf::INet4MulticastSocketProtocol
117 prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address const & mcAddr)
120 struct ip_mreqn mreqn;
121 mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
122 mreqn.imr_address.s_addr = htons(INADDR_ANY);
123 mreqn.imr_ifindex = 0;
124 if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
125 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP)");
128 prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address const & mcAddr,
129 INet4Address const & localAddr)
132 struct ip_mreqn mreqn;
133 mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
134 mreqn.imr_address.s_addr = localAddr.inaddr();
135 mreqn.imr_ifindex = 0;
136 if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
137 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP");
140 prefix_ void senf::INet4MulticastSocketProtocol::mcAddMembership(INet4Address const & mcAddr,
141 std::string const & iface)
144 struct ip_mreqn mreqn;
145 mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
146 mreqn.imr_address.s_addr = htons(INADDR_ANY);
147 mreqn.imr_ifindex = if_nametoindex(iface.c_str());
148 if (mreqn.imr_ifindex == 0)
149 throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
150 if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
151 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP");
154 prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address const & mcAddr)
157 struct ip_mreqn mreqn;
158 mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
159 mreqn.imr_address.s_addr = htons(INADDR_ANY);
160 mreqn.imr_ifindex = 0;
161 if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
162 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_DROP_MEMBERSHIP");
165 prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address const & mcAddr,
166 INet4Address const & localAddr)
169 struct ip_mreqn mreqn;
170 mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
171 mreqn.imr_address.s_addr = localAddr.inaddr();
172 mreqn.imr_ifindex = 0;
173 if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
174 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_DROP_MEMBERSHIP");
177 prefix_ void senf::INet4MulticastSocketProtocol::mcDropMembership(INet4Address const & mcAddr,
178 std::string const & iface)
181 struct ip_mreqn mreqn;
182 mreqn.imr_multiaddr.s_addr = mcAddr.inaddr();
183 mreqn.imr_address.s_addr = htons(INADDR_ANY);
184 mreqn.imr_ifindex = if_nametoindex(iface.c_str());
185 if (mreqn.imr_ifindex == 0)
186 throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
187 if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
188 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_DROP_MEMBERSHIP");
192 void mc4SSMSourceRequest(int operation, int fd, senf::INet4Address const & group,
193 senf::INet4Address const & source, std::string const & iface)
195 struct group_source_req req;
196 ::memset(&req, 0, sizeof(req));
197 req.gsr_interface = if_nametoindex(iface.c_str());
198 if (req.gsr_interface == 0)
199 throw senf::SystemException("::if_nametoindex()", ENOENT SENF_EXC_DEBUGINFO);
200 req.gsr_group.ss_family = AF_INET;
201 reinterpret_cast<struct sockaddr_in&>(req.gsr_group).sin_addr.s_addr = group.inaddr();
202 req.gsr_source.ss_family = AF_INET;
203 reinterpret_cast<struct sockaddr_in&>(req.gsr_source).sin_addr.s_addr = source.inaddr();
204 if (::setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &req, sizeof(req)) < 0)
205 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt()");
209 prefix_ void senf::INet4MulticastSocketProtocol::mcJoinSSMSource(INet4Address const & group,
210 INet4Address const & source,
211 std::string const & iface)
214 mc4SSMSourceRequest(MCAST_JOIN_SOURCE_GROUP, fd(), group, source, iface);
217 prefix_ void senf::INet4MulticastSocketProtocol::mcLeaveSSMSource(INet4Address const & group,
218 INet4Address const & source,
219 std::string const & iface)
222 mc4SSMSourceRequest(MCAST_LEAVE_SOURCE_GROUP, fd(), group, source, iface);
225 //-/////////////////////////////////////////////////////////////////////////////////////////////////
226 // senf::INet6MulticastSocketProtocol
228 prefix_ void senf::INet6MulticastSocketProtocol::mcAddMembership(INet6Address const & mcAddr)
231 if (mcAddr.inet4Mapped()) {
232 struct ip_mreqn mreqn;
233 mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
234 mreqn.imr_address.s_addr = htons(INADDR_ANY);
235 mreqn.imr_ifindex = 0;
236 if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
237 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP)");
240 struct ipv6_mreq mreqn;
241 std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
242 mreqn.ipv6mr_interface = 0;
243 if (::setsockopt(fd(),SOL_IPV6,IPV6_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
244 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IPV6_ADD_MEMBERSHIP");
248 prefix_ void senf::INet6MulticastSocketProtocol::mcAddMembership(INet6Address const & mcAddr,
249 std::string const & iface)
252 if (mcAddr.inet4Mapped()) {
253 struct ip_mreqn mreqn;
254 mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
255 mreqn.imr_address.s_addr = htons(INADDR_ANY);
256 mreqn.imr_ifindex = if_nametoindex(iface.c_str());
257 if (mreqn.imr_ifindex == 0)
258 throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
259 if (::setsockopt(fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
260 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_ADD_MEMBERSHIP");
263 struct ipv6_mreq mreqn;
264 std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
265 mreqn.ipv6mr_interface = if_nametoindex(iface.c_str());
266 if (mreqn.ipv6mr_interface == 0)
267 throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
268 if (::setsockopt(fd(),SOL_IPV6,IPV6_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
269 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IPV6_ADD_MEMBERSHIP");
273 prefix_ void senf::INet6MulticastSocketProtocol::mcDropMembership(INet6Address const & mcAddr)
276 if (mcAddr.inet4Mapped()) {
277 struct ip_mreqn mreqn;
278 mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
279 mreqn.imr_address.s_addr = htons(INADDR_ANY);
280 mreqn.imr_ifindex = 0;
281 if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
282 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_DROP_MEMBERSHIP");
285 struct ipv6_mreq mreqn;
286 std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
287 mreqn.ipv6mr_interface = 0;
288 if (::setsockopt(fd(),SOL_IPV6,IPV6_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
289 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IPV6_DROP_MEMBERSHIP");
294 senf::INet6MulticastSocketProtocol::mcDropMembership(INet6Address const & mcAddr,
295 std::string const & iface)
298 if (mcAddr.inet4Mapped()) {
299 struct ip_mreqn mreqn;
300 mreqn.imr_multiaddr.s_addr = mcAddr.inet4address().inaddr();
301 mreqn.imr_address.s_addr = htons(INADDR_ANY);
302 mreqn.imr_ifindex = if_nametoindex(iface.c_str());
303 if (mreqn.imr_ifindex == 0)
304 throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
305 if (::setsockopt(fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
306 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IP_DROP_MEMBERSHIP");
309 struct ipv6_mreq mreqn;
310 std::copy(mcAddr.begin(), mcAddr.end(), mreqn.ipv6mr_multiaddr.s6_addr);
311 mreqn.ipv6mr_interface = if_nametoindex(iface.c_str());
312 if (mreqn.ipv6mr_interface == 0)
313 throw SystemException("::if_nametoindex()",ENOENT SENF_EXC_DEBUGINFO);
314 if (::setsockopt(fd(),SOL_IPV6,IPV6_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0)
315 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt(IPV6_DROP_MEMBERSHIP");
321 void mc6SSMSourceRequest(int operation, int fd, senf::INet6Address const & group,
322 senf::INet6Address const & source, int ifacei)
324 struct group_source_req req;
325 ::memset(&req, 0, sizeof(req));
326 req.gsr_interface = ifacei;
327 req.gsr_group.ss_family = AF_INET6;
328 std::copy(group.begin(), group.end(),
329 reinterpret_cast<struct sockaddr_in6&>(req.gsr_group).sin6_addr.s6_addr);
330 req.gsr_source.ss_family = AF_INET6;
331 std::copy(source.begin(), source.end(),
332 reinterpret_cast<struct sockaddr_in6&>(req.gsr_source).sin6_addr.s6_addr);
333 if (::setsockopt(fd, SOL_IPV6, MCAST_JOIN_SOURCE_GROUP, &req, sizeof(req)) < 0)
334 SENF_THROW_SYSTEM_EXCEPTION("::setsockopt()");
337 void mc6SSMSourceRequest(int operation, int fd, senf::INet6Address const & group,
338 senf::INet6Address const & source, std::string const & iface)
341 if (! iface.empty()) {
342 ifacei = if_nametoindex(iface.c_str());
344 throw senf::SystemException("::if_nametoindex()", ENOENT SENF_EXC_DEBUGINFO);
346 mc6SSMSourceRequest(operation, fd, group, source, ifacei);
351 prefix_ void senf::INet6MulticastSocketProtocol::mcJoinSSMSource(INet6Address const & group,
352 INet6Address const & source,
353 std::string const & iface)
356 mc6SSMSourceRequest(MCAST_JOIN_SOURCE_GROUP, fd(), group, source, iface);
359 prefix_ void senf::INet6MulticastSocketProtocol::mcJoinSSMSource(INet6Address const & group,
360 INet6Address const & source,
364 mc6SSMSourceRequest(MCAST_JOIN_SOURCE_GROUP, fd(), group, source, ifacei);
367 prefix_ void senf::INet6MulticastSocketProtocol::mcLeaveSSMSource(INet6Address const & group,
368 INet6Address const & source,
369 std::string const & iface)
372 mc6SSMSourceRequest(MCAST_LEAVE_SOURCE_GROUP, fd(), group, source, iface);
376 //-/////////////////////////////////////////////////////////////////////////////////////////////////
378 //#include "MulticastSocketProtocol.mpp"
384 // comment-column: 40
385 // c-file-style: "senf"
386 // indent-tabs-mode: nil
387 // ispell-local-dictionary: "american"
388 // compile-command: "scons -u test"