7

I claim an IPv6 address using ifconfig in a script. This address is then immediately used to listen on a TCP port.

When I write the script like this, it fails because the service is unable to listen:

ifconfig igb0 inet6 2001:db8::10/64 add
service my_service start #fails

However, it succeeds when I do it like this:

ifconfig igb0 inet6 2001:db8::10/64 add
sleep 1
service my_service start

I tried writing the output of ifconfig directly after running the add-operation. It appears that ifconfig reports the IP-address as being tentative, which apparently prevents a service from listening on it.

Naturally, waiting exactly one second and hoping that the address has become available is not a very good way to handle this. How can I wait for a tentative address to become available, or make ifconfig return later so that the address is all set up?

8
  • You can replace the sleep with a loop, maybe until ifconfig igb0 inet6|grep something;do true; done but I don't have a suitable machine to test it on (why it's a comment rather than an answer). If you do get it to work, you can put the working code in an answer yourself.
    – MAP
    Jul 30, 2016 at 22:24
  • @MAP This will probably work, but it'll hog the CPU and spawn many short-lived processes. In my case, I think using sleep is safer, but there may be other cases where the loop is preferred.
    – jornane
    Aug 2, 2016 at 19:38
  • Well, it shouldn't be very long, but you're right it should probably be throttled (at least by replacing true in the loop with a sleep, for some suitable interval).
    – MAP
    Aug 3, 2016 at 4:16
  • An address can be in several states, tentative is one of them. Having ifconfig wait for an address to leave the state tentative is simply not in harmony with how addresses are being handled. ~ N.B. The ip utility of the iproute2 package is far superior to ifconfig. Feb 10, 2017 at 15:21
  • You may configure to use optimistic DAD as defined in RFC 4429. The purpose is to make an address available to applications even if the DAD is not yet completed. You may need to reconfigure the kernel to utilize this feature. Feb 10, 2017 at 15:24

2 Answers 2

3

An address can be in several states, tentative is one of them. Having ifconfig wait for an address to leave the state tentative is simply not in accord with the design.

You may configure to use optimistic DAD as defined in RFC 4429. The purpose is to make an address available to applications even if the DAD is not yet completed. You may need to reconfigure the kernel to utilize this feature.

Once the kernel is built to provide optimistic DAD, then you may certain sysctl-settings to enable it. From ip-sysctl.txt:

/proc/sys/net/ipv6/* Variables:
...

conf/interface/*:
        Change special settings per interface.

        The functional behaviour for certain settings is different
        depending on whether local forwarding is enabled or not.

...

optimistic_dad - BOOLEAN
        Whether to perform Optimistic Duplicate Address Detection (RFC 4429).
                0: disabled (default)
                1: enabled

use_optimistic - BOOLEAN
        If enabled, do not classify optimistic addresses as deprecated during
        source address selection.  Preferred addresses will still be chosen
        before optimistic addresses, subject to other ranking in the source
        address selection algorithm.
                0: disabled (default)
                1: enabled

That is, do something like

sysctl -w net.ipv6.conf.enp2s6.optimistic_dad=1
sysctl -w net.ipv6.conf.enp2s6.use_optimistic=1

at boot time.

3
  • On Linux, you can do this with /proc/sys/net/ipv4/optimistic_dad.
    – jornane
    Feb 15, 2017 at 18:06
  • 1
    This answer is for Linux, and the question was about NetBSD/FreeBSD. Feb 16, 2017 at 20:49
  • @EricSchnoebelen The OP accepted this answer... Moreover, the answer is conceptually the same for any OS - use optimistic DAD. Feb 16, 2017 at 21:24
2

After asking a NetBSD-developer, and verifying that the same applies to FreeBSD, I found out the solution (which applies on both these OSes):

The Duplicate Address Detection (DAD) will use some time detecting if the address is already in use. The amount of time it will use for this is defined in seconds in the sysctl(3) value net.inet6.ip6.dad_count. In NetBSD's /etc/rc.d/network, function network_start_ipv6_autoconf, the script waits for this amount plus one second.

When DAD finds out that the address is already in use on the network, ifconfig(8) will show the address as duplicated. In this state it is not possible to bind to the address, similar to when the address is tentative.

A more complete and correcter solution would thus be:

ifconfig igb0 inet6 2001:db8::10/64 add
dadcount=$(/sbin/sysctl -n net.inet6.ip6.dad_count 2>/dev/null)
sleep $dadcount
sleep 1
ifconfig igb0 | grep 2001:db8::10/64 | egrep '(duplicated|tentative)$' >&2 && exit 1
service my_service start

I have observed that FreeBSD and NetBSD behave differently when adding an address that is currently in duplicated state:

  • FreeBSD 11 will immediatly remove the duplicated state, allowing the address to be used, abeit possibly causing conflicts.
  • NetBSD 7 will mark the address as tentative, and it won't change the state from there, at least not for a couple minutes. The address must be removed and added again in order to be useable.

You must log in to answer this question.

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