resolved: put DNS-SD records to mDNS-enabled zones.

This commit is contained in:
Dmitry Rozhkov 2017-10-04 11:34:39 +03:00
parent 6501dd31a7
commit 6db6a4642e
8 changed files with 187 additions and 0 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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) {

View file

@ -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);