LCOV - code coverage report
Current view: top level - nss-resolve - nss-resolve.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 379 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 10 0.0 %

          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