summaryrefslogtreecommitdiffstats
path: root/src/resolve/resolved-dnssd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/resolve/resolved-dnssd.c')
-rw-r--r--src/resolve/resolved-dnssd.c116
1 files changed, 79 insertions, 37 deletions
diff --git a/src/resolve/resolved-dnssd.c b/src/resolve/resolved-dnssd.c
index 994771e..5f66e3c 100644
--- a/src/resolve/resolved-dnssd.c
+++ b/src/resolve/resolved-dnssd.c
@@ -3,10 +3,11 @@
#include "conf-files.h"
#include "conf-parser.h"
#include "constants.h"
-#include "resolved-dnssd.h"
+#include "path-util.h"
+#include "resolved-conf.h"
#include "resolved-dns-rr.h"
+#include "resolved-dnssd.h"
#include "resolved-manager.h"
-#include "resolved-conf.h"
#include "specifier.h"
#include "strv.h"
@@ -40,55 +41,81 @@ DnssdService *dnssd_service_free(DnssdService *service) {
return NULL;
if (service->manager)
- hashmap_remove(service->manager->dnssd_services, service->name);
+ hashmap_remove(service->manager->dnssd_services, service->id);
dns_resource_record_unref(service->ptr_rr);
+ dns_resource_record_unref(service->sub_ptr_rr);
dns_resource_record_unref(service->srv_rr);
dnssd_txtdata_free_all(service->txt_data_items);
- free(service->filename);
- free(service->name);
+ free(service->path);
+ free(service->id);
free(service->type);
+ free(service->subtype);
free(service->name_template);
return mfree(service);
}
-static int dnssd_service_load(Manager *manager, const char *filename) {
+void dnssd_service_clear_on_reload(Hashmap *services) {
+ DnssdService *service;
+
+ HASHMAP_FOREACH(service, services)
+ if (service->config_source == RESOLVE_CONFIG_SOURCE_FILE) {
+ hashmap_remove(services, service->id);
+ dnssd_service_free(service);
+ }
+}
+
+static int dnssd_id_from_path(const char *path, char **ret_id) {
+ int r;
+
+ assert(path);
+ assert(ret_id);
+
+ _cleanup_free_ char *fn = NULL;
+ r = path_extract_filename(path, &fn);
+ if (r < 0)
+ return r;
+
+ char *d = endswith(fn, ".dnssd");
+ if (!d)
+ return -EINVAL;
+
+ *d = '\0';
+
+ *ret_id = TAKE_PTR(fn);
+ return 0;
+}
+
+static int dnssd_service_load(Manager *manager, const char *path) {
_cleanup_(dnssd_service_freep) DnssdService *service = NULL;
_cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
- char *d;
- const char *dropin_dirname;
+ _cleanup_free_ char *dropin_dirname = NULL;
int r;
assert(manager);
- assert(filename);
+ assert(path);
service = new0(DnssdService, 1);
if (!service)
return log_oom();
- service->filename = strdup(filename);
- if (!service->filename)
+ service->path = strdup(path);
+ if (!service->path)
return log_oom();
- service->name = strdup(basename(filename));
- if (!service->name)
- return log_oom();
-
- d = endswith(service->name, ".dnssd");
- if (!d)
- return -EINVAL;
-
- assert(streq(d, ".dnssd"));
-
- *d = '\0';
+ r = dnssd_id_from_path(path, &service->id);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extract DNS-SD service id from filename: %m");
- dropin_dirname = strjoina(service->name, ".dnssd.d");
+ dropin_dirname = strjoin(service->id, ".dnssd.d");
+ if (!dropin_dirname)
+ return log_oom();
r = config_parse_many(
- STRV_MAKE_CONST(filename), DNSSD_SERVICE_DIRS, dropin_dirname, /* root = */ NULL,
+ STRV_MAKE_CONST(path), DNSSD_SERVICE_DIRS, dropin_dirname, /* root = */ NULL,
"Service\0",
config_item_perf_lookup, resolved_dnssd_gperf_lookup,
CONFIG_PARSE_WARN,
@@ -101,12 +128,12 @@ static int dnssd_service_load(Manager *manager, const char *filename) {
if (!service->name_template)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s doesn't define service instance name",
- service->name);
+ service->id);
if (!service->type)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s doesn't define service type",
- service->name);
+ service->id);
if (!service->txt_data_items) {
txt_data = new0(DnssdTxtData, 1);
@@ -121,7 +148,7 @@ static int dnssd_service_load(Manager *manager, const char *filename) {
TAKE_PTR(txt_data);
}
- r = hashmap_ensure_put(&manager->dnssd_services, &string_hash_ops, service->name, service);
+ r = hashmap_ensure_put(&manager->dnssd_services, &string_hash_ops, service->id, service);
if (r < 0)
return r;
@@ -138,16 +165,10 @@ static int dnssd_service_load(Manager *manager, const char *filename) {
static int specifier_dnssd_hostname(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
const Manager *m = ASSERT_PTR(userdata);
- char *n;
assert(m->llmnr_hostname);
- n = strdup(m->llmnr_hostname);
- if (!n)
- return -ENOMEM;
-
- *ret = n;
- return 0;
+ return strdup_to(ret, m->llmnr_hostname);
}
int dnssd_render_instance_name(Manager *m, DnssdService *s, char **ret) {
@@ -208,7 +229,7 @@ int dnssd_load(Manager *manager) {
}
int dnssd_update_rrs(DnssdService *s) {
- _cleanup_free_ char *n = NULL, *service_name = NULL, *full_name = NULL;
+ _cleanup_free_ char *n = NULL, *service_name = NULL, *full_name = NULL, *sub_name = NULL, *selective_name = NULL;
int r;
assert(s);
@@ -216,6 +237,7 @@ int dnssd_update_rrs(DnssdService *s) {
assert(s->manager);
s->ptr_rr = dns_resource_record_unref(s->ptr_rr);
+ s->sub_ptr_rr = dns_resource_record_unref(s->sub_ptr_rr);
s->srv_rr = dns_resource_record_unref(s->srv_rr);
LIST_FOREACH(items, txt_data, s->txt_data_items)
txt_data->rr = dns_resource_record_unref(txt_data->rr);
@@ -230,6 +252,14 @@ int dnssd_update_rrs(DnssdService *s) {
r = dns_name_concat(n, service_name, 0, &full_name);
if (r < 0)
return r;
+ if (s->subtype) {
+ r = dns_name_concat("_sub", service_name, 0, &sub_name);
+ if (r < 0)
+ return r;
+ r = dns_name_concat(s->subtype, sub_name, 0, &selective_name);
+ if (r < 0)
+ return r;
+ }
LIST_FOREACH(items, txt_data, s->txt_data_items) {
txt_data->rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_TXT,
@@ -253,6 +283,17 @@ int dnssd_update_rrs(DnssdService *s) {
if (!s->ptr_rr->ptr.name)
goto oom;
+ if (selective_name) {
+ s->sub_ptr_rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, selective_name);
+ if (!s->sub_ptr_rr)
+ goto oom;
+
+ s->sub_ptr_rr->ttl = MDNS_DEFAULT_TTL;
+ s->sub_ptr_rr->ptr.name = strdup(full_name);
+ if (!s->sub_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)
@@ -272,6 +313,7 @@ oom:
LIST_FOREACH(items, txt_data, s->txt_data_items)
txt_data->rr = dns_resource_record_unref(txt_data->rr);
s->ptr_rr = dns_resource_record_unref(s->ptr_rr);
+ s->sub_ptr_rr = dns_resource_record_unref(s->sub_ptr_rr);
s->srv_rr = dns_resource_record_unref(s->srv_rr);
return -ENOMEM;
}
@@ -337,12 +379,12 @@ int dnssd_signal_conflict(Manager *manager, const char *name) {
if (s->withdrawn)
continue;
- if (dns_name_equal(dns_resource_key_name(s->srv_rr->key), name)) {
+ if (dns_name_equal(dns_resource_key_name(s->srv_rr->key), name) > 0) {
_cleanup_free_ char *path = NULL;
s->withdrawn = true;
- r = sd_bus_path_encode("/org/freedesktop/resolve1/dnssd", s->name, &path);
+ r = sd_bus_path_encode("/org/freedesktop/resolve1/dnssd", s->id, &path);
if (r < 0)
return log_error_errno(r, "Can't get D-BUS object path: %m");