From: Dmitry Rozhkov Date: Wed, 4 Oct 2017 08:34:39 +0000 (+0300) Subject: resolved: put DNS-SD records to mDNS-enabled zones. X-Git-Tag: v236~33^2~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6db6a4642ebd202fda2d8cffeb0b8bd62ed043e2;p=thirdparty%2Fsystemd.git resolved: put DNS-SD records to mDNS-enabled zones. --- diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index a9071ee73e3..5b7ac0ea252 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -27,6 +27,7 @@ #include "hostname-util.h" #include "missing.h" #include "random-util.h" +#include "resolved-dnssd.h" #include "resolved-dns-scope.h" #include "resolved-llmnr.h" #include "resolved-mdns.h" @@ -1123,3 +1124,58 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) { return 0; } + +int dns_scope_add_dnssd_services(DnsScope *scope) { + Iterator i; + DnssdService *service; + int r; + + assert(scope); + + if (hashmap_size(scope->manager->dnssd_services) == 0) + return 0; + + scope->announced = false; + + HASHMAP_FOREACH(service, scope->manager->dnssd_services, i) { + r = dns_zone_put(&scope->zone, scope, service->ptr_rr, false); + if (r < 0) + log_warning_errno(r, "Failed to add PTR record to MDNS zone: %m"); + + r = dns_zone_put(&scope->zone, scope, service->srv_rr, true); + if (r < 0) + log_warning_errno(r, "Failed to add SRV record to MDNS zone: %m"); + + r = dns_zone_put(&scope->zone, scope, service->txt_rr, true); + if (r < 0) + log_warning_errno(r, "Failed to add TXT record to MDNS zone: %m"); + } + + return 0; +} + +int dns_scope_remove_dnssd_services(DnsScope *scope) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + Iterator i; + DnssdService *service; + int r; + + assert(scope); + + key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_PTR, + "_services._dns-sd._udp.local"); + if (!key) + return log_oom(); + + r = dns_zone_remove_rrs_by_key(&scope->zone, key); + if (r < 0) + return r; + + HASHMAP_FOREACH(service, scope->manager->dnssd_services, i) { + dns_zone_remove_rr(&scope->zone, service->ptr_rr); + dns_zone_remove_rr(&scope->zone, service->srv_rr); + dns_zone_remove_rr(&scope->zone, service->txt_rr); + } + + return 0; +} diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h index d3da8e54ea3..d46ccd884ce 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -119,3 +119,7 @@ bool dns_scope_network_good(DnsScope *s); int dns_scope_ifindex(DnsScope *s); int dns_scope_announce(DnsScope *scope, bool goodbye); + +int dns_scope_add_dnssd_services(DnsScope *scope); + +int dns_scope_remove_dnssd_services(DnsScope *scope); diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c index 2c32bb4d4fb..8080c3e7a1a 100644 --- a/src/resolve/resolved-dns-zone.c +++ b/src/resolve/resolved-dns-zone.c @@ -119,6 +119,22 @@ void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr) { dns_zone_item_remove_and_free(z, i); } +int dns_zone_remove_rrs_by_key(DnsZone *z, DnsResourceKey *key) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL; + DnsResourceRecord *rr; + bool tentative; + int r; + + r = dns_zone_lookup(z, key, 0, &answer, &soa, &tentative); + if (r < 0) + return r; + + DNS_ANSWER_FOREACH(rr, answer) + dns_zone_remove_rr(z, rr); + + return 0; +} + static int dns_zone_init(DnsZone *z) { int r; diff --git a/src/resolve/resolved-dns-zone.h b/src/resolve/resolved-dns-zone.h index f654537b45c..55702fb8401 100644 --- a/src/resolve/resolved-dns-zone.h +++ b/src/resolve/resolved-dns-zone.h @@ -68,6 +68,7 @@ void dns_zone_flush(DnsZone *z); int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe); void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr); +int dns_zone_remove_rrs_by_key(DnsZone *z, DnsResourceKey *key); int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, int ifindex, DnsAnswer **answer, DnsAnswer **soa, bool *tentative); diff --git a/src/resolve/resolved-dnssd.c b/src/resolve/resolved-dnssd.c index e025a534944..f565460e9c0 100644 --- a/src/resolve/resolved-dnssd.c +++ b/src/resolve/resolved-dnssd.c @@ -119,6 +119,10 @@ static int dnssd_service_load(Manager *manager, const char *filename) { service->manager = manager; + r = dnssd_update_rrs(service); + if (r < 0) + return r; + service = NULL; return 0; @@ -192,6 +196,73 @@ int dnssd_load(Manager *manager) { return 0; } +int dnssd_update_rrs(DnssdService *s) { + _cleanup_free_ char *n = NULL; + _cleanup_free_ char *service_name = NULL; + _cleanup_free_ char *full_name = NULL; + int r; + + assert(s); + assert(s->txt); + assert(s->manager); + + s->ptr_rr = dns_resource_record_unref(s->ptr_rr); + s->srv_rr = dns_resource_record_unref(s->srv_rr); + s->txt_rr = dns_resource_record_unref(s->txt_rr); + + r = dnssd_render_instance_name(s, &n); + if (r < 0) + return r; + + r = dns_name_concat(s->type, "local", &service_name); + if (r < 0) + return r; + r = dns_name_concat(n, service_name, &full_name); + if (r < 0) + return r; + + s->txt_rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_TXT, + full_name); + if (!s->txt_rr) + goto oom; + + s->txt_rr->ttl = MDNS_DEFAULT_TTL; + s->txt_rr->txt.items = dns_txt_item_copy(s->txt); + if (!s->txt_rr->txt.items) + goto oom; + + s->ptr_rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, + service_name); + if (!s->ptr_rr) + goto oom; + + s->ptr_rr->ttl = MDNS_DEFAULT_TTL; + s->ptr_rr->ptr.name = strdup(full_name); + if (!s->ptr_rr->ptr.name) + goto oom; + + s->srv_rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SRV, + full_name); + if (!s->srv_rr) + goto oom; + + s->srv_rr->ttl = MDNS_DEFAULT_TTL; + s->srv_rr->srv.priority = s->priority; + s->srv_rr->srv.weight = s->weight; + s->srv_rr->srv.port = s->port; + s->srv_rr->srv.name = strdup(s->manager->mdns_hostname); + if (!s->srv_rr->srv.name) + goto oom; + + return 0; + +oom: + s->txt_rr = dns_resource_record_unref(s->txt_rr); + s->ptr_rr = dns_resource_record_unref(s->ptr_rr); + s->srv_rr = dns_resource_record_unref(s->srv_rr); + return -ENOMEM; +} + int dnssd_txt_item_new_from_string(const char *key, const char *value, DnsTxtItem **ret_item) { size_t length; DnsTxtItem *i; diff --git a/src/resolve/resolved-dnssd.h b/src/resolve/resolved-dnssd.h index 0c0e1cddc07..b723698d3aa 100644 --- a/src/resolve/resolved-dnssd.h +++ b/src/resolve/resolved-dnssd.h @@ -55,3 +55,4 @@ int dnssd_render_instance_name(DnssdService *s, char **ret_name); int dnssd_load(Manager *manager); int dnssd_txt_item_new_from_string(const char *key, const char *value, DnsTxtItem **ret_item); int dnssd_txt_item_new_from_data(const char *key, const void *value, const size_t size, DnsTxtItem **ret_item); +int dnssd_update_rrs(DnssdService *s); diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index a0128aace0a..ed7bdc848af 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -191,9 +191,41 @@ void link_allocate_scopes(Link *l) { void link_add_rrs(Link *l, bool force_remove) { LinkAddress *a; + int r; LIST_FOREACH(addresses, a, l->addresses) link_address_add_rrs(a, force_remove); + + if (!force_remove && + l->mdns_support == RESOLVE_SUPPORT_YES && + l->manager->mdns_support == RESOLVE_SUPPORT_YES) { + + if (l->mdns_ipv4_scope) { + r = dns_scope_add_dnssd_services(l->mdns_ipv4_scope); + if (r < 0) + log_warning_errno(r, "Failed to add IPv4 DNS-SD services: %m"); + } + + if (l->mdns_ipv6_scope) { + r = dns_scope_add_dnssd_services(l->mdns_ipv6_scope); + if (r < 0) + log_warning_errno(r, "Failed to add IPv6 DNS-SD services: %m"); + } + + } else { + + if (l->mdns_ipv4_scope) { + r = dns_scope_remove_dnssd_services(l->mdns_ipv4_scope); + if (r < 0) + log_warning_errno(r, "Failed to remove IPv4 DNS-SD services: %m"); + } + + if (l->mdns_ipv6_scope) { + r = dns_scope_remove_dnssd_services(l->mdns_ipv6_scope); + if (r < 0) + log_warning_errno(r, "Failed to remove IPv6 DNS-SD services: %m"); + } + } } int link_process_rtnl(Link *l, sd_netlink_message *m) { diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 91bed0a3795..2813f6ee402 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -1104,6 +1104,7 @@ int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_a void manager_refresh_rrs(Manager *m) { Iterator i; Link *l; + DnssdService *s; assert(m); @@ -1112,6 +1113,11 @@ void manager_refresh_rrs(Manager *m) { m->mdns_host_ipv4_key = dns_resource_key_unref(m->mdns_host_ipv4_key); m->mdns_host_ipv6_key = dns_resource_key_unref(m->mdns_host_ipv6_key); + if (m->mdns_support == RESOLVE_SUPPORT_YES) + HASHMAP_FOREACH(s, m->dnssd_services, i) + if (dnssd_update_rrs(s) < 0) + log_warning("Failed to refresh DNS-SD service '%s'", s->name); + HASHMAP_FOREACH(l, m->links, i) { link_add_rrs(l, true); link_add_rrs(l, false);