diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2017-02-12 15:08:19 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-12 15:08:19 -0500 |
commit | 179e679edd5c4456da5cf09c230941d620ed4c3a (patch) | |
tree | 7eca1f0bef034d0992bae7871465dcf066a6acc4 | |
parent | 6818c54ca6663c008fad77d2677c61758c7215f5 (diff) | |
parent | 12bf233175208d9250e44f5e4ec137d154b69a16 (diff) |
Merge pull request #5276 from poettering/resolved-cname
a good number of resolved fixes
-rw-r--r-- | src/analyze/analyze.c | 2 | ||||
-rw-r--r-- | src/core/dbus-manager.c | 2 | ||||
-rw-r--r-- | src/hostname/hostnamectl.c | 23 | ||||
-rw-r--r-- | src/locale/localectl.c | 5 | ||||
-rw-r--r-- | src/login/loginctl.c | 15 | ||||
-rw-r--r-- | src/machine/machinectl.c | 13 | ||||
-rw-r--r-- | src/nss-myhostname/nss-myhostname.c | 11 | ||||
-rw-r--r-- | src/nss-resolve/nss-resolve.c | 16 | ||||
-rw-r--r-- | src/resolve/resolve-tool.c | 8 | ||||
-rw-r--r-- | src/resolve/resolved-bus.c | 8 | ||||
-rw-r--r-- | src/resolve/resolved-dns-query.c | 10 | ||||
-rw-r--r-- | src/resolve/resolved-dns-query.h | 5 | ||||
-rw-r--r-- | src/resolve/resolved-dns-server.c | 19 | ||||
-rw-r--r-- | src/resolve/resolved-dns-server.h | 2 | ||||
-rw-r--r-- | src/resolve/resolved-dns-stub.c | 126 | ||||
-rw-r--r-- | src/resolve/resolved-dns-transaction.c | 11 | ||||
-rw-r--r-- | src/resolve/resolved-manager.c | 47 | ||||
-rw-r--r-- | src/resolve/resolved-manager.h | 1 | ||||
-rw-r--r-- | src/run/run.c | 4 | ||||
-rw-r--r-- | src/shared/bus-util.c | 15 | ||||
-rw-r--r-- | src/shared/bus-util.h | 6 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 17 | ||||
-rw-r--r-- | src/timedate/timedatectl.c | 5 |
23 files changed, 251 insertions, 120 deletions
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 51d881c5fb..a9402fdb28 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -461,6 +461,7 @@ static int acquire_host_info(sd_bus *bus, struct host_info **hi) { "org.freedesktop.hostname1", "/org/freedesktop/hostname1", hostname_map, + &error, host); if (r < 0) log_debug_errno(r, "Failed to get host information from systemd-hostnamed: %s", bus_error_message(&error, r)); @@ -469,6 +470,7 @@ static int acquire_host_info(sd_bus *bus, struct host_info **hi) { "org.freedesktop.systemd1", "/org/freedesktop/systemd1", manager_map, + &error, host); if (r < 0) return log_error_errno(r, "Failed to get host information from systemd: %s", bus_error_message(&error, r)); diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 27f948cbdd..f87b52a266 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1338,7 +1338,7 @@ static int verify_run_space(const char *message, sd_bus_error *error) { } int verify_run_space_and_log(const char *message) { - sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; r = verify_run_space(message, &error); diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c index 07c57fb567..f5a9de94a6 100644 --- a/src/hostname/hostnamectl.c +++ b/src/hostname/hostnamectl.c @@ -137,10 +137,8 @@ static int show_one_name(sd_bus *bus, const char* attr) { "org.freedesktop.hostname1", attr, &error, &reply, "s"); - if (r < 0) { - log_error("Could not get property: %s", bus_error_message(&error, -r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Could not get property: %s", bus_error_message(&error, r)); r = sd_bus_message_read(reply, "s", &s); if (r < 0) @@ -151,7 +149,7 @@ static int show_one_name(sd_bus *bus, const char* attr) { return 0; } -static int show_all_names(sd_bus *bus) { +static int show_all_names(sd_bus *bus, sd_bus_error *error) { StatusInfo info = {}; static const struct bus_properties_map hostname_map[] = { @@ -181,6 +179,7 @@ static int show_all_names(sd_bus *bus) { "org.freedesktop.hostname1", "/org/freedesktop/hostname1", hostname_map, + error, &info); if (r < 0) goto fail; @@ -189,6 +188,7 @@ static int show_all_names(sd_bus *bus) { "org.freedesktop.systemd1", "/org/freedesktop/systemd1", manager_map, + error, &info); print_status_info(&info); @@ -212,6 +212,8 @@ fail: } static int show_status(sd_bus *bus, char **args, unsigned n) { + int r; + assert(args); if (arg_pretty || arg_static || arg_transient) { @@ -226,8 +228,15 @@ static int show_status(sd_bus *bus, char **args, unsigned n) { arg_static ? "StaticHostname" : "Hostname"; return show_one_name(bus, attr); - } else - return show_all_names(bus); + } else { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = show_all_names(bus, &error); + if (r < 0) + return log_error_errno(r, "Failed to query system properties: %s", bus_error_message(&error, r)); + + return 0; + } } static int set_simple_string(sd_bus *bus, const char *method, const char *value) { diff --git a/src/locale/localectl.c b/src/locale/localectl.c index 81afb4909f..0bd18a5c0b 100644 --- a/src/locale/localectl.c +++ b/src/locale/localectl.c @@ -166,6 +166,8 @@ static int show_status(sd_bus *bus, char **args, unsigned n) { { "Locale", "as", NULL, offsetof(StatusInfo, locale) }, {} }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); @@ -174,9 +176,10 @@ static int show_status(sd_bus *bus, char **args, unsigned n) { "org.freedesktop.locale1", "/org/freedesktop/locale1", map, + &error, &info); if (r < 0) - return log_error_errno(r, "Could not get properties: %m"); + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); print_overridden_variables(); print_status_info(&info); diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 1aac7ae979..7dea5c0859 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -482,14 +482,15 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li {} }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char since2[FORMAT_TIMESTAMP_MAX], *s2; _cleanup_(session_status_info_clear) SessionStatusInfo i = {}; int r; - r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i); + r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i); if (r < 0) - return log_error_errno(r, "Could not get properties: %m"); + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); if (*new_line) printf("\n"); @@ -611,14 +612,15 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {} }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char since2[FORMAT_TIMESTAMP_MAX], *s2; _cleanup_(user_status_info_clear) UserStatusInfo i = {}; int r; - r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i); + r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i); if (r < 0) - return log_error_errno(r, "Could not get properties: %m"); + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); if (*new_line) printf("\n"); @@ -685,12 +687,13 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {} }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(seat_status_info_clear) SeatStatusInfo i = {}; int r; - r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i); + r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i); if (r < 0) - return log_error_errno(r, "Could not get properties: %m"); + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); if (*new_line) printf("\n"); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 4f5f659c7c..fe4f1b7726 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -772,6 +772,7 @@ static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bo {} }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(machine_status_info_clear) MachineStatusInfo info = {}; int r; @@ -784,9 +785,10 @@ static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bo "org.freedesktop.machine1", path, map, + &error, &info); if (r < 0) - return log_error_errno(r, "Could not get properties: %m"); + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); if (*new_line) printf("\n"); @@ -962,6 +964,7 @@ static int show_image_info(sd_bus *bus, const char *path, bool *new_line) { {} }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(image_status_info_clear) ImageStatusInfo info = {}; int r; @@ -973,9 +976,10 @@ static int show_image_info(sd_bus *bus, const char *path, bool *new_line) { "org.freedesktop.machine1", path, map, + &error, &info); if (r < 0) - return log_error_errno(r, "Could not get properties: %m"); + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); if (*new_line) printf("\n"); @@ -1029,6 +1033,8 @@ static int show_pool_info(sd_bus *bus) { .usage = (uint64_t) -1, .limit = (uint64_t) -1, }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); @@ -1037,9 +1043,10 @@ static int show_pool_info(sd_bus *bus) { "org.freedesktop.machine1", "/org/freedesktop/machine1", map, + &error, &info); if (r < 0) - return log_error_errno(r, "Could not get properties: %m"); + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); print_pool_status_info(bus, &info); diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c index 11c27575c0..326672cab5 100644 --- a/src/nss-myhostname/nss-myhostname.c +++ b/src/nss-myhostname/nss-myhostname.c @@ -55,7 +55,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r( _cleanup_free_ struct local_address *addresses = NULL; _cleanup_free_ char *hn = NULL; const char *canonical = NULL; - int n_addresses = 0, lo_ifi; + int n_addresses = 0; uint32_t local_address_ipv4; struct local_address *a; size_t l, idx, ms; @@ -111,9 +111,6 @@ enum nss_status _nss_myhostname_gethostbyname4_r( local_address_ipv4 = LOCALADDRESS_IPV4; } - /* If this call fails we fill in 0 as scope. Which is fine */ - lo_ifi = n_addresses <= 0 ? LOOPBACK_IFINDEX : 0; - l = strlen(canonical); ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * (n_addresses > 0 ? n_addresses : 2); if (buflen < ms) { @@ -135,7 +132,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r( r_tuple->name = r_name; r_tuple->family = AF_INET6; memcpy(r_tuple->addr, LOCALADDRESS_IPV6, 16); - r_tuple->scopeid = (uint32_t) lo_ifi; + r_tuple->scopeid = 0; idx += ALIGN(sizeof(struct gaih_addrtuple)); r_tuple_prev = r_tuple; @@ -146,7 +143,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r( r_tuple->name = r_name; r_tuple->family = AF_INET; *(uint32_t*) r_tuple->addr = local_address_ipv4; - r_tuple->scopeid = (uint32_t) lo_ifi; + r_tuple->scopeid = 0; idx += ALIGN(sizeof(struct gaih_addrtuple)); r_tuple_prev = r_tuple; @@ -158,7 +155,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r( r_tuple->next = r_tuple_prev; r_tuple->name = r_name; r_tuple->family = a->family; - r_tuple->scopeid = a->ifindex; + r_tuple->scopeid = a->family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&a->address.in6) ? a->ifindex : 0; memcpy(r_tuple->addr, &a->address, 16); idx += ALIGN(sizeof(struct gaih_addrtuple)); diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c index d46a3afe91..ce8d59d390 100644 --- a/src/nss-resolve/nss-resolve.c +++ b/src/nss-resolve/nss-resolve.c @@ -110,6 +110,20 @@ static int count_addresses(sd_bus_message *m, int af, const char **canonical) { return c; } +static uint32_t ifindex_to_scopeid(int family, const void *a, int ifindex) { + struct in6_addr in6; + + if (family != AF_INET6) + return 0; + + /* Some apps can't deal with the scope ID attached to non-link-local addresses. Hence, let's suppress that. */ + + assert(sizeof(in6) == FAMILY_ADDRESS_SIZE(AF_INET)); + memcpy(&in6, a, sizeof(struct in6_addr)); + + return IN6_IS_ADDR_LINKLOCAL(&in6) ? ifindex : 0; +} + enum nss_status _nss_resolve_gethostbyname4_r( const char *name, struct gaih_addrtuple **pat, @@ -245,7 +259,7 @@ enum nss_status _nss_resolve_gethostbyname4_r( r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple))); r_tuple->name = r_name; r_tuple->family = family; - r_tuple->scopeid = ifindex; + r_tuple->scopeid = ifindex_to_scopeid(family, a, ifindex); memcpy(r_tuple->addr, a, sz); idx += ALIGN(sizeof(struct gaih_addrtuple)); diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c index 07d9582ccb..13841c2b57 100644 --- a/src/resolve/resolve-tool.c +++ b/src/resolve/resolve-tool.c @@ -1186,6 +1186,7 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empt {} }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *ifi = NULL, *p = NULL; char ifname[IF_NAMESIZE] = ""; char **i; @@ -1213,9 +1214,10 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, bool *empt "org.freedesktop.resolve1", p, property_map, + &error, &link_info); if (r < 0) { - log_error_errno(r, "Failed to get link data for %i: %m", ifindex); + log_error_errno(r, "Failed to get link data for %i: %s", ifindex, bus_error_message(&error, r)); goto finish; } @@ -1405,6 +1407,7 @@ static int status_global(sd_bus *bus, bool *empty_line) { {} }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char **i; int r; @@ -1415,9 +1418,10 @@ static int status_global(sd_bus *bus, bool *empty_line) { "org.freedesktop.resolve1", "/org/freedesktop/resolve1", property_map, + &error, &global_info); if (r < 0) { - log_error_errno(r, "Failed to get global data: %m"); + log_error_errno(r, "Failed to get global data: %s", bus_error_message(&error, r)); goto finish; } diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index 2ca65e6953..2c50109388 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -211,7 +211,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) { r = sd_bus_message_append( reply, "st", normalized, - SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated)); + SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))); if (r < 0) goto finish; @@ -439,7 +439,7 @@ static void bus_method_resolve_address_complete(DnsQuery *q) { if (r < 0) goto finish; - r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated)); + r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))); if (r < 0) goto finish; @@ -605,7 +605,7 @@ static void bus_method_resolve_record_complete(DnsQuery *q) { if (r < 0) goto finish; - r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated)); + r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))); if (r < 0) goto finish; @@ -979,7 +979,7 @@ static void resolve_service_all_complete(DnsQuery *q) { reply, "ssst", name, type, domain, - SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated)); + SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))); if (r < 0) goto finish; diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index e03db4d003..c58845c3b6 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -403,6 +403,7 @@ DnsQuery *dns_query_free(DnsQuery *q) { sd_bus_track_unref(q->bus_track); dns_packet_unref(q->request_dns_packet); + dns_packet_unref(q->reply_dns_packet); if (q->request_dns_stream) { /* Detach the stream from our query, in case something else keeps a reference to it. */ @@ -1028,6 +1029,9 @@ int dns_query_process_cname(DnsQuery *q) { if (q->flags & SD_RESOLVED_NO_CNAME) return -ELOOP; + if (!q->answer_authenticated) + q->previous_redirect_unauthenticated = true; + /* OK, let's actually follow the CNAME */ r = dns_query_cname_redirect(q, cname); if (r < 0) @@ -1115,3 +1119,9 @@ const char *dns_query_string(DnsQuery *q) { return dns_question_first_name(q->question_idna); } + +bool dns_query_fully_authenticated(DnsQuery *q) { + assert(q); + + return q->answer_authenticated && !q->previous_redirect_unauthenticated; +} diff --git a/src/resolve/resolved-dns-query.h b/src/resolve/resolved-dns-query.h index 49a35b846b..b8ea48f6af 100644 --- a/src/resolve/resolved-dns-query.h +++ b/src/resolve/resolved-dns-query.h @@ -71,7 +71,6 @@ struct DnsQuery { * family */ bool suppress_unroutable_family; - /* If true, the RR TTLs of the answer will be clamped by their current left validity in the cache */ bool clamp_ttl; @@ -90,6 +89,7 @@ struct DnsQuery { int answer_family; DnsSearchDomain *answer_search_domain; int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */ + bool previous_redirect_unauthenticated; /* Bus client information */ sd_bus_message *request; @@ -102,6 +102,7 @@ struct DnsQuery { /* DNS stub information */ DnsPacket *request_dns_packet; DnsStream *request_dns_stream; + DnsPacket *reply_dns_packet; /* Completion callback */ void (*complete)(DnsQuery* q); @@ -139,3 +140,5 @@ DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol); const char *dns_query_string(DnsQuery *q); DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery*, dns_query_free); + +bool dns_query_fully_authenticated(DnsQuery *q); diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 22c64e8491..10562d03ec 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -451,18 +451,22 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) { s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0; } else if (s->n_failed_udp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS && - s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_UDP) { + s->possible_feature_level >= (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) { /* We lost too many UDP packets in a row, and are on a feature level of UDP or higher. If the * packets are lost, maybe the server cannot parse them, hence downgrading sounds like a good - * idea. We might downgrade all the way down to TCP this way. */ + * idea. We might downgrade all the way down to TCP this way. + * + * If strict DNSSEC mode is used we won't downgrade below DO level however, as packet loss + * might have many reasons, a broken DNSSEC implementation being only one reason. And if the + * user is strict on DNSSEC, then let's assume that DNSSEC is not the fault here. */ log_debug("Lost too many UDP packets, downgrading feature level..."); s->possible_feature_level--; } else if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS && s->packet_truncated && - s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP) { + s->possible_feature_level > (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) { /* We got too many TCP connection failures in a row, we had at least one truncated packet, and * are on a feature level above UDP. By downgrading things and getting rid of DNSSEC or EDNS0 @@ -779,6 +783,15 @@ bool dns_server_address_valid(int family, const union in_addr_union *sa) { return true; } +DnssecMode dns_server_get_dnssec_mode(DnsServer *s) { + assert(s); + + if (s->link) + return link_get_dnssec_mode(s->link); + + return manager_get_dnssec_mode(s->manager); +} + static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = { [DNS_SERVER_SYSTEM] = "system", [DNS_SERVER_FALLBACK] = "fallback", diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h index 83e288a202..406282d864 100644 --- a/src/resolve/resolved-dns-server.h +++ b/src/resolve/resolved-dns-server.h @@ -144,6 +144,8 @@ void manager_next_dns_server(Manager *m); bool dns_server_address_valid(int family, const union in_addr_union *sa); +DnssecMode dns_server_get_dnssec_mode(DnsServer *s); + DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref); extern const struct hash_ops dns_server_hash_ops; diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 4a3c5f612f..9376b0fe4c 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -29,49 +29,33 @@ static int manager_dns_stub_udp_fd(Manager *m); static int manager_dns_stub_tcp_fd(Manager *m); static int dns_stub_make_reply_packet( - uint16_t id, - int rcode, + DnsPacket **p, DnsQuestion *q, - DnsAnswer *answer, - bool add_opt, /* add an OPT RR to this packet */ - bool edns0_do, /* set the EDNS0 DNSSEC OK bit */ - bool ad, /* set the DNSSEC authenticated data bit */ - DnsPacket **ret) { + DnsAnswer *answer) { - _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; DnsResourceRecord *rr; unsigned c = 0; int r; + assert(p); + /* Note that we don't bother with any additional RRs, as this is stub is for local lookups only, and hence * roundtrips aren't expensive. */ - r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0); - if (r < 0) - return r; - - /* If the client didn't do EDNS, clamp the rcode to 4 bit */ - if (!add_opt && rcode > 0xF) - rcode = DNS_RCODE_SERVFAIL; + if (!*p) { + r = dns_packet_new(p, DNS_PROTOCOL_DNS, 0); + if (r < 0) + return r; - DNS_PACKET_HEADER(p)->id = id; - DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS( - 1 /* qr */, - 0 /* opcode */, - 0 /* aa */, - 0 /* tc */, - 1 /* rd */, - 1 /* ra */, - ad /* ad */, - 0 /* cd */, - rcode)); + r = dns_packet_append_question(*p, q); + if (r < 0) + return r; - r = dns_packet_append_question(p, q); - if (r < 0) - return r; - DNS_PACKET_HEADER(p)->qdcount = htobe16(dns_question_size(q)); + DNS_PACKET_HEADER(*p)->qdcount = htobe16(dns_question_size(q)); + } DNS_ANSWER_FOREACH(rr, answer) { + r = dns_question_matches_rr(q, rr, NULL); if (r < 0) return r; @@ -86,13 +70,46 @@ static int dns_stub_make_reply_packet( continue; add: - r = dns_packet_append_rr(p, rr, NULL, NULL); + r = dns_packet_append_rr(*p, rr, NULL, NULL); if (r < 0) return r; c++; } - DNS_PACKET_HEADER(p)->ancount = htobe16(c); + + DNS_PACKET_HEADER(*p)->ancount = htobe16(be16toh(DNS_PACKET_HEADER(*p)->ancount) + c); + + return 0; +} + +static int dns_stub_finish_reply_packet( + DnsPacket *p, + uint16_t id, + int rcode, + bool add_opt, /* add an OPT RR to this packet? */ + bool edns0_do, /* set the EDNS0 DNSSEC OK bit? */ + bool ad) { /* set the DNSSEC authenticated data bit? */ + + int r; + + assert(p); + + /* If the client didn't do EDNS, clamp the rcode to 4 bit */ + if (!add_opt && rcode > 0xF) + rcode = DNS_RCODE_SERVFAIL; + + DNS_PACKET_HEADER(p)->id = id; + + DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS( + 1 /* qr */, + 0 /* opcode */, + 0 /* aa */, + 0 /* tc */, + 1 /* rd */, + 1 /* ra */, + ad /* ad */, + 0 /* cd */, + rcode)); if (add_opt) { r = dns_packet_append_opt(p, ADVERTISE_DATAGRAM_SIZE_MAX, edns0_do, rcode, NULL); @@ -100,9 +117,6 @@ static int dns_stub_make_reply_packet( return r; } - *ret = p; - p = NULL; - return 0; } @@ -155,7 +169,11 @@ static int dns_stub_send_failure(Manager *m, DnsStream *s, DnsPacket *p, int rco assert(m); assert(p); - r = dns_stub_make_reply_packet(DNS_PACKET_ID(p), rcode, p->question, NULL, !!p->opt, DNS_PACKET_DO(p), false, &reply); + r = dns_stub_make_reply_packet(&reply, p->question, NULL); + if (r < 0) + return log_debug_errno(r, "Failed to make failure packet: %m"); + + r = dns_stub_finish_reply_packet(reply, DNS_PACKET_ID(p), rcode, !!p->opt, DNS_PACKET_DO(p), false); if (r < 0) return log_debug_errno(r, "Failed to build failure packet: %m"); @@ -170,26 +188,40 @@ static void dns_stub_query_complete(DnsQuery *q) { switch (q->state) { - case DNS_TRANSACTION_SUCCESS: { - _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL; + case DNS_TRANSACTION_SUCCESS: + + r = dns_stub_make_reply_packet(&q->reply_dns_packet, q->question_idna, q->answer); + if (r < 0) { + log_debug_errno(r, "Failed to build reply packet: %m"); + break; + } + + r = dns_query_process_cname(q); + if (r == -ELOOP) { + (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL); + break; + } + if (r < 0) { + log_debug_errno(r, "Failed to process CNAME: %m"); + break; + } + if (r == DNS_QUERY_RESTARTED) + return; - r = dns_stub_make_reply_packet( + r = dns_stub_finish_reply_packet( + q->reply_dns_packet, DNS_PACKET_ID(q->request_dns_packet), q->answer_rcode, - q->question_idna, - q->answer, !!q->request_dns_packet->opt, DNS_PACKET_DO(q->request_dns_packet), - DNS_PACKET_DO(q->request_dns_packet) && q->answer_authenticated, - &reply); + DNS_PACKET_DO(q->request_dns_packet) && dns_query_fully_authenticated(q)); if (r < 0) { - log_debug_errno(r, "Failed to build reply packet: %m"); + log_debug_errno(r, "Failed to finish reply packet: %m"); break; } - (void) dns_stub_send(q->manager, q->request_dns_stream, q->request_dns_packet, reply); + (void) dns_stub_send(q->manager, q->request_dns_stream, q->request_dns_packet, q->reply_dns_packet); break; - } case DNS_TRANSACTION_RCODE_FAILURE: (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, q->answer_rcode); @@ -301,7 +333,7 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) { goto fail; } - r = dns_query_new(m, &q, p->question, p->question, 0, SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_SEARCH|SD_RESOLVED_NO_CNAME); + r = dns_query_new(m, &q, p->question, p->question, 0, SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_SEARCH); if (r < 0) { log_error_errno(r, "Failed to generate query object: %m"); dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 2fce44ec8b..1985dbde21 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -924,7 +924,16 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { dns_transaction_retry(t, false /* use the same server */); return; - } else if (DNS_PACKET_TC(p)) + } + + if (DNS_PACKET_RCODE(p) == DNS_RCODE_REFUSED) { + /* This server refused our request? If so, try again, use a different server */ + log_debug("Server returned REFUSED, switching servers, and retrying."); + dns_transaction_retry(t, true /* pick a new server */); + return; + } + + if (DNS_PACKET_TC(p)) dns_server_packet_truncated(t->server, t->current_feature_level); break; diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 667774b906..195c6d5d40 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -322,12 +322,13 @@ static int manager_network_monitor_listen(Manager *m) { return 0; } -static int determine_hostname(char **llmnr_hostname, char **mdns_hostname) { +static int determine_hostname(char **full_hostname, char **llmnr_hostname, char **mdns_hostname) { _cleanup_free_ char *h = NULL, *n = NULL; char label[DNS_LABEL_MAX]; const char *p; int r, k; + assert(full_hostname); assert(llmnr_hostname); assert(mdns_hostname); @@ -374,32 +375,33 @@ static int determine_hostname(char **llmnr_hostname, char **mdns_hostname) { *llmnr_hostname = n; n = NULL; + *full_hostname = h; + h = NULL; + return 0; } static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) { - _cleanup_free_ char *llmnr_hostname = NULL, *mdns_hostname = NULL; + _cleanup_free_ char *full_hostname = NULL, *llmnr_hostname = NULL, *mdns_hostname = NULL; Manager *m = userdata; int r; assert(m); - r = determine_hostname(&llmnr_hostname, &mdns_hostname); + r = determine_hostname(&full_hostname, &llmnr_hostname, &mdns_hostname); if (r < 0) return 0; /* ignore invalid hostnames */ - if (streq(llmnr_hostname, m->llmnr_hostname) && streq(mdns_hostname, m->mdns_hostname)) + if (streq(full_hostname, m->full_hostname) && + streq(llmnr_hostname, m->llmnr_hostname) && + streq(mdns_hostname, m->mdns_hostname)) return 0; - log_info("System hostname changed to '%s'.", llmnr_hostname); - - free(m->llmnr_hostname); - free(m->mdns_hostname); + log_info("System hostname changed to '%s'.", full_hostname); - m->llmnr_hostname = llmnr_hostname; - m->mdns_hostname = mdns_hostname; - - llmnr_hostname = mdns_hostname = NULL; + free_and_replace(m->full_hostname, full_hostname); + free_and_replace(m->llmnr_hostname, llmnr_hostname); + free_and_replace(m->mdns_hostname, mdns_hostname); manager_refresh_rrs(m); @@ -428,9 +430,14 @@ static int manager_watch_hostname(Manager *m) { (void) sd_event_source_set_description(m->hostname_event_source, "hostname"); - r = determine_hostname(&m->llmnr_hostname, &m->mdns_hostname); + r = determine_hostname(&m->full_hostname, &m->llmnr_hostname, &m->mdns_hostname); if (r < 0) { log_info("Defaulting to hostname 'linux'."); + + m->full_hostname = strdup("linux"); + if (!m->full_hostname) + return log_oom(); + m->llmnr_hostname = strdup("linux"); if (!m->llmnr_hostname) return log_oom(); @@ -439,7 +446,7 @@ static int manager_watch_hostname(Manager *m) { if (!m->mdns_hostname) return log_oom(); } else - log_info("Using system hostname '%s'.", m->llmnr_hostname); + log_info("Using system hostname '%s'.", m->full_hostname); return 0; } @@ -624,6 +631,8 @@ Manager *manager_free(Manager *m) { sd_event_source_unref(m->hostname_event_source); safe_close(m->hostname_fd); + + free(m->full_hostname); free(m->llmnr_hostname); free(m->mdns_hostname); @@ -1146,8 +1155,14 @@ int manager_is_own_hostname(Manager *m, const char *name) { return r; } - if (m->mdns_hostname) - return dns_name_equal(name, m->mdns_hostname); + if (m->mdns_hostname) { + r = dns_name_equal(name, m->mdns_hostname); + if (r != 0) + return r; + } + + if (m->full_hostname) + return dns_name_equal(name, m->full_hostname); return 0; } diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index 6b2208ed94..9b71b81e76 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -109,6 +109,7 @@ struct Manager { sd_event_source *bus_retry_event_source; /* The hostname we publish on LLMNR and mDNS */ + char *full_hostname; char *llmnr_hostname; char *mdns_hostname; DnsResourceKey *llmnr_host_ipv4_key; diff --git a/src/run/run.c b/src/run/run.c index 08f7e12336..f8257abc93 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -818,16 +818,18 @@ static int run_context_update(RunContext *c, const char *path) { {} }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; r = bus_map_all_properties(c->bus, "org.freedesktop.systemd1", path, map, + &error, c); if (r < 0) { sd_event_exit(c->event, EXIT_FAILURE); - return log_error_errno(r, "Failed to query unit state: %m"); + return log_error_errno(r, "Failed to query unit state: %s", bus_error_message(&error, r)); } run_context_check_done(c); diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 6aebe18fc0..8ddfb584ea 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1116,9 +1116,9 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ int bus_message_map_all_properties( sd_bus_message *m, const struct bus_properties_map *map, + sd_bus_error *error, void *userdata) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(m); @@ -1156,9 +1156,9 @@ int bus_message_map_all_properties( v = (uint8_t *)userdata + prop->offset; if (map[i].set) - r = prop->set(sd_bus_message_get_bus(m), member, m, &error, v); + r = prop->set(sd_bus_message_get_bus(m), member, m, error, v); else - r = map_basic(sd_bus_message_get_bus(m), member, m, &error, v); + r = map_basic(sd_bus_message_get_bus(m), member, m, error, v); if (r < 0) return r; @@ -1184,6 +1184,7 @@ int bus_message_map_all_properties( int bus_message_map_properties_changed( sd_bus_message *m, const struct bus_properties_map *map, + sd_bus_error *error, void *userdata) { const char *member; @@ -1192,7 +1193,7 @@ int bus_message_map_properties_changed( assert(m); assert(map); - r = bus_message_map_all_properties(m, map, userdata); + r = bus_message_map_all_properties(m, map, error, userdata); if (r < 0) return r; @@ -1222,10 +1223,10 @@ int bus_map_all_properties( const char *destination, const char *path, const struct bus_properties_map *map, + sd_bus_error *error, void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); @@ -1239,13 +1240,13 @@ int bus_map_all_properties( path, "org.freedesktop.DBus.Properties", "GetAll", - &error, + error, &m, "s", ""); if (r < 0) return r; - return bus_message_map_all_properties(m, map, userdata); + return bus_message_map_all_properties(m, map, error, userdata); } int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) { diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index af5f133912..d9ce4263bb 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -50,9 +50,9 @@ struct bus_properties_map { int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); -int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, void *userdata); -int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, void *userdata); -int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, void *userdata); +int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, sd_bus_error *error, void *userdata); +int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, sd_bus_error *error, void *userdata); +int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, sd_bus_error *error, void *userdata); int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 2809dece50..2336ae34f4 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -1922,7 +1922,7 @@ static int get_machine_properties(sd_bus *bus, struct machine_info *mi) { bus = container; } - r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi); + r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, NULL, mi); if (r < 0) return r; @@ -1957,7 +1957,7 @@ static int get_machine_list( machine_infos[c].name = hn; hn = NULL; - get_machine_properties(bus, &machine_infos[c]); + (void) get_machine_properties(bus, &machine_infos[c]); c++; } @@ -1987,7 +1987,7 @@ static int get_machine_list( return log_oom(); } - get_machine_properties(NULL, &machine_infos[c]); + (void) get_machine_properties(NULL, &machine_infos[c]); c++; } @@ -4953,7 +4953,7 @@ static int show_one( return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r)); if (unit) { - r = bus_message_map_all_properties(reply, property_map, &info); + r = bus_message_map_all_properties(reply, property_map, &error, &info); if (r < 0) return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r)); @@ -5125,8 +5125,9 @@ static int show_all( static int show_system_status(sd_bus *bus) { char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX]; - _cleanup_free_ char *hn = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(machine_info_clear) struct machine_info mi = {}; + _cleanup_free_ char *hn = NULL; const char *on, *off; int r; @@ -5134,9 +5135,9 @@ static int show_system_status(sd_bus *bus) { if (!hn) return log_oom(); - r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi); + r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &error, &mi); if (r < 0) - return log_error_errno(r, "Failed to read server status: %m"); + return log_error_errno(r, "Failed to read server status: %s", bus_error_message(&error, r)); if (streq_ptr(mi.state, "degraded")) { on = ansi_highlight_red(); @@ -6028,7 +6029,7 @@ static int unit_exists(const char *unit) { if (r < 0) return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r)); - r = bus_message_map_all_properties(reply, property_map, &info); + r = bus_message_map_all_properties(reply, property_map, &error, &info); if (r < 0) return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r)); diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index 553ef67011..281b1534a3 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -165,6 +165,8 @@ static int show_status(sd_bus *bus, char **args, unsigned n) { { "RTCTimeUSec", "t", NULL, offsetof(StatusInfo, rtc_time) }, {} }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); @@ -173,9 +175,10 @@ static int show_status(sd_bus *bus, char **args, unsigned n) { "org.freedesktop.timedate1", "/org/freedesktop/timedate1", map, + &error, &info); if (r < 0) - return log_error_errno(r, "Failed to query server: %m"); + return log_error_errno(r, "Failed to query server: %s", bus_error_message(&error, r)); print_status_info(&info); |