summaryrefslogtreecommitdiffstats
path: root/src/resolve
diff options
context:
space:
mode:
authorDmitry Rozhkov <dmitry.rozhkov@linux.intel.com>2017-10-31 08:47:37 +0100
committerDmitry Rozhkov <dmitry.rozhkov@linux.intel.com>2017-12-08 13:29:27 +0100
commite7c1b0e4566a7f1dd24ff0a580161f5c6435f811 (patch)
tree2e7f21df1ca8a06932464a9f9a1b6d331a2db30b /src/resolve
parentresolved: don't check conflicts for DNS-SD enumeration RRs (diff)
downloadsystemd-e7c1b0e4566a7f1dd24ff0a580161f5c6435f811.tar.xz
systemd-e7c1b0e4566a7f1dd24ff0a580161f5c6435f811.zip
resolved: resolve possible conflicts for DNS-SD RRs
It might happen that a DNS-SD service doesn't include local host's name in its RR keys and still conflicts with a remote service. In this case try to resolve the conflict by changing name for this particular service.
Diffstat (limited to 'src/resolve')
-rw-r--r--src/resolve/resolved-dns-scope.c4
-rw-r--r--src/resolve/resolved-manager.c74
-rw-r--r--src/resolve/resolved-manager.h2
3 files changed, 63 insertions, 17 deletions
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 5448575d5a..7a5143d8ac 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -1085,6 +1085,10 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) {
if (DNS_TRANSACTION_IS_LIVE(t->state))
return 0;
+ /* Check if there're services pending conflict resolution. */
+ if (manager_next_dnssd_names(scope->manager))
+ return 0; /* we reach this point only if changing hostname didn't help */
+
/* Calculate answer's size. */
HASHMAP_FOREACH(z, scope->zone.by_key, iterator) {
if (z->state != DNS_ZONE_ITEM_ESTABLISHED)
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 2813f6ee40..983e6c091a 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -1124,19 +1124,16 @@ void manager_refresh_rrs(Manager *m) {
}
}
-int manager_next_hostname(Manager *m) {
+static int manager_next_random_name(const char *old, char **ret_new) {
const char *p;
uint64_t u, a;
- char *h, *k;
- int r;
-
- assert(m);
+ char *n;
- p = strchr(m->llmnr_hostname, 0);
+ p = strchr(old, 0);
assert(p);
- while (p > m->llmnr_hostname) {
- if (!strchr("0123456789", p[-1]))
+ while (p > old) {
+ if (!strchr(DIGITS, p[-1]))
break;
p--;
@@ -1155,22 +1152,32 @@ int manager_next_hostname(Manager *m) {
random_bytes(&a, sizeof(a));
u += 1 + a % 10;
- if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->llmnr_hostname), m->llmnr_hostname, u) < 0)
+ if (asprintf(&n, "%.*s%" PRIu64, (int) (p - old), old, u) < 0)
return -ENOMEM;
+ *ret_new = n;
+
+ return 0;
+}
+
+int manager_next_hostname(Manager *m) {
+ _cleanup_free_ char *h = NULL, *k = NULL;
+ int r;
+
+ assert(m);
+
+ r = manager_next_random_name(m->llmnr_hostname, &h);
+ if (r < 0)
+ return r;
+
r = dns_name_concat(h, "local", &k);
- if (r < 0) {
- free(h);
+ if (r < 0)
return r;
- }
log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->llmnr_hostname, h);
- free(m->llmnr_hostname);
- m->llmnr_hostname = h;
-
- free(m->mdns_hostname);
- m->mdns_hostname = k;
+ free_and_replace(m->llmnr_hostname, h);
+ free_and_replace(m->mdns_hostname, k);
manager_refresh_rrs(m);
@@ -1504,3 +1511,36 @@ void manager_cleanup_saved_user(Manager *m) {
(void) unlink(p);
}
}
+
+bool manager_next_dnssd_names(Manager *m) {
+ Iterator i;
+ DnssdService *s;
+ bool tried = false;
+ int r;
+
+ assert(m);
+
+ HASHMAP_FOREACH(s, m->dnssd_services, i) {
+ _cleanup_free_ char * new_name = NULL;
+
+ if (!s->withdrawn)
+ continue;
+
+ r = manager_next_random_name(s->name_template, &new_name);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to get new name for service '%s': %m", s->name);
+ continue;
+ }
+
+ free_and_replace(s->name_template, new_name);
+
+ s->withdrawn = false;
+
+ tried = true;
+ }
+
+ if (tried)
+ manager_refresh_rrs(m);
+
+ return tried;
+}
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
index e16d6a4732..d964742921 100644
--- a/src/resolve/resolved-manager.h
+++ b/src/resolve/resolved-manager.h
@@ -192,3 +192,5 @@ void manager_flush_caches(Manager *m);
void manager_reset_server_features(Manager *m);
void manager_cleanup_saved_user(Manager *m);
+
+bool manager_next_dnssd_names(Manager *m);