::1/128 and 127.0.0.1 address creation ownership

From: Alexander Chernikov <melifaro_at_FreeBSD.org>
Date: Mon, 22 May 2023 10:52:42 UTC
Hi,


The current model of assigning default lo0 addresses is, well, interesting.
The ownership for creating 127.0.0.1 belongs to the rc.d (network.subr:ifn_start() -> ipv4_up()).
It is executed at the system start or jail start (explicitly by running /etc/rc).

The ownership for creating ::1 belongs to the kernel.
When the userland (most likely, network.subr when adding 127.0.0.1) calls SIOCAIFADDR (note it’s setting _alias_, not SIOCSIFADDR),
It gets passed via kern_ioctl() to soo_ioctl() and then to if.c:ifioctl(). Ifioctl() then calls in_aifaddr_ioctl().

in_aifaddr_ioctl() handler calls if_ioctl() for SIOCSIFADDR (set, but not alias) before assigning the address.
Loopback handler (loioctl()) sets IFF_UP flag and schedules taskq link state change.
Then, in_aifaddr_ioctl() adds the ifa & interface routes and completes, returning to ifioctl().
Ifioctl() inspects the changed interface flags and, if IFF_UP is added it explicitly calls in6_if_up() for the interface.
in6_if_up() kicks up DAD and calls in6_ifattach(). Finally, in6_ifattach() calls in6_ifattach_loopback() which adds ::1 and fe80::1.

As a result, when adding 127.0.0.1 to lo0 from userland, ::1 gets automatically added by the kernel.

(I’m not sure what part of the process above I dislike the most - there are too many of them).
My main question here is the desired ownership model. I don’t have a strong opinion on whether the userland of the kernel should own loopback creation.
However, I think that:
1) the behaviour should be consistent (either both of them created by the userland or both created by the kernel)
2) the process should be independent (e.g. adding address from one family shouldn’t result in adding address from the other family).
For example, it can be either userland explicitly creates both or the kernel creates both on interface up, using protocol hooks).
3) I’m not sure SIOCSIFADDR should be (ab)used by the drivers ioctls(). That model dates back to BSD 4.4 and doesn’t look well in presence of event handlers.
Most drivers (default ethernet handler, loop, gre,disc,me,ipsec) just set IFF_UP there.

More than happy to hear what other’s think on the issue(s)

/Alexander