Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Jan 2023 19:52:12 +0100
From:      Steffen Christgau <mail@s14u.de>
To:        freebsd-net@freebsd.org
Subject:   Bind fails in jail with assigned IP address
Message-ID:  <68c52405-1071-db04-0874-f6dac2bacceb@s14u.de>

next in thread | raw e-mail | index | archive | help
Hi folks,

(The whole discussion is for legacy IP (v4) only, IPv6 might be affected 
as well, but I haven't tested yet.)

I've implemented a daemon in Python for the Web Services on Devices 
(WSD) discovery protocol [1]. The protocol requires the "host" side to 
receive multicast packets addressed to a specific port (i.e. 3702). On 
the other hand, unicast traffic must be sent from that very same port as 
well [2]. I realize this by using separate sockets for multicast 
reception (recv_socket), unicast transmission (uc_send_socket) and a 
third one for multicast transmission, but the third one is not of 
concern here.

So, essentially I have a multicast-enabled socket and a "conventional" 
unicast socket that need to be bound to the same port. On Linux, I can 
bind the the multicast socket to the legacy IP multicast address, but 
for FreeBSD this does not work (EADDRNOTAVAIL) and I fall back to bind 
to the port only and a wildcard IP address [3]. Although I found a hint 
on this in Stevens' book and it actually works, I maybe doing it wrong. 
So if there is a better way to do so, I'd be happy to know about it.

After the receiving multicast socket is bound, I bind the unicast 
sending socket to the IP address of the intended network interface and 
the required protocol-specific port.

As said, this works fine under FreeBSD in general. But if the 
script/daemon is executed in a jail with an IP addresses assigned to the 
jail, binding the sending socket fails with EADDRINUSE. This appears to 
be caused by what is described in jail(8) for jails with provided IP 
addresses:

> ip4.addr
> A list of IPv4 addresses assigned to the jail.  If this is set, the 
> jail is restricted to using only these addresses. [...] Attempts to 
> use wildcard addresses silently use the jailed address instead. For 
> IPv4 the first address given will be used as the source address when
> source address selection on unbound sockets cannot find a better 
> match.
The effect of the silently changed wildcard address in my case is that 
the changed address prevents the required binding of the second/sending 
socket. This is inconsistent with the behavior outside a jail. Is this 
actually intended? If so, what can be done to bind both sockets to their 
required ports?

I also tried to set ip4.saddrsel = 1 in the jail config, but it appeared 
that nothing changed. If the IP address configuration is omitted for the 
jail, the service does not encounter the error of an address that is 
already in use.

If there is a solution to have the daemon run in a jail, I would be 
happy to discuss this. If jails are not suitable for this use case, let 
me know as well. 😉

Looking forward to your replies.

Regards, Steffen

[1] https://github.com/christgau/wsdd
[2] 
https://learn.microsoft.com/en-us/windows/win32/wsdapi/discovery-and-metadata-exchange-message-patterns
[3] https://github.com/christgau/wsdd/blob/0aef2d7/src/wsdd.py#L281-L287



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?68c52405-1071-db04-0874-f6dac2bacceb>