From 81b1bf12365297c8bace12f28e45c0796c593915 Mon Sep 17 00:00:00 2001 Message-Id: <81b1bf12365297c8bace12f28e45c0796c593915.1715321197.git.mdw@distorted.org.uk> From: Mark Wooding Date: Wed, 26 Sep 2007 14:46:21 +0100 Subject: [PATCH] disorder-speaker now logs what it's transmitting too, and only requests broadcast if you specify the broadcast address of some interface. Organization: Straylight/Edgeware From: Richard Kettlewell --- lib/Makefile.am | 1 + lib/ifreq.c | 84 ++++++++++++++++++++++++++++++++++++++++ lib/ifreq.h | 47 ++++++++++++++++++++++ server/speaker-network.c | 26 +++++++++++-- 4 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 lib/ifreq.c create mode 100644 lib/ifreq.h diff --git a/lib/Makefile.am b/lib/Makefile.am index e9f7e43..0101aa2 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -38,6 +38,7 @@ libdisorder_a_SOURCES=charset.c charset.h \ hash.c hash.h \ heap.h \ hex.c hex.h \ + ifreq.c ifreq.h \ inputline.c inputline.h \ kvp.c kvp.h \ log.c log.h log-impl.h \ diff --git a/lib/ifreq.c b/lib/ifreq.c new file mode 100644 index 0000000..7f16ac7 --- /dev/null +++ b/lib/ifreq.c @@ -0,0 +1,84 @@ +/* + * This file is part of DisOrder. + * Copyright (C) 2007 Richard Kettlewell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ +/** @file lib/ffreq.c + * @brief Network interface support + */ + +#include +#include "types.h" + +#include +#include +#include +#include +#include + +#include "ifreq.h" +#include "mem.h" +#include "log.h" + +/** @brief Get the list of network interfaces + * @param fd File descriptor to use + * @param interfaces Where to put pointer to array of interfaces + * @param ninterfaces Where to put count of interfaces + */ +void ifreq_list(int fd, struct ifreq **interfaces, int *ninterfaces) { + struct ifconf ifc; + int l; + + ifc.ifc_len = 0; + ifc.ifc_req = 0; + do { + l = ifc.ifc_len = ifc.ifc_len ? 2 * ifc.ifc_len + : 16 * (int)sizeof (struct ifreq); + if(!l) fatal(0, "out of memory"); + ifc.ifc_req = xrealloc(ifc.ifc_req, l); + if(ioctl(fd, SIOCGIFCONF, &ifc) < 0) + fatal(errno, "error calling ioctl SIOCGIFCONF"); + } while(l == ifc.ifc_len); + *ninterfaces = ifc.ifc_len / sizeof (struct ifreq); + *interfaces = ifc.ifc_req; +} + +/** @brief Return true if two socket addresses match */ +int sockaddr_equal(const struct sockaddr *a, const struct sockaddr *b) { + if(a->sa_family != b->sa_family) + return 0; + switch(a->sa_family) { + case AF_INET: + return ((const struct sockaddr_in *)a)->sin_addr.s_addr + == ((const struct sockaddr_in *)b)->sin_addr.s_addr; + case AF_INET6: + return !memcmp(&((const struct sockaddr_in6 *)a)->sin6_addr, + &((const struct sockaddr_in6 *)b)->sin6_addr, + sizeof (struct in6_addr)); + default: + fatal(0, "unknown address family %d", a->sa_family); + } +} + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +indent-tabs-mode:nil +End: +*/ diff --git a/lib/ifreq.h b/lib/ifreq.h new file mode 100644 index 0000000..93778d2 --- /dev/null +++ b/lib/ifreq.h @@ -0,0 +1,47 @@ +/* + * This file is part of DisOrder. + * Copyright (C) 2007 Richard Kettlewell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ +/** @file lib/ifreq.h + * @brief Network interface support + */ +#ifndef IFREQ_H +#define IFREQ_H + +struct ifreq; + +/** @brief Get the list of network interfaces + * @param fd File descriptor to use + * @param interfaces Where to put pointer to array of interfaces + * @param ninterfaces Where to put count of interfaces + */ +void ifreq_list(int fd, struct ifreq **interfaces, int *ninterfaces); + +/** @brief Return true if two socket addresses match */ +int sockaddr_equal(const struct sockaddr *a, const struct sockaddr *b); + +#endif /* IFREQ_H */ + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +indent-tabs-mode:nil +End: +*/ diff --git a/server/speaker-network.c b/server/speaker-network.c index affc1a1..6ffe929 100644 --- a/server/speaker-network.c +++ b/server/speaker-network.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "configuration.h" #include "syscalls.h" @@ -37,6 +39,7 @@ #include "addr.h" #include "timeval.h" #include "rtp.h" +#include "ifreq.h" #include "speaker-protocol.h" #include "speaker.h" @@ -99,7 +102,7 @@ static void network_init(void) { 0 }; static const int one = 1; - int sndbuf, target_sndbuf = 131072; + int sndbuf, target_sndbuf = 131072, n; socklen_t len; char *sockname, *ssockname; @@ -145,10 +148,25 @@ static void network_init(void) { default: fatal(0, "unsupported address family %d", res->ai_family); } + info("multicasting on %s", sockname); } else { - /* Presumably just broadcasting */ - if(setsockopt(bfd, SOL_SOCKET, SO_BROADCAST, &one, sizeof one) < 0) - fatal(errno, "error setting SO_BROADCAST on broadcast socket"); + struct ifreq *ifs; + int nifs; + + /* See if the address matches the broadcast address of some interface */ + ifreq_list(bfd, &ifs, &nifs); + for(n = 0; n < nifs; ++n) { + if(ioctl(bfd, SIOCGIFBRDADDR, &ifs[n]) < 0) + fatal(errno, "error calling ioctl SIOCGIFBRDADDR"); + if(sockaddr_equal(&ifs[n].ifr_broadaddr, res->ai_addr)) + break; + } + if(n < nifs) { + 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[n].ifr_name); + } else + info("unicasting on %s", sockname); } len = sizeof sndbuf; if(getsockopt(bfd, SOL_SOCKET, SO_SNDBUF, -- [mdw]