]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/nss-resolve/nss-resolve.c
Merge pull request #2495 from heftig/master
[thirdparty/systemd.git] / src / nss-resolve / nss-resolve.c
index 8f181a6c72e072315a1c042f8b4d7c82791961b6..69c0d9bdc13169aa9af1de41725b40d780bc31a2 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <nss.h>
-#include <netdb.h>
+#include <dlfcn.h>
 #include <errno.h>
-#include <string.h>
+#include <netdb.h>
+#include <nss.h>
 #include <stdlib.h>
-#include <dlfcn.h>
+#include <string.h>
 
 #include "sd-bus.h"
-#include "bus-util.h"
+
 #include "bus-common-errors.h"
+#include "in-addr-util.h"
 #include "macro.h"
 #include "nss-util.h"
+#include "string-util.h"
 #include "util.h"
-#include "in-addr-util.h"
+#include "signal-util.h"
 
 NSS_GETHOSTBYNAME_PROTOTYPES(resolve);
 NSS_GETHOSTBYADDR_PROTOTYPES(resolve);
@@ -61,23 +61,21 @@ static bool bus_error_shall_fallback(sd_bus_error *e) {
 }
 
 static int count_addresses(sd_bus_message *m, int af, const char **canonical) {
-        int c = 0, r, ifindex;
+        int c = 0, r;
 
         assert(m);
         assert(canonical);
 
-        r = sd_bus_message_read(m, "i", &ifindex);
+        r = sd_bus_message_enter_container(m, 'a', "(iiay)");
         if (r < 0)
                 return r;
 
-        r = sd_bus_message_enter_container(m, 'a', "(iay)");
-        if (r < 0)
-                return r;
+        while ((r = sd_bus_message_enter_container(m, 'r', "iiay")) > 0) {
+                int family, ifindex;
 
-        while ((r = sd_bus_message_enter_container(m, 'r', "iay")) > 0) {
-                int family;
+                assert_cc(sizeof(int32_t) == sizeof(int));
 
-                r = sd_bus_message_read(m, "i", &family);
+                r = sd_bus_message_read(m, "ii", &ifindex, &family);
                 if (r < 0)
                         return r;
 
@@ -119,14 +117,23 @@ enum nss_status _nss_resolve_gethostbyname4_r(
                 int *errnop, int *h_errnop,
                 int32_t *ttlp) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        enum nss_status (*fallback)(
+                        const char *name,
+                        struct gaih_addrtuple **pat,
+                        char *buffer, size_t buflen,
+                        int *errnop, int *h_errnop,
+                        int32_t *ttlp);
+
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
-        _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         const char *canonical = NULL;
         size_t l, ms, idx;
         char *r_name;
-        int c, r, i = 0, ifindex;
+        int c, r, i = 0;
+
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
 
         assert(name);
         assert(pat);
@@ -136,7 +143,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
 
         r = sd_bus_open_system(&bus);
         if (r < 0)
-                goto fail;
+                goto fallback;
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -164,28 +171,10 @@ enum nss_status _nss_resolve_gethostbyname4_r(
                         return NSS_STATUS_NOTFOUND;
                 }
 
-                if (bus_error_shall_fallback(&error)) {
-
-                        enum nss_status (*fallback)(
-                                        const char *name,
-                                        struct gaih_addrtuple **pat,
-                                        char *buffer, size_t buflen,
-                                        int *errnop, int *h_errnop,
-                                        int32_t *ttlp);
-
-                        fallback = (enum nss_status (*)(const char *name,
-                                                        struct gaih_addrtuple **pat,
-                                                        char *buffer, size_t buflen,
-                                                        int *errnop, int *h_errnop,
-                                                        int32_t *ttlp))
-                                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r");
-                        if (fallback)
-                                return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp);
-                }
+                if (bus_error_shall_fallback(&error))
+                        goto fallback;
 
-                *errnop = -r;
-                *h_errnop = NO_RECOVERY;
-                return NSS_STATUS_UNAVAIL;
+                goto fail;
         }
 
         c = count_addresses(reply, AF_UNSPEC, &canonical);
@@ -218,28 +207,26 @@ enum nss_status _nss_resolve_gethostbyname4_r(
         /* Second, append addresses */
         r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);
 
-        r = sd_bus_message_read(reply, "i", &ifindex);
-        if (r < 0)
-                goto fail;
-
-        if (ifindex < 0) {
-                r = -EINVAL;
-                goto fail;
-        }
-
-        r = sd_bus_message_enter_container(reply, 'a', "(iay)");
+        r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
         if (r < 0)
                 goto fail;
 
-        while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
-                int family;
+        while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
+                int family, ifindex;
                 const void *a;
                 size_t sz;
 
-                r = sd_bus_message_read(reply, "i", &family);
+                assert_cc(sizeof(int32_t) == sizeof(int));
+
+                r = sd_bus_message_read(reply, "ii", &ifindex, &family);
                 if (r < 0)
                         goto fail;
 
+                if (ifindex < 0) {
+                        r = -EINVAL;
+                        goto fail;
+                }
+
                 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
                 if (r < 0)
                         goto fail;
@@ -287,9 +274,20 @@ enum nss_status _nss_resolve_gethostbyname4_r(
 
         return NSS_STATUS_SUCCESS;
 
+fallback:
+        fallback = (enum nss_status (*)(const char *name,
+                                        struct gaih_addrtuple **pat,
+                                        char *buffer, size_t buflen,
+                                        int *errnop, int *h_errnop,
+                                        int32_t *ttlp))
+                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r");
+
+        if (fallback)
+                return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp);
+
 fail:
         *errnop = -r;
-        *h_errnop = NO_DATA;
+        *h_errnop = NO_RECOVERY;
         return NSS_STATUS_UNAVAIL;
 }
 
@@ -302,13 +300,24 @@ enum nss_status _nss_resolve_gethostbyname3_r(
                 int32_t *ttlp,
                 char **canonp) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        enum nss_status (*fallback)(
+                        const char *name,
+                        int af,
+                        struct hostent *result,
+                        char *buffer, size_t buflen,
+                        int *errnop, int *h_errnop,
+                        int32_t *ttlp,
+                        char **canonp);
+
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char *r_name, *r_aliases, *r_addr, *r_addr_list;
-        _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         size_t l, idx, ms, alen;
         const char *canonical;
-        int c, r, i = 0, ifindex;
+        int c, r, i = 0;
+
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
 
         assert(name);
         assert(result);
@@ -326,7 +335,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
 
         r = sd_bus_open_system(&bus);
         if (r < 0)
-                goto fail;
+                goto fallback;
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -354,32 +363,10 @@ enum nss_status _nss_resolve_gethostbyname3_r(
                         return NSS_STATUS_NOTFOUND;
                 }
 
-                if (bus_error_shall_fallback(&error)) {
+                if (bus_error_shall_fallback(&error))
+                        goto fallback;
 
-                        enum nss_status (*fallback)(
-                                        const char *name,
-                                        int af,
-                                        struct hostent *result,
-                                        char *buffer, size_t buflen,
-                                        int *errnop, int *h_errnop,
-                                        int32_t *ttlp,
-                                        char **canonp);
-
-                        fallback = (enum nss_status (*)(const char *name,
-                                                        int af,
-                                                        struct hostent *result,
-                                                        char *buffer, size_t buflen,
-                                                        int *errnop, int *h_errnop,
-                                                        int32_t *ttlp,
-                                                        char **canonp))
-                                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r");
-                        if (fallback)
-                                return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
-                }
-
-                *errnop = -r;
-                *h_errnop = NO_RECOVERY;
-                return NSS_STATUS_UNAVAIL;
+                goto fail;
         }
 
         c = count_addresses(reply, af, &canonical);
@@ -420,28 +407,24 @@ enum nss_status _nss_resolve_gethostbyname3_r(
         /* Third, append addresses */
         r_addr = buffer + idx;
 
-        r = sd_bus_message_read(reply, "i", &ifindex);
-        if (r < 0)
-                goto fail;
-
-        if (ifindex < 0) {
-                r = -EINVAL;
-                goto fail;
-        }
-
-        r = sd_bus_message_enter_container(reply, 'a', "(iay)");
+        r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
         if (r < 0)
                 goto fail;
 
-        while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
-                int family;
+        while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
+                int ifindex, family;
                 const void *a;
                 size_t sz;
 
-                r = sd_bus_message_read(reply, "i", &family);
+                r = sd_bus_message_read(reply, "ii", &ifindex, &family);
                 if (r < 0)
                         goto fail;
 
+                if (ifindex < 0) {
+                        r = -EINVAL;
+                        goto fail;
+                }
+
                 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
                 if (r < 0)
                         goto fail;
@@ -496,9 +479,21 @@ enum nss_status _nss_resolve_gethostbyname3_r(
 
         return NSS_STATUS_SUCCESS;
 
+fallback:
+        fallback = (enum nss_status (*)(const char *name,
+                                        int af,
+                                        struct hostent *result,
+                                        char *buffer, size_t buflen,
+                                        int *errnop, int *h_errnop,
+                                        int32_t *ttlp,
+                                        char **canonp))
+                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r");
+        if (fallback)
+                return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
+
 fail:
         *errnop = -r;
-        *h_errnop = NO_DATA;
+        *h_errnop = NO_RECOVERY;
         return NSS_STATUS_UNAVAIL;
 }
 
@@ -510,15 +505,26 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
                 int *errnop, int *h_errnop,
                 int32_t *ttlp) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        enum nss_status (*fallback)(
+                        const void* addr, socklen_t len,
+                        int af,
+                        struct hostent *result,
+                        char *buffer, size_t buflen,
+                        int *errnop, int *h_errnop,
+                        int32_t *ttlp);
+
+
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char *r_name, *r_aliases, *r_addr, *r_addr_list;
-        _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         unsigned c = 0, i = 0;
         size_t ms = 0, idx;
         const char *n;
         int r, ifindex;
 
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
         assert(addr);
         assert(result);
         assert(buffer);
@@ -539,7 +545,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
 
         r = sd_bus_open_system(&bus);
         if (r < 0)
-                goto fail;
+                goto fallback;
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -575,48 +581,26 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
                         return NSS_STATUS_NOTFOUND;
                 }
 
-                if (bus_error_shall_fallback(&error)) {
-
-                        enum nss_status (*fallback)(
-                                        const void* addr, socklen_t len,
-                                        int af,
-                                        struct hostent *result,
-                                        char *buffer, size_t buflen,
-                                        int *errnop, int *h_errnop,
-                                        int32_t *ttlp);
-
-                        fallback = (enum nss_status (*)(
-                                        const void* addr, socklen_t len,
-                                        int af,
-                                        struct hostent *result,
-                                        char *buffer, size_t buflen,
-                                        int *errnop, int *h_errnop,
-                                        int32_t *ttlp))
-                                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyaddr2_r");
+                if (bus_error_shall_fallback(&error))
+                        goto fallback;
 
-                        if (fallback)
-                                return fallback(addr, len, af, result, buffer, buflen, errnop, h_errnop, ttlp);
-                }
 
                 *errnop = -r;
                 *h_errnop = NO_RECOVERY;
                 return NSS_STATUS_UNAVAIL;
         }
 
-        r = sd_bus_message_read(reply, "i", &ifindex);
+        r = sd_bus_message_enter_container(reply, 'a', "(is)");
         if (r < 0)
                 goto fail;
 
-        if (ifindex < 0) {
-                r = -EINVAL;
-                goto fail;
-        }
+        while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {
 
-        r = sd_bus_message_enter_container(reply, 'a', "s");
-        if (r < 0)
-                goto fail;
+                if (ifindex < 0) {
+                        r = -EINVAL;
+                        goto fail;
+                }
 
-        while ((r = sd_bus_message_read(reply, "s", &n)) > 0) {
                 c++;
                 ms += ALIGN(strlen(n) + 1);
         }
@@ -661,7 +645,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
         /* Fourth, place aliases */
         i = 0;
         r_name = buffer + idx;
-        while ((r = sd_bus_message_read(reply, "s", &n)) > 0) {
+        while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {
                 char *p;
                 size_t l;
 
@@ -669,7 +653,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
                 p = buffer + idx;
                 memcpy(p, n, l+1);
 
-                if (i > 1)
+                if (i > 0)
                         ((char**) r_aliases)[i-1] = p;
                 i++;
 
@@ -697,9 +681,22 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
 
         return NSS_STATUS_SUCCESS;
 
+fallback:
+        fallback = (enum nss_status (*)(
+                                    const void* addr, socklen_t len,
+                                    int af,
+                                    struct hostent *result,
+                                    char *buffer, size_t buflen,
+                                    int *errnop, int *h_errnop,
+                                    int32_t *ttlp))
+                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyaddr2_r");
+
+        if (fallback)
+                return fallback(addr, len, af, result, buffer, buflen, errnop, h_errnop, ttlp);
+
 fail:
         *errnop = -r;
-        *h_errnop = NO_DATA;
+        *h_errnop = NO_RECOVERY;
         return NSS_STATUS_UNAVAIL;
 }