I'd like to setup a static hostname for an IPv6 address on local network. It seems, however, that /etc/hosts won't accept a zone ID - when I append a zone ID to an IPv6 address, it acts as if the host is not defined. Without the zone ID, applications are unable to connect to the host.

Can I work around this somehow? Or is there some special syntax for zone IDs in /etc/hosts?

  • Just a note, I know it as IPv6 scope ID or Linux ifindex, not as a zone ID. Commented Dec 30, 2014 at 22:41
  • As far as I know, Zone ID is the textual interface identification as part of an IPv6 address, ie. the part after %. Scope ID - ie. ifindex on Linux - is the numerical interface identifier that the Zone ID translates to. That's what I gathered, anyway...
    – kralyk
    Commented Jan 4, 2015 at 14:12
  • 1
    Not sure, would be nice to have some sources for the name. By the way, you can put the numeric representation after % as well. On Windows, this is AFAIK the more common way, while on Linux, the name is usually used. Commented Jan 4, 2015 at 14:22

2 Answers 2


This is a limitation of GNU C Library (and possibly others). It has a plugin API which won't even convey the scope ID (or ifindex/ifname) reliably. Then there's the actual nss_files plugin which is AFAIK not ready for the syntax.

I can certainly help in this area and amend the answer accordingly. First, I'm working on a more or less experimental replacement for the glibc name resolution APIs in the form of open source project netresolve. It can be used for experiments but also for everyday work if you know what you're doing. It doesn't seem to support IPv6 scope ID in /etc/hosts either but I'm adding it on my TODO list. Second, I can provide patches towards support for glibc itself. You can apply them locally or hope the project will accept them.

Then there are protocols like Multicast DNS which can theoretically provide this but are not implemented in nss_mdns and are blocked by the same issue.

Workaround using netresolve

So I realized I have already implemented this in netresolve but I had to fix a couple of tiny bugs to get it actually working. Thanks for bringing them to attention by making me try it.

You need to build the project from git. A live ebuild for Gentoo and an Arch AUR package are provided. Dependency checking is not perfect, yet. The package provides you a netresolve command for performing name resolution queries and a wrapresolve command for running programs with libc resolution routines replaced by reimplementations based on libnetresolve. It is achieved using the LD_PRELOAD environment variable, so you can even run the whole shell by running wrapresolve bash or similar.



fe80::2677:3ff:fe40:db38%wlan0 test-link-local-with-scope-id

Note: You can write the link-local addresses with scope-id the standard way, i.e. appending a percent sign and then either an interface name (ifname) or an interface index (ifindex) as reported by e.g. ip link.

Test using netresolve

# netresolve --node testxxx
response netresolve 0.0.1
name testxxx
ip 1:2:3:4:5:6:7:8%eth0 any any 0 0 0 0

Test using wrapresolve and getaddrinfo

The netresolve package also provides a tool for testing getaddrinfo() called getaddrinfo.

# wrapresolve getaddrinfo test-link-local-with-scope-id
  nodename = test-link-local-with-scope-id
  servname = (null)
status = 0
  family = 10
  addrlen = 28
    family = 10
    port = 0
    flowinfo = 0x00000000
    address = 0xfe80000000000000267703fffe40db38
    scope_id = 3
  nodename = test-link-local-with-scope-id

Test using wrapresolve and getent

This is the first test that uses a tool that is already present in your system. Otherwise it is very close to the previous test.

# wrapresolve getent ahosts test-link-local-with-scope-id 
fe80::2677:3ff:fe40:db38 0      test-link-local-with-scope-id

Test using wrapresolve and ping6

# wrapresolve ping6 test-link-local-with-scope-id

PING test-link-local-with-scope-id(fe80::2677:3ff:fe40:db38) 56 data bytes
64 bytes from fe80::2677:3ff:fe40:db38: icmp_seq=1 ttl=64 time=0.029 ms
64 bytes from fe80::2677:3ff:fe40:db38: icmp_seq=2 ttl=64 time=0.075 ms
64 bytes from fe80::2677:3ff:fe40:db38: icmp_seq=3 ttl=64 time=0.072 ms
64 bytes from fe80::2677:3ff:fe40:db38: icmp_seq=4 ttl=64 time=0.078 ms

Note: You need to run ping and ping6 as root. Their job requires additional privileges and they are suid root because of that, which doesn't play well with wrapresolve.

Test using wrapresolve and ssh

# wrapresolve ssh test-link-local-with-scope-id
# logout

You can also test with tools like curl. This works for non-privileged users as well.

Multicast DNS

I have mDNS on my TODO list for netresolve, probably via both Avahi and systemd-resolved which is going to serve DNS, LLMNR and mDNS at once.

Fixes for GNU C Library

This is on my longer term TODO list and I'm in contact with other people working on parts of it. There are more options and I'm going to fill in more information in this answer later.


Using link-local for manual stuff is not really convenient (as you have noticed). Link-local is great for automatic functions like discovering the local gateways on the network, talking to the local DHCPv6 server, mDNS, OSPFv3 routers talking to each other etc. But for normal work you should use routable addresses. If you get IPv6 addresses from your ISP then use those, otherwise generate your own ULA prefix.

In short: link-local addresses in /etc/hosts don't work, use routable addresses instead

  • I'm not sure I'll be able to change the device's IPv6 address, because it's actually an Android phone. I'm gonna have to look into that. Thanks for your answer though!
    – kralyk
    Commented Dec 18, 2014 at 21:43
  • 2
    The text is certainly right from the operator perspective, upvoting. My answer provides a different perspective because in theory you could use them in convenient ways via mDNS, other protocols or via /etc/hosts as requested. Commented Dec 18, 2014 at 22:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .