From d195ac7ddd53ac457c282581783ef5cd756b9608 Mon Sep 17 00:00:00 2001 From: David Kerr Date: Sat, 2 Jul 2016 14:05:24 -0400 Subject: [PATCH 1/7] Add service types to database for audio streaming, device info, amazon fire and qnap nas devices. --- service-type-database/service-types | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/service-type-database/service-types b/service-type-database/service-types index 6e7e2cd98..4bbf52a3f 100644 --- a/service-type-database/service-types +++ b/service-type-database/service-types @@ -139,6 +139,7 @@ _realplayfavs._tcp:RealPlayer Shared Favorites _realplayfavs._tcp[it]:RealPlayer - Preferiti Condivisi _raop._tcp:AirTunes Remote Audio +_airplay._tcp:AirPlay Remote Video _rtsp._tcp:RTSP Realtime Streaming Server _rtp._udp:RTP Realtime Streaming Server @@ -216,6 +217,10 @@ _adobe-vc._tcp:Adobe Version Cue _home-sharing._tcp:Apple Home Sharing +_amzn-wplay._tcp:Amazon Fire TV + +_qdiscover._tcp:QNAP NAS + # Other @@ -231,3 +236,6 @@ _tp-https._tcp:Thousand Parsec Server (Secure HTTP Tunnel) _shifter._tcp:Window Shifter _libvirt._tcp:Virtual Machine Manager + +_device-info._tcp:Device Info + From d9caeb59739c4e8af6b0dfbffff8e4ed365d3beb Mon Sep 17 00:00:00 2001 From: David Kerr Date: Sat, 2 Jul 2016 18:14:24 -0400 Subject: [PATCH 2/7] Adds support for filtering reflector advertisements This enhancement is provided courtesy of James Rudd and http://jrudd.org/2014/08/avahi-reflector-filtering-patch/ Allows Avahi-Daemon to filter which advertisements are added to the cache to be reflected to different networks. It checks incoming service names against a list defined in avahi-daemon.conf [reflector] reflect-filters. The list can be types of services or can contain hostnames to match. For example if we only allow AirPlay and AirTunes to be reflected between VLANs, so have "_airplay._tcp.local,_raop._tcp.local" set. For AirPrint set "_printer._tcp.local,_ipp._tcp.local,_pdl-datastream._tcp.local" Remember to set firewall to permit traffic between LANs for the corresponding ports. The patch will block the PTR and SRV advertisements but will still allow A records for machine name lookup. All locally published services are still published even if they do not match the filter. The filter also blocks local programs from seeing advertised programs so it is recommend to only enable it on a dedicated bonjour reflector server. --- avahi-core/core.h | 1 + avahi-core/server.c | 48 ++++++++++++++++++++++++++++- avahi-daemon/avahi-daemon.conf | 1 + avahi-daemon/main.c | 12 ++++++++ man/avahi-daemon.conf.5.xml.in | 10 ++++++ service-type-database/service-types | 1 - 6 files changed, 71 insertions(+), 2 deletions(-) diff --git a/avahi-core/core.h b/avahi-core/core.h index f50c6128a..1ebd27a00 100644 --- a/avahi-core/core.h +++ b/avahi-core/core.h @@ -56,6 +56,7 @@ typedef struct AvahiServerConfig { int use_iff_running; /**< Require IFF_RUNNING on local network interfaces. This is the official way to check for link beat. Unfortunately this doesn't work with all drivers. So bettere leave this off. */ int enable_reflector; /**< Reflect incoming mDNS traffic to all local networks. This allows mDNS based network browsing beyond ethernet borders */ int reflect_ipv; /**< if enable_reflector is 1, enable/disable reflecting between IPv4 and IPv6 */ + AvahiStringList *reflect_filters; /**< if enable_reflector is 1, will only add services containing one of these strings */ int add_service_cookie; /**< Add magic service cookie to all locally generated records implicitly */ int enable_wide_area; /**< Enable wide area support */ AvahiAddress wide_area_servers[AVAHI_WIDE_AREA_SERVERS_MAX]; /** Unicast DNS server to use for wide area lookup */ diff --git a/avahi-core/server.c b/avahi-core/server.c index a2cb19a83..1a91907dd 100644 --- a/avahi-core/server.c +++ b/avahi-core/server.c @@ -674,6 +674,40 @@ static void handle_response_packet(AvahiServer *s, AvahiDnsPacket *p, AvahiInter } if (!avahi_key_is_pattern(record->key)) { + // Filter services that will be cached. Allow all local services + if (!from_local_iface && s->config.enable_reflector && s->config.reflect_filters != NULL){ + AvahiStringList *l; + int match = 0; + + if (record->key->type == AVAHI_DNS_TYPE_PTR){ + // Need to match DNS pointer target with filter + for (l = s->config.reflect_filters; l; l = l->next) { + if (strstr( record->data.ptr.name, (char*) l->text) != NULL) { + match = 1; + break; + } + } + + if (! match){ + //avahi_log_info("Reject Ptr SRC [%s] Dest [%s]", record->key->name, record->data.ptr.name); + return; + } + } + else if (record->key->type == AVAHI_DNS_TYPE_SRV || record->key->type == AVAHI_DNS_TYPE_TXT){ + // Need to match key name with filter + for (l = s->config.reflect_filters; l; l = l->next) { + if (strstr( record->key->name, (char*) l->text) != NULL) { + match = 1; + break; + } + } + + if (! match){ + //avahi_log_info("Reject Key [%s] iface [%d]", record->key->name, from_local_iface); + return; + } + } + } if (handle_conflict(s, i, record, cache_flush)) { if (!from_local_iface && !avahi_record_is_link_local_address(record)) @@ -1589,6 +1623,7 @@ AvahiServerConfig* avahi_server_config_init(AvahiServerConfig *c) { c->use_iff_running = 0; c->enable_reflector = 0; c->reflect_ipv = 0; + c->reflect_filters = NULL; c->add_service_cookie = 0; c->enable_wide_area = 0; c->n_wide_area_servers = 0; @@ -1611,13 +1646,14 @@ void avahi_server_config_free(AvahiServerConfig *c) { avahi_free(c->host_name); avahi_free(c->domain_name); avahi_string_list_free(c->browse_domains); + avahi_string_list_free(c->reflect_filters); avahi_string_list_free(c->allow_interfaces); avahi_string_list_free(c->deny_interfaces); } AvahiServerConfig* avahi_server_config_copy(AvahiServerConfig *ret, const AvahiServerConfig *c) { char *d = NULL, *h = NULL; - AvahiStringList *browse = NULL, *allow = NULL, *deny = NULL; + AvahiStringList *browse = NULL, *allow = NULL, *deny = NULL, *reflect = NULL ; assert(ret); assert(c); @@ -1652,12 +1688,22 @@ AvahiServerConfig* avahi_server_config_copy(AvahiServerConfig *ret, const AvahiS return NULL; } + if (!(reflect = avahi_string_list_copy(c->reflect_filters)) && c->reflect_filters) { + avahi_string_list_free(allow); + avahi_string_list_free(browse); + avahi_string_list_free(deny); + avahi_free(h); + avahi_free(d); + return NULL; + } + *ret = *c; ret->host_name = h; ret->domain_name = d; ret->browse_domains = browse; ret->allow_interfaces = allow; ret->deny_interfaces = deny; + ret->reflect_filters = reflect; return ret; } diff --git a/avahi-daemon/avahi-daemon.conf b/avahi-daemon/avahi-daemon.conf index 95166f802..2c6c1fcc5 100644 --- a/avahi-daemon/avahi-daemon.conf +++ b/avahi-daemon/avahi-daemon.conf @@ -57,6 +57,7 @@ publish-workstation=no [reflector] #enable-reflector=no #reflect-ipv=no +#reflect-filters=_airplay._tcp.local,_raop._tcp.local [rlimits] #rlimit-as= diff --git a/avahi-daemon/main.c b/avahi-daemon/main.c index 10cb41e7e..346338fb9 100644 --- a/avahi-daemon/main.c +++ b/avahi-daemon/main.c @@ -826,6 +826,18 @@ static int load_config_file(DaemonConfig *c) { c->server_config.enable_reflector = is_yes(p->value); else if (strcasecmp(p->key, "reflect-ipv") == 0) c->server_config.reflect_ipv = is_yes(p->value); + else if (strcasecmp(p->key, "reflect-filters") == 0) { + char **e, **t; + + avahi_string_list_free(c->server_config.reflect_filters); + c->server_config.reflect_filters = NULL; + e = avahi_split_csv(p->value); + + for (t = e; *t; t++) + c->server_config.reflect_filters = avahi_string_list_add(c->server_config.reflect_filters, *t); + + avahi_strfreev(e); + } else { avahi_log_error("Invalid configuration key \"%s\" in group \"%s\"\n", p->key, g->name); goto finish; diff --git a/man/avahi-daemon.conf.5.xml.in b/man/avahi-daemon.conf.5.xml.in index 2d15017a1..dd91e60d3 100644 --- a/man/avahi-daemon.conf.5.xml.in +++ b/man/avahi-daemon.conf.5.xml.in @@ -327,6 +327,16 @@ enabled, avahi-daemon will forward mDNS traffic between IPv4 and IPv6, which is usually not recommended. Defaults to "no".

+ +
diff --git a/service-type-database/service-types b/service-type-database/service-types index 4bbf52a3f..0b99d403f 100644 --- a/service-type-database/service-types +++ b/service-type-database/service-types @@ -238,4 +238,3 @@ _shifter._tcp:Window Shifter _libvirt._tcp:Virtual Machine Manager _device-info._tcp:Device Info - From c8723de8100cac0449514e095caa45eb6af416c6 Mon Sep 17 00:00:00 2001 From: David Kerr Date: Sun, 3 Jul 2016 21:46:11 -0400 Subject: [PATCH 3/7] Uncommented the info messages and changed them to debug messages. Added debug message for matches as well as rejects. I have found that it is extremely useful to see what mDNS-SD messages are matched or rejected in order to debug service discovery and therefore it is best if these messages can be turned on with the --debug flag as necessary. --- avahi-core/server.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/avahi-core/server.c b/avahi-core/server.c index 1a91907dd..018429ccf 100644 --- a/avahi-core/server.c +++ b/avahi-core/server.c @@ -689,9 +689,11 @@ static void handle_response_packet(AvahiServer *s, AvahiDnsPacket *p, AvahiInter } if (! match){ - //avahi_log_info("Reject Ptr SRC [%s] Dest [%s]", record->key->name, record->data.ptr.name); + avahi_log_debug("Reject Ptr SRC [%s] Dest [%s]", record->key->name, record->data.ptr.name); return; } + else + avahi_log_debug("Match Ptr SRC [%s] Dest [%s]", record->key->name, record->data.ptr.name); } else if (record->key->type == AVAHI_DNS_TYPE_SRV || record->key->type == AVAHI_DNS_TYPE_TXT){ // Need to match key name with filter @@ -703,9 +705,11 @@ static void handle_response_packet(AvahiServer *s, AvahiDnsPacket *p, AvahiInter } if (! match){ - //avahi_log_info("Reject Key [%s] iface [%d]", record->key->name, from_local_iface); + avahi_log_debug("Reject Key [%s] iface [%d]", record->key->name, from_local_iface); return; } + else + avahi_log_debug("Match Key [%s] iface [%d]", record->key->name, from_local_iface); } } From 2e42c6416327c256ab70940c7341caf3830d5c24 Mon Sep 17 00:00:00 2001 From: David Kerr Date: Fri, 24 Feb 2017 23:43:33 -0500 Subject: [PATCH 4/7] suppress warning message that avahi_server_add_address() failed when disable-publishing=yes is set in conf file. Fixes lathiat/avahi issue #38 --- avahi-core/iface.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/avahi-core/iface.c b/avahi-core/iface.c index 39a860ae7..a68a4b900 100644 --- a/avahi-core/iface.c +++ b/avahi-core/iface.c @@ -74,7 +74,10 @@ void avahi_interface_address_update_rrs(AvahiInterfaceAddress *a, int remove_rrs avahi_log_info("Registering new address record for %s on %s.%s.", t, a->interface->hardware->name, p == AVAHI_PROTO_UNSPEC ? "*" : avahi_proto_to_string(p)); if (avahi_server_add_address(m->server, a->entry_group, a->interface->hardware->index, p, 0, NULL, &a->address) < 0) { - avahi_log_warn(__FILE__": avahi_server_add_address() failed: %s", avahi_strerror(m->server->error)); + if (!m->server->config.disable_publishing || m->server->error != AVAHI_ERR_NOT_PERMITTED) { + /* suppress warning if disable_publishing set as this is expected state */ + avahi_log_warn(__FILE__": avahi_server_add_address() failed: %s", avahi_strerror(m->server->error)); + } avahi_s_entry_group_free(a->entry_group); a->entry_group = NULL; return; From 659a7df2c51b2c4dbf227c465ea89ef52ec54432 Mon Sep 17 00:00:00 2001 From: wisd0me Date: Wed, 25 Sep 2019 15:38:21 +0700 Subject: [PATCH 5/7] reflect-filters logic bugfix This commit fixes the bug, when there is multiple records in the response (usually there are), and first record does not correspond to any of the configured services - originally, packet was getting dropped. With this fix current record is skipped, and the code looks further. --- avahi-core/server.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/avahi-core/server.c b/avahi-core/server.c index 018429ccf..622658f39 100644 --- a/avahi-core/server.c +++ b/avahi-core/server.c @@ -690,7 +690,7 @@ static void handle_response_packet(AvahiServer *s, AvahiDnsPacket *p, AvahiInter if (! match){ avahi_log_debug("Reject Ptr SRC [%s] Dest [%s]", record->key->name, record->data.ptr.name); - return; + goto unref; } else avahi_log_debug("Match Ptr SRC [%s] Dest [%s]", record->key->name, record->data.ptr.name); @@ -706,7 +706,7 @@ static void handle_response_packet(AvahiServer *s, AvahiDnsPacket *p, AvahiInter if (! match){ avahi_log_debug("Reject Key [%s] iface [%d]", record->key->name, from_local_iface); - return; + goto unref; } else avahi_log_debug("Match Key [%s] iface [%d]", record->key->name, from_local_iface); @@ -721,6 +721,7 @@ static void handle_response_packet(AvahiServer *s, AvahiDnsPacket *p, AvahiInter } } + unref: avahi_record_unref(record); } From 6dabb000cc4206ecbf30d016c0a4625c5eae2930 Mon Sep 17 00:00:00 2001 From: wisd0me Date: Wed, 25 Sep 2019 15:51:53 +0700 Subject: [PATCH 6/7] formatting fixed --- avahi-core/server.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/avahi-core/server.c b/avahi-core/server.c index 622658f39..7dcfb7b14 100644 --- a/avahi-core/server.c +++ b/avahi-core/server.c @@ -674,37 +674,37 @@ static void handle_response_packet(AvahiServer *s, AvahiDnsPacket *p, AvahiInter } if (!avahi_key_is_pattern(record->key)) { - // Filter services that will be cached. Allow all local services - if (!from_local_iface && s->config.enable_reflector && s->config.reflect_filters != NULL){ + /* Filter services that will be cached. Allow all local services */ + if (!from_local_iface && s->config.enable_reflector && s->config.reflect_filters != NULL) { AvahiStringList *l; int match = 0; - if (record->key->type == AVAHI_DNS_TYPE_PTR){ - // Need to match DNS pointer target with filter + if (record->key->type == AVAHI_DNS_TYPE_PTR) { + /* Need to match DNS pointer target with filter */ for (l = s->config.reflect_filters; l; l = l->next) { - if (strstr( record->data.ptr.name, (char*) l->text) != NULL) { + if (strstr(record->data.ptr.name, (char*) l->text) != NULL) { match = 1; break; } } - if (! match){ + if (!match) { avahi_log_debug("Reject Ptr SRC [%s] Dest [%s]", record->key->name, record->data.ptr.name); goto unref; } else avahi_log_debug("Match Ptr SRC [%s] Dest [%s]", record->key->name, record->data.ptr.name); } - else if (record->key->type == AVAHI_DNS_TYPE_SRV || record->key->type == AVAHI_DNS_TYPE_TXT){ - // Need to match key name with filter + else if (record->key->type == AVAHI_DNS_TYPE_SRV || record->key->type == AVAHI_DNS_TYPE_TXT) { + /* Need to match key name with filter */ for (l = s->config.reflect_filters; l; l = l->next) { - if (strstr( record->key->name, (char*) l->text) != NULL) { + if (strstr(record->key->name, (char*) l->text) != NULL) { match = 1; break; } } - if (! match){ + if (!match) { avahi_log_debug("Reject Key [%s] iface [%d]", record->key->name, from_local_iface); goto unref; } From 0538cf4c483edd01fecf6287109dbf9e538dd7d5 Mon Sep 17 00:00:00 2001 From: David Kerr Date: Thu, 26 Sep 2019 08:39:34 -0400 Subject: [PATCH 7/7] bugfix free avahi record before returning from function. --- avahi-core/server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/avahi-core/server.c b/avahi-core/server.c index 250af412b..cbb389f53 100644 --- a/avahi-core/server.c +++ b/avahi-core/server.c @@ -1208,6 +1208,7 @@ static void register_hinfo(AvahiServer *s) { if (avahi_server_add(s, s->hinfo_entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_PUBLISH_UNIQUE, r) < 0) { avahi_log_warn("Failed to add HINFO RR: %s", avahi_strerror(s->error)); + avahi_record_unref(r); return; } }