Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for reflect-filter list in avahi daemon. #62

Merged
merged 10 commits into from Feb 13, 2020
1 change: 1 addition & 0 deletions avahi-core/core.h
Expand Up @@ -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 */
Expand Down
5 changes: 4 additions & 1 deletion avahi-core/iface.c
Expand Up @@ -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;
Expand Down
54 changes: 53 additions & 1 deletion avahi-core/server.c
Expand Up @@ -674,6 +674,44 @@ 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_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 */
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_debug("Reject Key [%s] iface [%d]", record->key->name, from_local_iface);
goto unref;
}
else
avahi_log_debug("Match Key [%s] iface [%d]", record->key->name, from_local_iface);
}
}

if (handle_conflict(s, i, record, cache_flush)) {
if (!from_local_iface && !avahi_record_is_link_local_address(record))
Expand All @@ -683,6 +721,7 @@ static void handle_response_packet(AvahiServer *s, AvahiDnsPacket *p, AvahiInter
}
}

unref:
avahi_record_unref(record);
}

Expand Down Expand Up @@ -1169,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;
}
}
Expand Down Expand Up @@ -1597,6 +1637,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;
Expand All @@ -1619,13 +1660,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);

Expand Down Expand Up @@ -1660,12 +1702,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;
}
Expand Down
1 change: 1 addition & 0 deletions avahi-daemon/avahi-daemon.conf
Expand Up @@ -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=
Expand Down
12 changes: 12 additions & 0 deletions avahi-daemon/main.c
Expand Up @@ -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;
Expand Down
10 changes: 10 additions & 0 deletions man/avahi-daemon.conf.5.xml.in
Expand Up @@ -327,6 +327,16 @@
enabled, avahi-daemon will forward mDNS traffic between IPv4
and IPv6, which is usually not recommended. Defaults to "no".</p>
</option>

<option>
<p><opt>reflect-filters=</opt> Set a comma separated list of
allowed service names to be reflected. Each service that is
seen must match an entry in this list to be reflected to other
networks. This list can match the type of service or the name
of the machine providing the service. Defaults to allowing all
services.</p>

</option>
</section>

<section name="Section [rlimits]">
Expand Down
7 changes: 7 additions & 0 deletions service-type-database/service-types
Expand Up @@ -140,6 +140,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
Expand Down Expand Up @@ -217,6 +218,10 @@ _adobe-vc._tcp:Adobe Version Cue

_home-sharing._tcp:Apple Home Sharing

_amzn-wplay._tcp:Amazon Fire TV

_qdiscover._tcp:QNAP NAS


# Other

Expand All @@ -233,3 +238,5 @@ _shifter._tcp:Window Shifter
_xpra._tcp:Xpra Session Server

_libvirt._tcp:Virtual Machine Manager

_device-info._tcp:Device Info