From edc501d4674dadc304d45a7e1c5b69e207eb8cd4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 4 Aug 2014 19:48:03 +0200 Subject: [PATCH] resolved: when there's already somebody listening on the LLMNR ports, simple disable LLMNR and warn, but continue This allows us to run resolved inside an nspawn container that shares the network namespace with the host, if there's already an instance running. --- src/resolve/resolved-manager.c | 92 ++++++++++++++++++++++++++-------- src/resolve/resolved-manager.h | 1 + src/resolve/resolved.c | 6 +++ 3 files changed, 77 insertions(+), 22 deletions(-) diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 1b6dc8a4a3a..5061d39c463 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -392,6 +392,63 @@ static int manager_watch_hostname(Manager *m) { return 0; } +static void manager_llmnr_stop(Manager *m) { + assert(m); + + m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source); + m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd); + + m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source); + m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd); + + m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source); + m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd); + + m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source); + m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd); +} + +static int manager_llmnr_start(Manager *m) { + int r; + + assert(m); + + if (m->llmnr_support == SUPPORT_NO) + return 0; + + r = manager_llmnr_ipv4_udp_fd(m); + if (r == -EADDRINUSE) + goto eaddrinuse; + if (r < 0) + return r; + + r = manager_llmnr_ipv6_udp_fd(m); + if (r == -EADDRINUSE) + goto eaddrinuse; + if (r < 0) + return r; + + r = manager_llmnr_ipv4_tcp_fd(m); + if (r == -EADDRINUSE) + goto eaddrinuse; + if (r < 0) + return r; + + r = manager_llmnr_ipv6_tcp_fd(m); + if (r == -EADDRINUSE) + goto eaddrinuse; + if (r < 0) + return r; + + return 0; + +eaddrinuse: + log_warning("There appears to be another LLMNR respondering running. Turning off LLMNR support."); + m->llmnr_support = SUPPORT_NO; + manager_llmnr_stop(m); + return 0; +} + int manager_new(Manager **ret) { _cleanup_(manager_freep) Manager *m = NULL; int r; @@ -443,25 +500,24 @@ int manager_new(Manager **ret) { if (r < 0) return r; - r = manager_llmnr_ipv4_udp_fd(m); - if (r < 0) - return r; - r = manager_llmnr_ipv6_udp_fd(m); - if (r < 0) - return r; - r = manager_llmnr_ipv4_tcp_fd(m); - if (r < 0) - return r; - r = manager_llmnr_ipv6_tcp_fd(m); - if (r < 0) - return r; - *ret = m; m = NULL; return 0; } +int manager_start(Manager *m) { + int r; + + assert(m); + + r = manager_llmnr_start(m); + if (r < 0) + return r; + + return 0; +} + Manager *manager_free(Manager *m) { Link *l; @@ -492,15 +548,7 @@ Manager *manager_free(Manager *m) { safe_close(m->dns_ipv4_fd); safe_close(m->dns_ipv6_fd); - sd_event_source_unref(m->llmnr_ipv4_udp_event_source); - sd_event_source_unref(m->llmnr_ipv6_udp_event_source); - safe_close(m->llmnr_ipv4_udp_fd); - safe_close(m->llmnr_ipv6_udp_fd); - - sd_event_source_unref(m->llmnr_ipv4_tcp_event_source); - sd_event_source_unref(m->llmnr_ipv6_tcp_event_source); - safe_close(m->llmnr_ipv4_tcp_fd); - safe_close(m->llmnr_ipv6_tcp_fd); + manager_llmnr_stop(m); sd_event_source_unref(m->bus_retry_event_source); sd_bus_unref(m->bus); diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index 31d670da44e..1fd4be41a44 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -114,6 +114,7 @@ struct Manager { int manager_new(Manager **ret); Manager* manager_free(Manager *m); +int manager_start(Manager *m); int manager_read_resolv_conf(Manager *m); int manager_write_resolv_conf(Manager *m); diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c index 900a36d8f06..892bb51386d 100644 --- a/src/resolve/resolved.c +++ b/src/resolve/resolved.c @@ -75,6 +75,12 @@ int main(int argc, char *argv[]) { if (r < 0) log_warning("Failed to parse configuration file: %s", strerror(-r)); + r = manager_start(m); + if (r < 0) { + log_error("Failed to start manager: %s", strerror(-r)); + goto finish; + } + /* Write finish default resolv.conf to avoid a dangling * symlink */ r = manager_write_resolv_conf(m); -- 2.39.2