#include <sys/socket.h>
#include <sys/uio.h>
#include <assert.h>
+#include <net/if.h>
+#include <ifaddrs.h>
#include "configuration.h"
#include "syscalls.h"
#include "addr.h"
#include "timeval.h"
#include "rtp.h"
+#include "ifreq.h"
#include "speaker-protocol.h"
#include "speaker.h"
res->ai_socktype,
res->ai_protocol)) < 0)
fatal(errno, "error creating broadcast socket");
- if(setsockopt(bfd, SOL_SOCKET, SO_BROADCAST, &one, sizeof one) < 0)
- fatal(errno, "error setting SO_BROADCAST on broadcast socket");
+ if((res->ai_family == PF_INET
+ && IN_MULTICAST(
+ ntohl(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr)
+ ))
+ || (res->ai_family == PF_INET6
+ && IN6_IS_ADDR_MULTICAST(
+ &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr
+ ))) {
+ /* Multicasting */
+ switch(res->ai_family) {
+ case PF_INET: {
+ const int mttl = config->multicast_ttl;
+ if(setsockopt(bfd, IPPROTO_IP, IP_MULTICAST_TTL, &mttl, sizeof mttl) < 0)
+ fatal(errno, "error setting IP_MULTICAST_TTL on multicast socket");
+ break;
+ }
+ case PF_INET6: {
+ const int mttl = config->multicast_ttl;
+ if(setsockopt(bfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ &mttl, sizeof mttl) < 0)
+ fatal(errno, "error setting IPV6_MULTICAST_HOPS on multicast socket");
+ break;
+ }
+ default:
+ fatal(0, "unsupported address family %d", res->ai_family);
+ }
+ info("multicasting on %s", sockname);
+ } else {
+ struct ifaddrs *ifs;
+
+ if(getifaddrs(&ifs) < 0)
+ fatal(errno, "error calling getifaddrs");
+ while(ifs) {
+ if((ifs->ifa_flags & IFF_BROADCAST)
+ && sockaddr_equal(ifs->ifa_broadaddr, res->ai_addr))
+ break;
+ ifs = ifs->ifa_next;
+ }
+ if(ifs) {
+ if(setsockopt(bfd, SOL_SOCKET, SO_BROADCAST, &one, sizeof one) < 0)
+ fatal(errno, "error setting SO_BROADCAST on broadcast socket");
+ info("broadcasting on %s (%s)", sockname, ifs->ifa_name);
+ } else
+ info("unicasting on %s", sockname);
+ }
len = sizeof sndbuf;
if(getsockopt(bfd, SOL_SOCKET, SO_SNDBUF,
&sndbuf, &len) < 0)