# hostname -f unnecessary DNS request

## cehrig

Hey guys,

i am facing a strange behavior with hostname -f (at least i can't explain what's going on there).

Let me start with the setup

/etc/hosts

```
# IPv4 and IPv6 localhost aliases

127.0.0.1       rt01.domain.net rt01 localhost

<public ip>     rt01.domain.net rt01

::1             localhost
```

/etc/host.conf

```
# This keyword specifies how host lookups are to be performed. It

# should be followed by one or more lookup methods, separated by

# commas.  Valid methods are bind, hosts, and nis.

#

order hosts, bind
```

/etc/conf.d/hostname

```
# Set to the hostname of this machine

hostname="rt01"
```

/etc/nsswitch.conf

```
# /etc/nsswitch.conf:

# $Header: /var/cvsroot/gentoo/src/patchsets/glibc/extra/etc/nsswitch.conf,v 1.1 2006/09/29 23:52:23 vapier Exp $

passwd:      compat

shadow:      compat

group:       compat

# passwd:    db files nis

# shadow:    db files nis

# group:     db files nis

hosts:       files dns

networks:    files

services:    db files

protocols:   db files

rpc:         db files

ethers:      db files

netmasks:    files

netgroup:    files

bootparams:  files

automount:   files

aliases:     files
```

Looking at the execution time of hostname -f makes me nervous and some of my applications slow.

 *Quote:*   

> rt01 ~ # time hostname -f
> 
> rt01.domain.net
> 
> real    0m5.007s
> ...

 

So i was checking with strace what's going on here ... and the time consuming portion comes at the very end:

```
socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP) = 3

connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, 16) = 0

poll([{fd=3, events=POLLOUT}], 1, 0)    = 1 ([{fd=3, revents=POLLOUT}])

sendto(3, "\352:\1\0\0\1\0\0\0\0\0\0\5webs1\0\0\34\0\1", 23, MSG_NOSIGNAL, NULL, 0) = 23

poll([{fd=3, events=POLLIN}], 1, 5000)  = 1 ([{fd=3, revents=POLLIN}])

ioctl(3, FIONREAD, [98])                = 0

recvfrom(3, "\352:\201\203\0\1\0\0\0\1\0\0\5rt01\0\0\34\0\1\0\0\6\0\1\0\0\0316"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("176.57.141.163")}, [16]) = 98

close(3)                                = 0

```

It is trying to connect to my primary DNS server - probably to look for any matching PTR record, but ... it won't find anything like this. Now i was playing around a little bit with the settings in /etc/nsswitch.conf and changing the relevant part to only read from /etc/hosts.

```
hosts:       files
```

That is really bad as you can imagine, but hostname -f is now very fast and it is of course not polling the DNS server. Anyway ... now i know that my /etc/hosts is without any doubt setup correctly. http://man7.org/linux/man-pages/man5/nsswitch.conf.5.html states, that the default action for status success is return. So my conclusion from playing around with nsswitch.conf is that:

- files' status is success and it should return

- dns service specification should not be respected

My question: Why is my machine still polling the DNS server when it gets all the information from /etc/hosts ?

Thank you very much in advance.

----------

## Ant P.

My first question would have to be: what package is your "hostname" binary from? The one in coreutils has no -f option.

----------

## cehrig

This is a good one. I can not remember during the last ten years, that i was anytime looking for a package containing 'hostname', so I guess it is coming from the stage3 tarball i always download from the official sources (?).

```
rt01 ~ # hostname --version

net-tools 1.60_p20141019041918
```

// edit: I just learned equery  :Smile: 

```
rt01 ~ # equery belongs /bin/hostname

 * Searching for /bin/hostname ... 

sys-apps/net-tools-1.60_p20141019041918-r1 (/bin/hostname)
```

// edit2: just downloading http://distfiles.gentoo.org/releases/amd64/autobuilds/current-stage3-amd64/stage3-amd64-20160317.tar.bz2 confirms my assumption. I'm using the default hostname binary shipped by the stage3 tarball.

----------

## Ant P.

Oh, looks like multiple packages provide it controlled by USE flags now...

My best guess is it's returning the entry in /etc/hosts for 127.0.0.1, then noticing you have more than one network interface and trying to look up reverse maps for the other IPs. The coreutils version of the command stops after getting one name, FWIW.

----------

## cehrig

Indeed, IMHO it seems to be an issue with the implementation of the net-tools hostname

Testing it with the following code snippet, i can see in strace only /etc/hosts is read:

```
struct addrinfo hints, *info, *p;

int gai_result;

char hostname[1024];

hostname[1023] = '\0';

gethostname(hostname, 1023);

memset(&hints, 0, sizeof hints);

hints.ai_family = AF_UNSPEC; /*either IPV4 or IPV6*/

hints.ai_socktype = SOCK_STREAM;

hints.ai_flags = AI_CANONNAME;

if ((gai_result = getaddrinfo(hostname, "http", &hints, &info)) != 0) {

    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(gai_result));

    exit(1);

}

for(p = info; p != NULL; p = p->ai_next) {

    printf("hostname: %s\n", p->ai_canonname);

}

freeaddrinfo(info);
```

The code was copied from: http://stackoverflow.com/questions/504810/how-do-i-find-the-current-machines-full-hostname-in-c-hostname-and-domain-info

----------

## khayyam

 *cehrig wrote:*   

> Indeed, IMHO it seems to be an issue with the implementation of the net-tools hostname

 

cehrig ... its not really surprising, net-tools has been without a maintainer since 2002. Anyhow, note that busybox also provides 'hostname' and this also supports the -f flag.

```
$ busybox hostname -f
```

... if that doesn't also behave in a similar manner then you could always symlink to busybox.

best ... khay

----------

## cehrig

I'll give it a try, thanks khay!

----------

