4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering This file is part of systemd.
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering Copyright 2014 Lennart Poettering
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering systemd is free software; you can redistribute it and/or modify it
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering under the terms of the GNU Lesser General Public License as published by
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering (at your option) any later version.
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering systemd is distributed in the hope that it will be useful, but
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering Lesser General Public License for more details.
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering You should have received a copy of the GNU Lesser General Public License
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering#define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
7c2a5e264c1d94ca9ba9c49acfdcd541c8a63a88Lennart Poetteringstatic voidfunc_t find_fallback(const char *module, const char *symbol) {
7c2a5e264c1d94ca9ba9c49acfdcd541c8a63a88Lennart Poettering /* Try to find a fallback NSS module symbol */
7c2a5e264c1d94ca9ba9c49acfdcd541c8a63a88Lennart Poettering dl = dlopen(module, RTLD_LAZY|RTLD_NODELETE);
7c2a5e264c1d94ca9ba9c49acfdcd541c8a63a88Lennart Poetteringstatic bool bus_error_shall_fallback(sd_bus_error *e) {
7c2a5e264c1d94ca9ba9c49acfdcd541c8a63a88Lennart Poettering return sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) ||
7c2a5e264c1d94ca9ba9c49acfdcd541c8a63a88Lennart Poettering sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER) ||
7c2a5e264c1d94ca9ba9c49acfdcd541c8a63a88Lennart Poettering sd_bus_error_has_name(e, SD_BUS_ERROR_NO_REPLY) ||
7c2a5e264c1d94ca9ba9c49acfdcd541c8a63a88Lennart Poettering sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poetteringstatic int count_addresses(sd_bus_message *m, int af, const char **canonical) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_bus_message_enter_container(m, 'a', "(iiay)");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering while ((r = sd_bus_message_enter_container(m, 'r', "iiay")) > 0) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert_cc(sizeof(int32_t) == sizeof(int));
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_bus_message_read(m, "ii", &ifindex, &family);
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering r = sd_bus_message_read(m, "s", canonical);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poetteringenum nss_status _nss_resolve_gethostbyname4_r(
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering int c, r, i = 0;
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering "org.freedesktop.resolve1",
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering "org.freedesktop.resolve1.Manager",
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering "ResolveHostname");
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r = sd_bus_message_set_auto_start(req, false);
51323288fc628a5cac50914df915545d685b793eLennart Poettering r = sd_bus_message_append(req, "isit", 0, name, AF_UNSPEC, (uint64_t) 0);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering c = count_addresses(reply, AF_UNSPEC, &canonical);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering /* First, append name */
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering /* Second, append addresses */
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering const void *a;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert_cc(sizeof(int32_t) == sizeof(int));
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_bus_message_read(reply, "ii", &ifindex, &family);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r = sd_bus_message_read_array(reply, 'y', &a, &sz);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r = sd_bus_message_exit_container(reply);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r_tuple = (struct gaih_addrtuple*) (buffer + idx);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple)));
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering idx += ALIGN(sizeof(struct gaih_addrtuple));
e70df46b9721a3d025e7a0b4ffb5893cbde5e55dLennart Poettering /* Explicitly reset all error variables */
a464cf80110f0c7424f688ffaa4ec0a8a19f9720Lennart Poettering fallback = (enum nss_status (*)(const char *name,
a464cf80110f0c7424f688ffaa4ec0a8a19f9720Lennart Poettering find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r");
a464cf80110f0c7424f688ffaa4ec0a8a19f9720Lennart Poettering return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poetteringenum nss_status _nss_resolve_gethostbyname3_r(
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering char *r_name, *r_aliases, *r_addr, *r_addr_list;
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering int c, r, i = 0;
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering "org.freedesktop.resolve1",
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering "org.freedesktop.resolve1.Manager",
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering "ResolveHostname");
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r = sd_bus_message_set_auto_start(req, false);
51323288fc628a5cac50914df915545d685b793eLennart Poettering r = sd_bus_message_append(req, "isit", 0, name, af, (uint64_t) 0);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering c = count_addresses(reply, af, &canonical);
66a16e7e9fc501d371b57cbe2ae5d130fe930c6dThomas Hindoe Paaboel Andersen ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering /* First, append name */
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering /* Second, create empty aliases array */
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering idx += sizeof(char*);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering /* Third, append addresses */
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering const void *a;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_bus_message_read(reply, "ii", &ifindex, &family);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r = sd_bus_message_read_array(reply, 'y', &a, &sz);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r = sd_bus_message_exit_container(reply);
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering /* Fourth, append address pointer array */
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering for (i = 0; i < c; i++)
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering result->h_addr_list = (char**) r_addr_list;
e70df46b9721a3d025e7a0b4ffb5893cbde5e55dLennart Poettering /* Explicitly reset all error variables */
a464cf80110f0c7424f688ffaa4ec0a8a19f9720Lennart Poettering fallback = (enum nss_status (*)(const char *name,
a464cf80110f0c7424f688ffaa4ec0a8a19f9720Lennart Poettering find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r");
a464cf80110f0c7424f688ffaa4ec0a8a19f9720Lennart Poettering return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poetteringenum nss_status _nss_resolve_gethostbyaddr2_r(
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering char *r_name, *r_aliases, *r_addr, *r_addr_list;
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering unsigned c = 0, i = 0;
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering const char *n;
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering "org.freedesktop.resolve1",
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering "org.freedesktop.resolve1.Manager",
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering "ResolveAddress");
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r = sd_bus_message_set_auto_start(req, false);
51323288fc628a5cac50914df915545d685b793eLennart Poettering r = sd_bus_message_append(req, "ii", 0, af);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r = sd_bus_message_append_array(req, 'y', addr, len);
51323288fc628a5cac50914df915545d685b793eLennart Poettering r = sd_bus_message_append(req, "t", (uint64_t) 0);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(is)");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering 2 * sizeof(char*) + /* pointers to the address, plus trailing NULL */
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering c * sizeof(char*); /* pointers to aliases, plus trailing NULL */
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering /* First, place address */
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering /* Second, place address list */
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering /* Third, reserve space for the aliases array */
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering idx += sizeof(char*) * c;
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering /* Fourth, place aliases */
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering result->h_addr_list = (char**) r_addr_list;
e70df46b9721a3d025e7a0b4ffb5893cbde5e55dLennart Poettering /* Explicitly reset all error variables */
a464cf80110f0c7424f688ffaa4ec0a8a19f9720Lennart Poettering find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyaddr2_r");