]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nss-myhostname: do not return IPv6 local address if IPv6 is disabled
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 22 Apr 2022 01:31:22 +0000 (10:31 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 22 Apr 2022 19:18:51 +0000 (04:18 +0900)
src/nss-myhostname/nss-myhostname.c

index 67b1554d278082aafe9ebc384ef7dbc89cdd4cd9..120e76be45c013f7fe46d4cfc62cd7751e3888cc 100644 (file)
@@ -13,6 +13,7 @@
 #include "macro.h"
 #include "nss-util.h"
 #include "signal-util.h"
+#include "socket-util.h"
 #include "string-util.h"
 
 /* We use 127.0.0.2 as IPv4 address. This has the advantage over
@@ -95,7 +96,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
         }
 
         l = strlen(canonical);
-        ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * (n_addresses > 0 ? n_addresses : 2);
+        ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * (n_addresses > 0 ? n_addresses : 1 + socket_ipv6_is_enabled());
         if (buflen < ms) {
                 UNPROTECT_ERRNO;
                 *errnop = ERANGE;
@@ -111,15 +112,17 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
         assert(n_addresses >= 0);
         if (n_addresses == 0) {
                 /* Second, fill in IPv6 tuple */
-                r_tuple = (struct gaih_addrtuple*) (buffer + idx);
-                r_tuple->next = r_tuple_prev;
-                r_tuple->name = r_name;
-                r_tuple->family = AF_INET6;
-                memcpy(r_tuple->addr, LOCALADDRESS_IPV6, 16);
-                r_tuple->scopeid = 0;
-
-                idx += ALIGN(sizeof(struct gaih_addrtuple));
-                r_tuple_prev = r_tuple;
+                if (socket_ipv6_is_enabled()) {
+                        r_tuple = (struct gaih_addrtuple*) (buffer + idx);
+                        r_tuple->next = r_tuple_prev;
+                        r_tuple->name = r_name;
+                        r_tuple->family = AF_INET6;
+                        memcpy(r_tuple->addr, LOCALADDRESS_IPV6, 16);
+                        r_tuple->scopeid = 0;
+
+                        idx += ALIGN(sizeof(struct gaih_addrtuple));
+                        r_tuple_prev = r_tuple;
+                }
 
                 /* Third, fill in IPv4 tuple */
                 r_tuple = (struct gaih_addrtuple*) (buffer + idx);
@@ -189,6 +192,7 @@ static enum nss_status fill_in_hostent(
         unsigned n, c;
 
         assert(canonical);
+        assert(IN_SET(af, AF_INET, AF_INET6));
         assert(result);
         assert(buffer);
         assert(errnop);
@@ -208,8 +212,8 @@ static enum nss_status fill_in_hostent(
                 (additional ? ALIGN(l_additional+1) : 0) +
                 sizeof(char*) +
                 (additional ? sizeof(char*) : 0) +
-                (c > 0 ? c : 1) * ALIGN(alen) +
-                (c > 0 ? c+1 : 2) * sizeof(char*);
+                (c > 0 ? c : af == AF_INET ? 1 : socket_ipv6_is_enabled()) * ALIGN(alen) +
+                (c > 0 ? c+1 : af == AF_INET ? 2 : (unsigned) socket_ipv6_is_enabled() + 1) * sizeof(char*);
 
         if (buflen < ms) {
                 UNPROTECT_ERRNO;
@@ -255,12 +259,12 @@ static enum nss_status fill_in_hostent(
 
                 assert(i == c);
                 idx += c*ALIGN(alen);
-        } else {
-                if (af == AF_INET)
-                        *(uint32_t*) r_addr = local_address_ipv4;
-                else
-                        memcpy(r_addr, LOCALADDRESS_IPV6, 16);
 
+        } else if (af == AF_INET) {
+                *(uint32_t*) r_addr = local_address_ipv4;
+                idx += ALIGN(alen);
+        } else if (socket_ipv6_is_enabled()) {
+                memcpy(r_addr, LOCALADDRESS_IPV6, 16);
                 idx += ALIGN(alen);
         }
 
@@ -275,10 +279,13 @@ static enum nss_status fill_in_hostent(
                 ((char**) r_addr_list)[i] = NULL;
                 idx += (c+1) * sizeof(char*);
 
-        } else {
+        } else if (af == AF_INET || socket_ipv6_is_enabled()) {
                 ((char**) r_addr_list)[0] = r_addr;
                 ((char**) r_addr_list)[1] = NULL;
                 idx += 2 * sizeof(char*);
+        } else {
+                ((char**) r_addr_list)[0] = NULL;
+                idx += sizeof(char*);
         }
 
         /* Verify the size matches */
@@ -339,6 +346,9 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
         }
 
         if (is_localhost(name)) {
+                if (af == AF_INET6 && !socket_ipv6_is_enabled())
+                        goto not_found;
+
                 canonical = "localhost";
                 local_address_ipv4 = htobe32(INADDR_LOOPBACK);
 
@@ -450,6 +460,9 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r(
         } else {
                 assert(af == AF_INET6);
 
+                if (socket_ipv6_is_enabled())
+                        goto not_found;
+
                 if (memcmp(addr, LOCALADDRESS_IPV6, 16) == 0) {
                         canonical = "localhost";
                         additional_from_hostname = true;
@@ -457,28 +470,21 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r(
                 }
         }
 
-        n_addresses = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
-        for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) {
-                if (af != a->family)
-                        continue;
-
+        n_addresses = local_addresses(NULL, 0, af, &addresses);
+        for (a = addresses, n = 0; (int) n < n_addresses; n++, a++)
                 if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0)
                         goto found;
-        }
 
         addresses = mfree(addresses);
 
-        n_addresses = local_gateways(NULL, 0, AF_UNSPEC, &addresses);
-        for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) {
-                if (af != a->family)
-                        continue;
-
+        n_addresses = local_gateways(NULL, 0, af, &addresses);
+        for (a = addresses, n = 0; (int) n < n_addresses; n++, a++)
                 if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) {
                         canonical = "_gateway";
                         goto found;
                 }
-        }
 
+not_found:
         *h_errnop = HOST_NOT_FOUND;
         return NSS_STATUS_NOTFOUND;