From: Mike Brady Date: Sun, 5 Feb 2017 13:47:01 +0000 (+0000) Subject: Add a new setting to specify the interface the service should be provided on. X-Git-Tag: 3.0.d23~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2cab35cd55eb30c28551927ea7a6435603763889;p=thirdparty%2Fshairport-sync.git Add a new setting to specify the interface the service should be provided on. --- diff --git a/common.h b/common.h index e15edf1a..d84de86d 100644 --- a/common.h +++ b/common.h @@ -123,6 +123,8 @@ typedef struct { char *configfile; char *regtype; // The regtype is the service type followed by the protocol, separated by a dot, by // default “_raop._tcp.”. + char *interface; // a string containg the interface name, or NULL if nothing specified + int interface_index; // only valid if the interface string is non-NULL double audio_backend_buffer_desired_length; // this will be the length in seconds of the // audio backend buffer -- the DAC buffer for ALSA double audio_backend_latency_offset; // this will be the offset in seconds to compensate for any diff --git a/mdns_avahi.c b/mdns_avahi.c index b9664674..d8fef9a9 100644 --- a/mdns_avahi.c +++ b/mdns_avahi.c @@ -204,16 +204,21 @@ static void register_service(AvahiClient *c) { return; int ret; + AvahiIfIndex selected_interface; + if (config.interface!=NULL) + selected_interface = config.interface_index; + else + selected_interface = AVAHI_IF_UNSPEC; #ifdef CONFIG_METADATA if (config.metadata_enabled) { - ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, + ret = avahi_entry_group_add_service(group, selected_interface, AVAHI_PROTO_UNSPEC, 0, name, config.regtype, NULL, NULL, port, MDNS_RECORD_WITH_METADATA, NULL); if (ret == 0) debug(1, "avahi: request to add \"%s\" service with metadata", config.regtype); } else { #endif - ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, + ret = avahi_entry_group_add_service(group, selected_interface, AVAHI_PROTO_UNSPEC, 0, name, config.regtype, NULL, NULL, port, MDNS_RECORD_WITHOUT_METADATA, NULL); if (ret == 0) diff --git a/mdns_tinysvcmdns.c b/mdns_tinysvcmdns.c index 8d51d4bf..57f41ae9 100644 --- a/mdns_tinysvcmdns.c +++ b/mdns_tinysvcmdns.c @@ -70,17 +70,21 @@ static int mdns_tinysvcmdns_register(char *apname, int port) { // Look for an ipv4/ipv6 non-loopback interface to use as the main one. for (ifa = ifalist; ifa != NULL; ifa = ifa->ifa_next) { - if (!(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) { - uint32_t main_ip = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; - - mdnsd_set_hostname(svr, hostname, main_ip); // TTL should be 120 seconds - break; - } else if (!(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_addr && - ifa->ifa_addr->sa_family == AF_INET6) { - struct in6_addr *addr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; - - mdnsd_set_hostname_v6(svr, hostname, addr); // TTL should be 120 seconds - break; + // only check for the named interface, if specified + if ((config.interface==NULL) || (strcmp(config.interface,ifa->ifa_name)==0)) { + + if (!(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) { + uint32_t main_ip = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; + + mdnsd_set_hostname(svr, hostname, main_ip); // TTL should be 120 seconds + break; + } else if (!(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_addr && + ifa->ifa_addr->sa_family == AF_INET6) { + struct in6_addr *addr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; + + mdnsd_set_hostname_v6(svr, hostname, addr); // TTL should be 120 seconds + break; + } } } @@ -92,20 +96,22 @@ static int mdns_tinysvcmdns_register(char *apname, int port) { // Skip the first one, it was already added by set_hostname for (ifa = ifa->ifa_next; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_flags & IFF_LOOPBACK) // Skip loop-back interfaces - continue; - - switch (ifa->ifa_addr->sa_family) { - case AF_INET: { // ipv4 - uint32_t ip = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; - struct rr_entry *a_e = rr_create_a(create_nlabel(hostname), ip); // TTL should be 120 seconds - mdnsd_add_rr(svr, a_e); - } break; - case AF_INET6: { // ipv6 - struct in6_addr *addr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; - struct rr_entry *aaaa_e = - rr_create_aaaa(create_nlabel(hostname), addr); // TTL should be 120 seconds - mdnsd_add_rr(svr, aaaa_e); - } break; + continue; + // only check for the named interface, if specified + if ((config.interface==NULL) || (strcmp(config.interface,ifa->ifa_name)==0)) { + switch (ifa->ifa_addr->sa_family) { + case AF_INET: { // ipv4 + uint32_t ip = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; + struct rr_entry *a_e = rr_create_a(create_nlabel(hostname), ip); // TTL should be 120 seconds + mdnsd_add_rr(svr, a_e); + } break; + case AF_INET6: { // ipv6 + struct in6_addr *addr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; + struct rr_entry *aaaa_e = + rr_create_aaaa(create_nlabel(hostname), addr); // TTL should be 120 seconds + mdnsd_add_rr(svr, aaaa_e); + } break; + } } } diff --git a/shairport.c b/shairport.c index ee69f8af..5a147005 100644 --- a/shairport.c +++ b/shairport.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "config.h" @@ -490,7 +491,45 @@ int parse_options(int argc, char **argv) { die("Invalid playback_mode choice \"%s\". It should be \"stereo\" (default), \"mono\", " "\"reverse stereo\", \"both left\", \"both right\""); } - + + + + + /* Get the interface to listen on, if specified Default is all interfaces */ + /* we keep the interface name and the index */ + + if (config_lookup_string(config.cfg, "general.interface", &str)) + config.interface = strdup(str); + + if (config_lookup_string(config.cfg, "general.interface", &str)) { + int specified_interface_found = 0; + + struct if_nameindex *if_ni, *i; + + if_ni = if_nameindex(); + if (if_ni == NULL) { + debug(1,"Can't get a list of interface names."); + } else { + for (i = if_ni; ! (i->if_index == 0 && i->if_name == NULL); i++) { + // printf("%u: %s\n", i->if_index, i->if_name); + if (strcmp(i->if_name,str)==0) { + config.interface_index = i->if_index; + specified_interface_found = 1; + } + } + + } + + if_freenameindex(if_ni); + + if (specified_interface_found==0) { + inform("The mdns service interface \"%s\" was not found, so the setting has been ignored.",config.interface); + free(config.interface); + config.interface = NULL; + config.interface_index = 0; + } + } + /* Get the regtype -- the service type and protocol, separated by a dot. Default is * "_raop._tcp" */ if (config_lookup_string(config.cfg, "general.regtype", &str)) @@ -762,7 +801,6 @@ void shairport_startup_complete(void) { const char *pid_file_proc(void) { #ifdef HAVE_ASPRINTF static char *fn = NULL; - free(fn); asprintf(&fn, "%s/%s.pid", PIDDIR, daemon_pid_file_ident ? daemon_pid_file_ident : "unknown"); #else static char fn[8192]; @@ -777,6 +815,7 @@ const char *pid_file_proc(void) { void exit_function() { if (config.cfg) config_destroy(config.cfg); + // probably should be freeing malloc'ed memory here, including strdup-created strings... } int main(int argc, char **argv) { @@ -1146,7 +1185,10 @@ int main(int argc, char **argv) { debug(1, "zeroconf regtype is \"%s\".", config.regtype); debug(1, "decoders_supported field is %d.", config.decoders_supported); debug(1, "use_apple_decoder is %d.", config.use_apple_decoder); - + if (config.interface) + debug(1, "mdns service interface \"%s\" requested.",config.interface); + else + debug(1, "no special mdns service interface was requested."); char *realConfigPath = realpath(config.configfile, NULL); if (realConfigPath) { debug(1, "configuration file name \"%s\" resolves to \"%s\".", config.configfile,