about summary refs log tree commit diff
path: root/nixpkgs/nixos
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2021-04-12 15:42:03 +0000
committerAlyssa Ross <hi@alyssa.is>2023-06-05 20:43:39 +0000
commitf62b3d09304a92d1b0f4a4645fcbe555df2c2187 (patch)
treebb93d0561ac52ca6f372ad4cd44e497f3e6e1571 /nixpkgs/nixos
parentb06375f67f8f494769605e194a6913f396a3b31c (diff)
downloadnixlib-f62b3d09304a92d1b0f4a4645fcbe555df2c2187.tar
nixlib-f62b3d09304a92d1b0f4a4645fcbe555df2c2187.tar.gz
nixlib-f62b3d09304a92d1b0f4a4645fcbe555df2c2187.tar.bz2
nixlib-f62b3d09304a92d1b0f4a4645fcbe555df2c2187.tar.lz
nixlib-f62b3d09304a92d1b0f4a4645fcbe555df2c2187.tar.xz
nixlib-f62b3d09304a92d1b0f4a4645fcbe555df2c2187.tar.zst
nixlib-f62b3d09304a92d1b0f4a4645fcbe555df2c2187.zip
nixos/networking: use one line per IP in /etc/hosts
From hosts(5) (emphasis mine):

> For each host a *single* line should be present with the following
> information:

Prior to this change, my hosts file looked like this:

      127.0.0.1 localhost
      ::1 localhost
      127.0.0.2 atuin.qyliss.net atuin
      ::1 atuin.qyliss.net atuin

After this change, it looks like this:

      127.0.0.1 localhost
      ::1 localhost atuin.qyliss.net atuin
      127.0.0.2 atuin.qyliss.net atuin

Having multiple lines for the same IP breaks glibc's gethostbyaddr.
The easiest way to demonstrate this is with Python, but a simplified C
program is provided at the end of this message too.

	$ python3 -c 'import socket; print(socket.gethostbyaddr("::1"))'
	('localhost', [], ['::1'])

With this fix applied:

	$ python3 -c 'import socket; print(socket.gethostbyaddr("::1"))'
	('localhost', ['atuin.qyliss.net', 'atuin'], ['::1'])

As a higher level example, socket.getfqdn() will return 'localhost'
without this change, and 'atuin.qyliss.net' with it.  This was
responsible for my Mailman instance sending mail with @localhost in
the Message-Id.

C program:

#include <err.h>
#include <netdb.h>
#include <sysexits.h>
#include <stdio.h>

int main(void)
{
        struct in6_addr addr = { 0 };
        addr.s6_addr[sizeof addr.s6_addr - 1] = 1; // ::1

        struct hostent *host = gethostbyaddr(&addr, sizeof addr, AF_INET6);
        if (!host)
                err(EX_OSERR, "gethostbyaddr: %s", hstrerror(h_errno));

        printf("name: %s\n", host->h_name);

        size_t n;
        for (n = 0; host->h_aliases[n]; n++);

        printf("aliases (%zu):", n);

        for (size_t i = 0; i < n; i++)
                printf(" %s", host->h_aliases[i]);

        printf("\n");
}
Diffstat (limited to 'nixpkgs/nixos')
-rw-r--r--nixpkgs/nixos/modules/config/networking.nix12
1 files changed, 6 insertions, 6 deletions
diff --git a/nixpkgs/nixos/modules/config/networking.nix b/nixpkgs/nixos/modules/config/networking.nix
index 185eff746de0..6f899d74db25 100644
--- a/nixpkgs/nixos/modules/config/networking.nix
+++ b/nixpkgs/nixos/modules/config/networking.nix
@@ -176,17 +176,17 @@ in
       # resolves back to "localhost" (as some applications assume) instead of
       # the FQDN! By default "networking.hosts" also contains entries for the
       # FQDN so that e.g. "hostname -f" works correctly.
-      localhostHosts = pkgs.writeText "localhost-hosts" ''
-        127.0.0.1 localhost
-        ${optionalString cfg.enableIPv6 "::1 localhost"}
-      '';
+      hosts = foldAttrs (a: e: a ++ e) [] ([ { "127.0.0.1" = [ "localhost" ]; } ]
+        ++ optional cfg.enableIPv6 { "::1" = [ "localhost" ]; }
+        ++ [ cfg.hosts ]);
+
       stringHosts =
         let
           oneToString = set: ip: ip + " " + concatStringsSep " " set.${ip} + "\n";
           allToString = set: concatMapStrings (oneToString set) (attrNames set);
-        in pkgs.writeText "string-hosts" (allToString (filterAttrs (_: v: v != []) cfg.hosts));
+        in pkgs.writeText "string-hosts" (allToString (filterAttrs (_: v: v != []) hosts));
       extraHosts = pkgs.writeText "extra-hosts" cfg.extraHosts;
-    in mkBefore [ localhostHosts stringHosts extraHosts ];
+    in mkBefore [ stringHosts extraHosts ];
 
     environment.etc =
       { # /etc/services: TCP/UDP port assignments.