]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Add a new setting to specify the interface the service should be provided on.
authorMike Brady <mikebrady@eircom.net>
Sun, 5 Feb 2017 13:47:01 +0000 (13:47 +0000)
committerMike Brady <mikebrady@eircom.net>
Sun, 5 Feb 2017 13:47:01 +0000 (13:47 +0000)
common.h
mdns_avahi.c
mdns_tinysvcmdns.c
shairport.c

index e15edf1ae12bfcb1c9f19cc661561399d6c84d6a..d84de86d922a0b090642288587e507dbf8fc6b08 100644 (file)
--- 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
index b96646743b58380d9ae108314931eae024e089f5..d8fef9a9788c75ec3a70132a08358c1c8210be31 100644 (file)
@@ -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)
index 8d51d4bf427cc9c2279fbbb703cbd9a55eb2f869..57f41ae96d2450107da18a38f06197b993c0f563 100644 (file)
@@ -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;
+      }
     }
   }
 
index ee69f8afca9b51d07e381ed9a035c33e15bab8ac..5a14700581da407857e4d89c08602411ebd6a23e 100644 (file)
@@ -38,6 +38,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <net/if.h>
 #include <unistd.h>
 
 #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,