Follow-up to PR 52804, applying thaJeztah's review suggestion: check
IsLoopback first for both address families (preserving any requested
loopback address), and only fall back to the canonical loopback for
the family otherwise. No behavior change; ::1 now returns through the
loopback-preserving branch instead of the IPv6 fallback, with the same
result.
Signed-off-by: Andrew Liu <andrewjliu22@gmail.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
In rootless mode, ChildHostIP maps every IPv4 host address to 127.0.0.1
in the child network namespace. Port bindings on the same port but
distinct loopback addresses (e.g. 127.0.1.2:80 and 127.0.1.3:80) were
therefore both reserved as 127.0.0.1:80 by the port allocator in the
child namespace, and the second binding failed with "Bind for
127.0.0.1:8080 failed: port is already allocated" even though the
requested addresses do not conflict.
Preserve IPv4 loopback host addresses as the child host IP instead. The
child namespace's lo interface covers all of 127.0.0.0/8, so the
addresses are bindable as-is, and RootlessKit's builtin port driver
both listens on the requested parent address and dials the requested
child address verbatim. Port drivers that disallow loopback child IPs
(slirp4netns) are unaffected: their forced non-loopback childIP is
selected before the loopback fallback.
Signed-off-by: Andrew Liu <andrewjliu22@gmail.com>
In rootless mode, the Engine needs to call the rootless port driver to
know which IP address it should bind to inside of its network namespace.
The slirp4netns port drivers doesn't support binding to IPv6 address, so
we need to detect that before listening on the port.
Before commit 201968cc0, this wasn't a problem because the Engine was
binding the port, then calling rootless port driver to learn whether the
proto/IP family was supported, and listen on the port if so.
Starting with that commit, the Engine does bind + listen in one go, and
then calls the port driver — this is too late. Fix the bug by checking
if the port driver supports the PortBindingReq, and only allocate the
port if so.
Signed-off-by: Albin Kerouanton <albin.kerouanton@docker.com>