LCOV - code coverage report
Current view: top level - nss-resolve - nss-resolve.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 379 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 10 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 246 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <netdb.h>
       5                 :            : #include <nss.h>
       6                 :            : #include <stdlib.h>
       7                 :            : #include <string.h>
       8                 :            : #include <sys/types.h>
       9                 :            : #include <unistd.h>
      10                 :            : 
      11                 :            : #include "sd-bus.h"
      12                 :            : 
      13                 :            : #include "bus-common-errors.h"
      14                 :            : #include "errno-util.h"
      15                 :            : #include "in-addr-util.h"
      16                 :            : #include "macro.h"
      17                 :            : #include "nss-util.h"
      18                 :            : #include "resolved-def.h"
      19                 :            : #include "signal-util.h"
      20                 :            : #include "string-util.h"
      21                 :            : 
      22                 :            : NSS_GETHOSTBYNAME_PROTOTYPES(resolve);
      23                 :            : NSS_GETHOSTBYADDR_PROTOTYPES(resolve);
      24                 :            : 
      25                 :          0 : static bool bus_error_shall_fallback(sd_bus_error *e) {
      26         [ #  # ]:          0 :         return sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) ||
      27         [ #  # ]:          0 :                sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER) ||
      28         [ #  # ]:          0 :                sd_bus_error_has_name(e, SD_BUS_ERROR_NO_REPLY) ||
      29         [ #  # ]:          0 :                sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED) ||
      30   [ #  #  #  # ]:          0 :                sd_bus_error_has_name(e, SD_BUS_ERROR_DISCONNECTED) ||
      31                 :          0 :                sd_bus_error_has_name(e, SD_BUS_ERROR_TIMEOUT);
      32                 :            : }
      33                 :            : 
      34                 :          0 : static int count_addresses(sd_bus_message *m, int af, const char **canonical) {
      35                 :          0 :         int c = 0, r;
      36                 :            : 
      37         [ #  # ]:          0 :         assert(m);
      38         [ #  # ]:          0 :         assert(canonical);
      39                 :            : 
      40                 :          0 :         r = sd_bus_message_enter_container(m, 'a', "(iiay)");
      41         [ #  # ]:          0 :         if (r < 0)
      42                 :          0 :                 return r;
      43                 :            : 
      44         [ #  # ]:          0 :         while ((r = sd_bus_message_enter_container(m, 'r', "iiay")) > 0) {
      45                 :            :                 int family, ifindex;
      46                 :            : 
      47                 :            :                 assert_cc(sizeof(int32_t) == sizeof(int));
      48                 :            : 
      49                 :          0 :                 r = sd_bus_message_read(m, "ii", &ifindex, &family);
      50         [ #  # ]:          0 :                 if (r < 0)
      51                 :          0 :                         return r;
      52                 :            : 
      53                 :          0 :                 r = sd_bus_message_skip(m, "ay");
      54         [ #  # ]:          0 :                 if (r < 0)
      55                 :          0 :                         return r;
      56                 :            : 
      57                 :          0 :                 r = sd_bus_message_exit_container(m);
      58         [ #  # ]:          0 :                 if (r < 0)
      59                 :          0 :                         return r;
      60                 :            : 
      61   [ #  #  #  # ]:          0 :                 if (af != AF_UNSPEC && family != af)
      62                 :          0 :                         continue;
      63                 :            : 
      64                 :          0 :                 c++;
      65                 :            :         }
      66         [ #  # ]:          0 :         if (r < 0)
      67                 :          0 :                 return r;
      68                 :            : 
      69                 :          0 :         r = sd_bus_message_exit_container(m);
      70         [ #  # ]:          0 :         if (r < 0)
      71                 :          0 :                 return r;
      72                 :            : 
      73                 :          0 :         r = sd_bus_message_read(m, "s", canonical);
      74         [ #  # ]:          0 :         if (r < 0)
      75                 :          0 :                 return r;
      76                 :            : 
      77                 :          0 :         r = sd_bus_message_rewind(m, true);
      78         [ #  # ]:          0 :         if (r < 0)
      79                 :          0 :                 return r;
      80                 :            : 
      81                 :          0 :         return c;
      82                 :            : }
      83                 :            : 
      84                 :          0 : static uint32_t ifindex_to_scopeid(int family, const void *a, int ifindex) {
      85                 :            :         struct in6_addr in6;
      86                 :            : 
      87         [ #  # ]:          0 :         if (family != AF_INET6)
      88                 :          0 :                 return 0;
      89                 :            : 
      90                 :            :         /* Some apps can't deal with the scope ID attached to non-link-local addresses. Hence, let's suppress that. */
      91                 :            : 
      92         [ #  # ]:          0 :         assert(sizeof(in6) == FAMILY_ADDRESS_SIZE(AF_INET6));
      93                 :          0 :         memcpy(&in6, a, sizeof(struct in6_addr));
      94                 :            : 
      95         [ #  # ]:          0 :         return IN6_IS_ADDR_LINKLOCAL(&in6) ? ifindex : 0;
      96                 :            : }
      97                 :            : 
      98                 :          0 : static bool avoid_deadlock(void) {
      99                 :            : 
     100                 :            :         /* Check whether this lookup might have a chance of deadlocking because we are called from the service manager
     101                 :            :          * code activating systemd-resolved.service. After all, we shouldn't synchronously do lookups to
     102                 :            :          * systemd-resolved if we are required to finish before it can be started. This of course won't detect all
     103                 :            :          * possible dead locks of this kind, but it should work for the most obvious cases. */
     104                 :            : 
     105         [ #  # ]:          0 :         if (geteuid() != 0) /* Ignore the env vars unless we are privileged. */
     106                 :          0 :                 return false;
     107                 :            : 
     108   [ #  #  #  # ]:          0 :         return streq_ptr(getenv("SYSTEMD_ACTIVATION_UNIT"), "systemd-resolved.service") &&
     109                 :          0 :                streq_ptr(getenv("SYSTEMD_ACTIVATION_SCOPE"), "system");
     110                 :            : }
     111                 :            : 
     112                 :          0 : enum nss_status _nss_resolve_gethostbyname4_r(
     113                 :            :                 const char *name,
     114                 :            :                 struct gaih_addrtuple **pat,
     115                 :            :                 char *buffer, size_t buflen,
     116                 :            :                 int *errnop, int *h_errnop,
     117                 :            :                 int32_t *ttlp) {
     118                 :            : 
     119                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
     120                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     121                 :          0 :         struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
     122                 :          0 :         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
     123                 :          0 :         const char *canonical = NULL;
     124                 :            :         size_t l, ms, idx;
     125                 :            :         char *r_name;
     126                 :          0 :         int c, r, i = 0;
     127                 :            : 
     128                 :          0 :         PROTECT_ERRNO;
     129         [ #  # ]:          0 :         BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
     130                 :            : 
     131         [ #  # ]:          0 :         assert(name);
     132         [ #  # ]:          0 :         assert(pat);
     133         [ #  # ]:          0 :         assert(buffer);
     134         [ #  # ]:          0 :         assert(errnop);
     135         [ #  # ]:          0 :         assert(h_errnop);
     136                 :            : 
     137         [ #  # ]:          0 :         if (avoid_deadlock()) {
     138                 :          0 :                 r = -EDEADLK;
     139                 :          0 :                 goto fail;
     140                 :            :         }
     141                 :            : 
     142                 :          0 :         r = sd_bus_open_system(&bus);
     143         [ #  # ]:          0 :         if (r < 0)
     144                 :          0 :                 goto fail;
     145                 :            : 
     146                 :          0 :         r = sd_bus_message_new_method_call(
     147                 :            :                         bus,
     148                 :            :                         &req,
     149                 :            :                         "org.freedesktop.resolve1",
     150                 :            :                         "/org/freedesktop/resolve1",
     151                 :            :                         "org.freedesktop.resolve1.Manager",
     152                 :            :                         "ResolveHostname");
     153         [ #  # ]:          0 :         if (r < 0)
     154                 :          0 :                 goto fail;
     155                 :            : 
     156                 :          0 :         r = sd_bus_message_set_auto_start(req, false);
     157         [ #  # ]:          0 :         if (r < 0)
     158                 :          0 :                 goto fail;
     159                 :            : 
     160                 :          0 :         r = sd_bus_message_append(req, "isit", 0, name, AF_UNSPEC, (uint64_t) 0);
     161         [ #  # ]:          0 :         if (r < 0)
     162                 :          0 :                 goto fail;
     163                 :            : 
     164                 :          0 :         r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
     165         [ #  # ]:          0 :         if (r < 0) {
     166         [ #  # ]:          0 :                 if (!bus_error_shall_fallback(&error))
     167                 :          0 :                         goto not_found;
     168                 :            : 
     169                 :            :                 /* Return NSS_STATUS_UNAVAIL when communication with systemd-resolved fails,
     170                 :            :                    allowing falling back to other nss modules. Treat all other error conditions as
     171                 :            :                    NOTFOUND. This includes DNSSEC errors and suchlike. (We don't use UNAVAIL in this
     172                 :            :                    case so that the nsswitch.conf configuration can distinguish such executed but
     173                 :            :                    negative replies from complete failure to talk to resolved). */
     174                 :          0 :                 goto fail;
     175                 :            :         }
     176                 :            : 
     177                 :          0 :         c = count_addresses(reply, AF_UNSPEC, &canonical);
     178         [ #  # ]:          0 :         if (c < 0) {
     179                 :          0 :                 r = c;
     180                 :          0 :                 goto fail;
     181                 :            :         }
     182         [ #  # ]:          0 :         if (c == 0)
     183                 :          0 :                 goto not_found;
     184                 :            : 
     185         [ #  # ]:          0 :         if (isempty(canonical))
     186                 :          0 :                 canonical = name;
     187                 :            : 
     188                 :          0 :         l = strlen(canonical);
     189                 :          0 :         ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
     190         [ #  # ]:          0 :         if (buflen < ms) {
     191                 :          0 :                 UNPROTECT_ERRNO;
     192                 :          0 :                 *errnop = ERANGE;
     193                 :          0 :                 *h_errnop = NETDB_INTERNAL;
     194                 :          0 :                 return NSS_STATUS_TRYAGAIN;
     195                 :            :         }
     196                 :            : 
     197                 :            :         /* First, append name */
     198                 :          0 :         r_name = buffer;
     199                 :          0 :         memcpy(r_name, canonical, l+1);
     200                 :          0 :         idx = ALIGN(l+1);
     201                 :            : 
     202                 :            :         /* Second, append addresses */
     203                 :          0 :         r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);
     204                 :            : 
     205                 :          0 :         r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
     206         [ #  # ]:          0 :         if (r < 0)
     207                 :          0 :                 goto fail;
     208                 :            : 
     209         [ #  # ]:          0 :         while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
     210                 :            :                 int family, ifindex;
     211                 :            :                 const void *a;
     212                 :            :                 size_t sz;
     213                 :            : 
     214                 :            :                 assert_cc(sizeof(int32_t) == sizeof(int));
     215                 :            : 
     216                 :          0 :                 r = sd_bus_message_read(reply, "ii", &ifindex, &family);
     217         [ #  # ]:          0 :                 if (r < 0)
     218                 :          0 :                         goto fail;
     219                 :            : 
     220         [ #  # ]:          0 :                 if (ifindex < 0) {
     221                 :          0 :                         r = -EINVAL;
     222                 :          0 :                         goto fail;
     223                 :            :                 }
     224                 :            : 
     225                 :          0 :                 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
     226         [ #  # ]:          0 :                 if (r < 0)
     227                 :          0 :                         goto fail;
     228                 :            : 
     229                 :          0 :                 r = sd_bus_message_exit_container(reply);
     230         [ #  # ]:          0 :                 if (r < 0)
     231                 :          0 :                         goto fail;
     232                 :            : 
     233   [ #  #  #  # ]:          0 :                 if (!IN_SET(family, AF_INET, AF_INET6))
     234                 :          0 :                         continue;
     235                 :            : 
     236         [ #  # ]:          0 :                 if (sz != FAMILY_ADDRESS_SIZE(family)) {
     237                 :          0 :                         r = -EINVAL;
     238                 :          0 :                         goto fail;
     239                 :            :                 }
     240                 :            : 
     241                 :          0 :                 r_tuple = (struct gaih_addrtuple*) (buffer + idx);
     242         [ #  # ]:          0 :                 r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple)));
     243                 :          0 :                 r_tuple->name = r_name;
     244                 :          0 :                 r_tuple->family = family;
     245                 :          0 :                 r_tuple->scopeid = ifindex_to_scopeid(family, a, ifindex);
     246                 :          0 :                 memcpy(r_tuple->addr, a, sz);
     247                 :            : 
     248                 :          0 :                 idx += ALIGN(sizeof(struct gaih_addrtuple));
     249                 :          0 :                 i++;
     250                 :            :         }
     251         [ #  # ]:          0 :         if (r < 0)
     252                 :          0 :                 goto fail;
     253                 :            : 
     254         [ #  # ]:          0 :         assert(i == c);
     255         [ #  # ]:          0 :         assert(idx == ms);
     256                 :            : 
     257         [ #  # ]:          0 :         if (*pat)
     258                 :          0 :                 **pat = *r_tuple_first;
     259                 :            :         else
     260                 :          0 :                 *pat = r_tuple_first;
     261                 :            : 
     262         [ #  # ]:          0 :         if (ttlp)
     263                 :          0 :                 *ttlp = 0;
     264                 :            : 
     265                 :            :         /* Explicitly reset both *h_errnop and h_errno to work around
     266                 :            :          * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
     267                 :          0 :         *h_errnop = NETDB_SUCCESS;
     268                 :          0 :         h_errno = 0;
     269                 :            : 
     270                 :          0 :         return NSS_STATUS_SUCCESS;
     271                 :            : 
     272                 :          0 : fail:
     273                 :          0 :         UNPROTECT_ERRNO;
     274                 :          0 :         *errnop = -r;
     275                 :          0 :         *h_errnop = NO_RECOVERY;
     276                 :          0 :         return NSS_STATUS_UNAVAIL;
     277                 :            : 
     278                 :          0 : not_found:
     279                 :          0 :         *h_errnop = HOST_NOT_FOUND;
     280                 :          0 :         return NSS_STATUS_NOTFOUND;
     281                 :            : }
     282                 :            : 
     283                 :          0 : enum nss_status _nss_resolve_gethostbyname3_r(
     284                 :            :                 const char *name,
     285                 :            :                 int af,
     286                 :            :                 struct hostent *result,
     287                 :            :                 char *buffer, size_t buflen,
     288                 :            :                 int *errnop, int *h_errnop,
     289                 :            :                 int32_t *ttlp,
     290                 :            :                 char **canonp) {
     291                 :            : 
     292                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
     293                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     294                 :            :         char *r_name, *r_aliases, *r_addr, *r_addr_list;
     295                 :          0 :         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
     296                 :            :         size_t l, idx, ms, alen;
     297                 :            :         const char *canonical;
     298                 :          0 :         int c, r, i = 0;
     299                 :            : 
     300                 :          0 :         PROTECT_ERRNO;
     301         [ #  # ]:          0 :         BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
     302                 :            : 
     303         [ #  # ]:          0 :         assert(name);
     304         [ #  # ]:          0 :         assert(result);
     305         [ #  # ]:          0 :         assert(buffer);
     306         [ #  # ]:          0 :         assert(errnop);
     307         [ #  # ]:          0 :         assert(h_errnop);
     308                 :            : 
     309         [ #  # ]:          0 :         if (af == AF_UNSPEC)
     310                 :          0 :                 af = AF_INET;
     311                 :            : 
     312   [ #  #  #  # ]:          0 :         if (!IN_SET(af, AF_INET, AF_INET6)) {
     313                 :          0 :                 r = -EAFNOSUPPORT;
     314                 :          0 :                 goto fail;
     315                 :            :         }
     316                 :            : 
     317         [ #  # ]:          0 :         if (avoid_deadlock()) {
     318                 :          0 :                 r = -EDEADLK;
     319                 :          0 :                 goto fail;
     320                 :            :         }
     321                 :            : 
     322                 :          0 :         r = sd_bus_open_system(&bus);
     323         [ #  # ]:          0 :         if (r < 0)
     324                 :          0 :                 goto fail;
     325                 :            : 
     326                 :          0 :         r = sd_bus_message_new_method_call(
     327                 :            :                         bus,
     328                 :            :                         &req,
     329                 :            :                         "org.freedesktop.resolve1",
     330                 :            :                         "/org/freedesktop/resolve1",
     331                 :            :                         "org.freedesktop.resolve1.Manager",
     332                 :            :                         "ResolveHostname");
     333         [ #  # ]:          0 :         if (r < 0)
     334                 :          0 :                 goto fail;
     335                 :            : 
     336                 :          0 :         r = sd_bus_message_set_auto_start(req, false);
     337         [ #  # ]:          0 :         if (r < 0)
     338                 :          0 :                 goto fail;
     339                 :            : 
     340                 :          0 :         r = sd_bus_message_append(req, "isit", 0, name, af, (uint64_t) 0);
     341         [ #  # ]:          0 :         if (r < 0)
     342                 :          0 :                 goto fail;
     343                 :            : 
     344                 :          0 :         r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
     345         [ #  # ]:          0 :         if (r < 0) {
     346         [ #  # ]:          0 :                 if (!bus_error_shall_fallback(&error))
     347                 :          0 :                         goto not_found;
     348                 :            : 
     349                 :          0 :                 goto fail;
     350                 :            :         }
     351                 :            : 
     352                 :          0 :         c = count_addresses(reply, af, &canonical);
     353         [ #  # ]:          0 :         if (c < 0) {
     354                 :          0 :                 r = c;
     355                 :          0 :                 goto fail;
     356                 :            :         }
     357         [ #  # ]:          0 :         if (c == 0)
     358                 :          0 :                 goto not_found;
     359                 :            : 
     360         [ #  # ]:          0 :         if (isempty(canonical))
     361                 :          0 :                 canonical = name;
     362                 :            : 
     363                 :          0 :         alen = FAMILY_ADDRESS_SIZE(af);
     364                 :          0 :         l = strlen(canonical);
     365                 :            : 
     366                 :          0 :         ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);
     367                 :            : 
     368         [ #  # ]:          0 :         if (buflen < ms) {
     369                 :          0 :                 UNPROTECT_ERRNO;
     370                 :          0 :                 *errnop = ERANGE;
     371                 :          0 :                 *h_errnop = NETDB_INTERNAL;
     372                 :          0 :                 return NSS_STATUS_TRYAGAIN;
     373                 :            :         }
     374                 :            : 
     375                 :            :         /* First, append name */
     376                 :          0 :         r_name = buffer;
     377                 :          0 :         memcpy(r_name, canonical, l+1);
     378                 :          0 :         idx = ALIGN(l+1);
     379                 :            : 
     380                 :            :         /* Second, create empty aliases array */
     381                 :          0 :         r_aliases = buffer + idx;
     382                 :          0 :         ((char**) r_aliases)[0] = NULL;
     383                 :          0 :         idx += sizeof(char*);
     384                 :            : 
     385                 :            :         /* Third, append addresses */
     386                 :          0 :         r_addr = buffer + idx;
     387                 :            : 
     388                 :          0 :         r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
     389         [ #  # ]:          0 :         if (r < 0)
     390                 :          0 :                 goto fail;
     391                 :            : 
     392         [ #  # ]:          0 :         while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
     393                 :            :                 int ifindex, family;
     394                 :            :                 const void *a;
     395                 :            :                 size_t sz;
     396                 :            : 
     397                 :          0 :                 r = sd_bus_message_read(reply, "ii", &ifindex, &family);
     398         [ #  # ]:          0 :                 if (r < 0)
     399                 :          0 :                         goto fail;
     400                 :            : 
     401         [ #  # ]:          0 :                 if (ifindex < 0) {
     402                 :          0 :                         r = -EINVAL;
     403                 :          0 :                         goto fail;
     404                 :            :                 }
     405                 :            : 
     406                 :          0 :                 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
     407         [ #  # ]:          0 :                 if (r < 0)
     408                 :          0 :                         goto fail;
     409                 :            : 
     410                 :          0 :                 r = sd_bus_message_exit_container(reply);
     411         [ #  # ]:          0 :                 if (r < 0)
     412                 :          0 :                         goto fail;
     413                 :            : 
     414         [ #  # ]:          0 :                 if (family != af)
     415                 :          0 :                         continue;
     416                 :            : 
     417         [ #  # ]:          0 :                 if (sz != alen) {
     418                 :          0 :                         r = -EINVAL;
     419                 :          0 :                         goto fail;
     420                 :            :                 }
     421                 :            : 
     422                 :          0 :                 memcpy(r_addr + i*ALIGN(alen), a, alen);
     423                 :          0 :                 i++;
     424                 :            :         }
     425         [ #  # ]:          0 :         if (r < 0)
     426                 :          0 :                 goto fail;
     427                 :            : 
     428         [ #  # ]:          0 :         assert(i == c);
     429                 :          0 :         idx += c * ALIGN(alen);
     430                 :            : 
     431                 :            :         /* Fourth, append address pointer array */
     432                 :          0 :         r_addr_list = buffer + idx;
     433         [ #  # ]:          0 :         for (i = 0; i < c; i++)
     434                 :          0 :                 ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);
     435                 :            : 
     436                 :          0 :         ((char**) r_addr_list)[i] = NULL;
     437                 :          0 :         idx += (c+1) * sizeof(char*);
     438                 :            : 
     439         [ #  # ]:          0 :         assert(idx == ms);
     440                 :            : 
     441                 :          0 :         result->h_name = r_name;
     442                 :          0 :         result->h_aliases = (char**) r_aliases;
     443                 :          0 :         result->h_addrtype = af;
     444                 :          0 :         result->h_length = alen;
     445                 :          0 :         result->h_addr_list = (char**) r_addr_list;
     446                 :            : 
     447         [ #  # ]:          0 :         if (ttlp)
     448                 :          0 :                 *ttlp = 0;
     449                 :            : 
     450         [ #  # ]:          0 :         if (canonp)
     451                 :          0 :                 *canonp = r_name;
     452                 :            : 
     453                 :            :         /* Explicitly reset both *h_errnop and h_errno to work around
     454                 :            :          * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
     455                 :          0 :         *h_errnop = NETDB_SUCCESS;
     456                 :          0 :         h_errno = 0;
     457                 :            : 
     458                 :          0 :         return NSS_STATUS_SUCCESS;
     459                 :            : 
     460                 :          0 : fail:
     461                 :          0 :         UNPROTECT_ERRNO;
     462                 :          0 :         *errnop = -r;
     463                 :          0 :         *h_errnop = NO_RECOVERY;
     464                 :          0 :         return NSS_STATUS_UNAVAIL;
     465                 :            : 
     466                 :          0 : not_found:
     467                 :          0 :         *h_errnop = HOST_NOT_FOUND;
     468                 :          0 :         return NSS_STATUS_NOTFOUND;
     469                 :            : }
     470                 :            : 
     471                 :          0 : enum nss_status _nss_resolve_gethostbyaddr2_r(
     472                 :            :                 const void* addr, socklen_t len,
     473                 :            :                 int af,
     474                 :            :                 struct hostent *result,
     475                 :            :                 char *buffer, size_t buflen,
     476                 :            :                 int *errnop, int *h_errnop,
     477                 :            :                 int32_t *ttlp) {
     478                 :            : 
     479                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
     480                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     481                 :            :         char *r_name, *r_aliases, *r_addr, *r_addr_list;
     482                 :          0 :         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
     483                 :          0 :         unsigned c = 0, i = 0;
     484                 :          0 :         size_t ms = 0, idx;
     485                 :            :         const char *n;
     486                 :            :         int r, ifindex;
     487                 :            : 
     488                 :          0 :         PROTECT_ERRNO;
     489         [ #  # ]:          0 :         BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
     490                 :            : 
     491         [ #  # ]:          0 :         assert(addr);
     492         [ #  # ]:          0 :         assert(result);
     493         [ #  # ]:          0 :         assert(buffer);
     494         [ #  # ]:          0 :         assert(errnop);
     495         [ #  # ]:          0 :         assert(h_errnop);
     496                 :            : 
     497   [ #  #  #  # ]:          0 :         if (!IN_SET(af, AF_INET, AF_INET6)) {
     498                 :          0 :                 UNPROTECT_ERRNO;
     499                 :          0 :                 *errnop = EAFNOSUPPORT;
     500                 :          0 :                 *h_errnop = NO_DATA;
     501                 :          0 :                 return NSS_STATUS_UNAVAIL;
     502                 :            :         }
     503                 :            : 
     504         [ #  # ]:          0 :         if (len != FAMILY_ADDRESS_SIZE(af)) {
     505                 :          0 :                 r = -EINVAL;
     506                 :          0 :                 goto fail;
     507                 :            :         }
     508                 :            : 
     509         [ #  # ]:          0 :         if (avoid_deadlock()) {
     510                 :          0 :                 r = -EDEADLK;
     511                 :          0 :                 goto fail;
     512                 :            :         }
     513                 :            : 
     514                 :          0 :         r = sd_bus_open_system(&bus);
     515         [ #  # ]:          0 :         if (r < 0)
     516                 :          0 :                 goto fail;
     517                 :            : 
     518                 :          0 :         r = sd_bus_message_new_method_call(
     519                 :            :                         bus,
     520                 :            :                         &req,
     521                 :            :                         "org.freedesktop.resolve1",
     522                 :            :                         "/org/freedesktop/resolve1",
     523                 :            :                         "org.freedesktop.resolve1.Manager",
     524                 :            :                         "ResolveAddress");
     525         [ #  # ]:          0 :         if (r < 0)
     526                 :          0 :                 goto fail;
     527                 :            : 
     528                 :          0 :         r = sd_bus_message_set_auto_start(req, false);
     529         [ #  # ]:          0 :         if (r < 0)
     530                 :          0 :                 goto fail;
     531                 :            : 
     532                 :          0 :         r = sd_bus_message_append(req, "ii", 0, af);
     533         [ #  # ]:          0 :         if (r < 0)
     534                 :          0 :                 goto fail;
     535                 :            : 
     536                 :          0 :         r = sd_bus_message_append_array(req, 'y', addr, len);
     537         [ #  # ]:          0 :         if (r < 0)
     538                 :          0 :                 goto fail;
     539                 :            : 
     540                 :          0 :         r = sd_bus_message_append(req, "t", (uint64_t) 0);
     541         [ #  # ]:          0 :         if (r < 0)
     542                 :          0 :                 goto fail;
     543                 :            : 
     544                 :          0 :         r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
     545         [ #  # ]:          0 :         if (r < 0) {
     546         [ #  # ]:          0 :                 if (!bus_error_shall_fallback(&error))
     547                 :          0 :                         goto not_found;
     548                 :            : 
     549                 :          0 :                 goto fail;
     550                 :            :         }
     551                 :            : 
     552                 :          0 :         r = sd_bus_message_enter_container(reply, 'a', "(is)");
     553         [ #  # ]:          0 :         if (r < 0)
     554                 :          0 :                 goto fail;
     555                 :            : 
     556         [ #  # ]:          0 :         while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {
     557                 :            : 
     558         [ #  # ]:          0 :                 if (ifindex < 0) {
     559                 :          0 :                         r = -EINVAL;
     560                 :          0 :                         goto fail;
     561                 :            :                 }
     562                 :            : 
     563                 :          0 :                 c++;
     564                 :          0 :                 ms += ALIGN(strlen(n) + 1);
     565                 :            :         }
     566         [ #  # ]:          0 :         if (r < 0)
     567                 :          0 :                 goto fail;
     568                 :            : 
     569                 :          0 :         r = sd_bus_message_rewind(reply, false);
     570         [ #  # ]:          0 :         if (r < 0)
     571                 :          0 :                 goto fail;
     572                 :            : 
     573         [ #  # ]:          0 :         if (c <= 0)
     574                 :          0 :                 goto not_found;
     575                 :            : 
     576                 :          0 :         ms += ALIGN(len) +              /* the address */
     577                 :          0 :               2 * sizeof(char*) +       /* pointers to the address, plus trailing NULL */
     578                 :          0 :               c * sizeof(char*);        /* pointers to aliases, plus trailing NULL */
     579                 :            : 
     580         [ #  # ]:          0 :         if (buflen < ms) {
     581                 :          0 :                 UNPROTECT_ERRNO;
     582                 :          0 :                 *errnop = ERANGE;
     583                 :          0 :                 *h_errnop = NETDB_INTERNAL;
     584                 :          0 :                 return NSS_STATUS_TRYAGAIN;
     585                 :            :         }
     586                 :            : 
     587                 :            :         /* First, place address */
     588                 :          0 :         r_addr = buffer;
     589                 :          0 :         memcpy(r_addr, addr, len);
     590                 :          0 :         idx = ALIGN(len);
     591                 :            : 
     592                 :            :         /* Second, place address list */
     593                 :          0 :         r_addr_list = buffer + idx;
     594                 :          0 :         ((char**) r_addr_list)[0] = r_addr;
     595                 :          0 :         ((char**) r_addr_list)[1] = NULL;
     596                 :          0 :         idx += sizeof(char*) * 2;
     597                 :            : 
     598                 :            :         /* Third, reserve space for the aliases array */
     599                 :          0 :         r_aliases = buffer + idx;
     600                 :          0 :         idx += sizeof(char*) * c;
     601                 :            : 
     602                 :            :         /* Fourth, place aliases */
     603                 :          0 :         i = 0;
     604                 :          0 :         r_name = buffer + idx;
     605         [ #  # ]:          0 :         while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {
     606                 :            :                 char *p;
     607                 :            :                 size_t l;
     608                 :            : 
     609                 :          0 :                 l = strlen(n);
     610                 :          0 :                 p = buffer + idx;
     611                 :          0 :                 memcpy(p, n, l+1);
     612                 :            : 
     613         [ #  # ]:          0 :                 if (i > 0)
     614                 :          0 :                         ((char**) r_aliases)[i-1] = p;
     615                 :          0 :                 i++;
     616                 :            : 
     617                 :          0 :                 idx += ALIGN(l+1);
     618                 :            :         }
     619         [ #  # ]:          0 :         if (r < 0)
     620                 :          0 :                 goto fail;
     621                 :            : 
     622                 :          0 :         ((char**) r_aliases)[c-1] = NULL;
     623         [ #  # ]:          0 :         assert(idx == ms);
     624                 :            : 
     625                 :          0 :         result->h_name = r_name;
     626                 :          0 :         result->h_aliases = (char**) r_aliases;
     627                 :          0 :         result->h_addrtype = af;
     628                 :          0 :         result->h_length = len;
     629                 :          0 :         result->h_addr_list = (char**) r_addr_list;
     630                 :            : 
     631         [ #  # ]:          0 :         if (ttlp)
     632                 :          0 :                 *ttlp = 0;
     633                 :            : 
     634                 :            :         /* Explicitly reset both *h_errnop and h_errno to work around
     635                 :            :          * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
     636                 :          0 :         *h_errnop = NETDB_SUCCESS;
     637                 :          0 :         h_errno = 0;
     638                 :            : 
     639                 :          0 :         return NSS_STATUS_SUCCESS;
     640                 :            : 
     641                 :          0 : fail:
     642                 :          0 :         UNPROTECT_ERRNO;
     643                 :          0 :         *errnop = -r;
     644                 :          0 :         *h_errnop = NO_RECOVERY;
     645                 :          0 :         return NSS_STATUS_UNAVAIL;
     646                 :            : 
     647                 :          0 : not_found:
     648                 :          0 :         *h_errnop = HOST_NOT_FOUND;
     649                 :          0 :         return NSS_STATUS_NOTFOUND;
     650                 :            : }
     651                 :            : 
     652   [ #  #  #  # ]:          0 : NSS_GETHOSTBYNAME_FALLBACKS(resolve);
     653                 :          0 : NSS_GETHOSTBYADDR_FALLBACKS(resolve);

Generated by: LCOV version 1.14