Need help to understand the resolution of Hostname and FQDN

Latest response

Hello @all,

Today I could use some help to understand how the resolution of the Hostname and the FQDN on RHEL works.

Here is what I discovered this morning on a misconfigured host:

$ hostname -d
$hostname --fqdn
my-foo

But my-foo is not the FQDN. Instead I suspected my-foo.example.com to be the FQDN of this host. So I looked up some files which come to mind that could have to do something with this strange behaviour:

# cat /etc/hostname
my-foo
# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.1.1 foo.example.com foo

In /etc/hosts is another hostname configured then in /etc/hostname. This was a mistake when the host was renamed in the past. So I changed the wrong entry in /etc/hosts so it looks like:

# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.1.1 my-foo.example.com my-foo

And now I get the results I expect:

# hostname -f
my-foo.example.com
# hostname -d
example.com
# hostname
my-foo

From the hostname manpage I know that different syscalls are being used depending on the options chosed:

The function gethostname(2) is used to get the hostname. When the hostname -a, -d, -f or -i is called will gethostbyname(3) be called. The difference in gethostname(2) and gethostbyname(3) is that gethostbyname(3) is network aware, so it consults /etc/nsswitch.conf and /etc/host.conf to decide whether to read information in /etc/hostname or /etc/hosts

While using hostname -d or -f the information is read from /etc/hosts. But how the information gets processed? Does gethostbyname(3) a DNS request with the names found in /etc/hosts to determine the hosts FQDN? Or does some other mechanism do the trick?

Please, enlighten me because I'm confused.

Best regards,
Joerg

Responses

You could use "strace hostname -d" to determine what happens.

On one of our 6.9 systems:

open("/etc/resolv.conf", O_RDONLY)      = 3
read(3, "#\n# template to create /etc/reso"..., 4096) = 357
...
write(1, "my-domain.com\n", 15my-domain.com

On one of our 7.3 systems:

connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("x.x.x.x")}, 16) = 0
recvfrom(3, "x .....
write(1, "my-domain.com\n", 15my-domain.com

Where x.x.x.x is the address of the nameserver.

Hi Jörg,

No reason to be confused, you already have answered the question yourself : "In /etc/hosts is another hostname configured than in /etc/hostname. This was a mistake when the host was renamed in the past." Once everything is configured correctly, in every Linux distribution the terminal outputs are the same - it is just right like this example from my currently running fedora 27 workstation ->

[cl@cl-fw-1 ~]$ hostname
cl-fw-1
[cl@cl-fw-1 ~]$ hostname -d
fritz.box
[cl@cl-fw-1 ~]$ hostname -f
cl-fw-1.fritz.box

And here (for comparison) you can see the terminal output (exactly same structure) from my Red Hat Enterprise Linux 7.4 Server ->

[cl@cl-rs-1 ~]$ hostname
cl-rs-1
[cl@cl-rs-1 ~]$ hostname -d
fritz.box
[cl@cl-rs-1 ~]$ hostname -f
cl-rs-1.fritz.box

Regards,
Christian

Good Morning,

I used strace as Siem suggested and took a look at what happened. Surprisingly the behaviour differs from host to host. On the first RHEL 7.4 host with correct config I tried I got a similar result like Siem got. A request was send to a nameserver and in return the FQDN was wirtten.

On a second host with correct config I run the same command but in this case no nameserver was involved. The FQDN was returend after the /etc/hosts was read:

open("/etc/hosts", O_RDONLY|O_CLOEXEC)  = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=224, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc020e17000
read(3, "127.0.0.1   localhost localhost."..., 4096) = 224
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x7fc020e17000, 4096)            = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc020e17000
write(1, "example.com\n", 20)   = 20
exit_group(0)

Now I've changed /etc/hosts on the second host to see what happens with a broken config:

# cat /etc/hostname
my-foo
# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.1.1 foo.example.com foo

# strace hostname -d
[...]
open("/etc/hosts", O_RDONLY|O_CLOEXEC)  = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=214, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd7deffc000
read(3, "127.0.0.1   localhost localhost."..., 4096) = 214
read(3, "", 4096)                       = 0
close(3)                                = 0
[...]
socket(AF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.1.1")}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(37167), sin_addr=inet_addr("192.168.1.1")}, [16]) = 0
close(3)
[...]
exit_group(0)                           = ?

192.168.1.1 is the ip address of the host in question and not a nameserver address. In this case no FQDN was discovered. Unfortunately I have to litte experiences with strace and knowledge about what happend there to fully understand why the behaviour seems to differ from host to host. But I understand that there is no FQDN received in the last case because was wrong ip address was used for the nameserver. What I do not understand is why in the first case the FQDN could be discoverd directly from the /etc/hosts where no connect to any other host happened.

What is in in /etc/nsswitch.conf? If it says hosts: files dns then /etc/hosts has precedence over /etc/resolv.conf for lookups by most glibc clients.