Address Differences between UDP and SCTP

Michael Tuexen Michael.Tuexen at lurchi.franken.de
Tue Sep 8 05:50:45 UTC 2020


> On 8. Sep 2020, at 01:41, Doug Hardie <bc979 at lafn.org> wrote:
> 
>> On 7 September 2020, at 13:57, Michael Tuexen <Michael.Tuexen at lurchi.franken.de> wrote:
>> 
>>> On 7. Sep 2020, at 22:48, Doug Hardie <bc979 at lafn.org> wrote:
>>> 
>>> I was quite surprised to discover that the sockaddr structure returned from recv_fd and recvfrom handle IPv4 addresses differently when using an INET6 socket.  I don't know if this was intended, or a side effect.  I started using SCTP because of the need for accessing multi-homed servers.  Some would be on IPv6 and others on IPv4.  SCTP handles that nicely if you use an INET6 socket.  When a transaction is received, if it is to an IPv4 address, then the returned sockaddr will have a inet_family of IPv4 and the IPv4 structure.  If it was sent to an IPv6 address, then the inet6_family is used.  A simple test of the family tells you which address format was provided and the address is in IPv4 or IPv6 format accordingly.
>>> 
>>> However, A new site needed to be added and it is behind a NAT router.  The problem with SCTP is that most (possibly all) NAT routers only work with TCP and UDP.  They will not port forward SCTP.  So I have no way to get through to the machine.  So I added code to check for that situation and use UDP instead.  This will work because I don't thing it is at all likely that a machine behind NAT can be multi-homed.
>> Would using SCTP/UDP/IPv[46] be an option? It is supported by the FreeBSD kernel.
>> See https://tools.ietf.org/html/rfc6951#section-6 for the socket API for it.
> 
> Perhaps I am not understanding this completely, but I believe that it requires UDP encapsulation which is mostly user land code.  Thus there would be two implementations of SCTP in the system.  I don't think that is the best approach.
No, the UDP encapsulation/decapsulation is done by the kernel. On FreeBSD you have only a single stack.
You can even have a single association where some paths are using UDP encapsulation, some are not.

For the server side, the only thing you need to do is to enable it hostwide by setting
sudo sysctl -w net.inet.sctp.udp_tunneling_port=9899
or putting
net.inet.sctp.udp_tunneling_port=9899
in /etc/sysctl.conf

On the client side you need to use the socket option defined in
https://tools.ietf.org/html/rfc6951#section-6.1
See
https://github.com/nplab/tsctp/blob/master/tsctp.c#L477
for an example.
> 
>>> 
>>> However, the code to obtain the remote IP address failed miserably.  It turns out that if you have v6only set to 1, you will never see the IPv4 packets.  If you set it to 0, then you get the packets, but the sockaddr format with UDP is different than that for SCTP.  If it is an IPv6 address, everything is the same.  However, if it is an IPv4 address, then the family remains IPv6, and the address is in sin6_addr and it is in the format ::ffff:n.n.n.n.  This makes it interesting as I need to obtain the IPv4 address as part of the verification process that the transaction is authorized.
>> For UDP and TCP you always get IPv6 addresses on AF_INET6 sockets. If you are actually using IPv4, IPv4-mapped IPv6 addresses are used. For SCTP you an choose if you want IPv4-mapped IPv6 addresses or IPv4 address. It is controlled by
>> the socket option specified in https://tools.ietf.org/html/rfc6458#section-8.1.15
> 
> That would simplify my code so I am going to implement it.  Thanks.
> 
>>> 
>>> Was this difference intended, or is it likely to change in the future?
>> I think it is intended.
> 
> I had a feeling that would be the case, but I would think consistency would be more helpful to those using the services.
You mean to switch the default for SCTP_I_WANT_MAPPED_V4_ADDR to false?

Best regards
Michael
> 
>> 
>> Best regards
>> Michael
> 
> -- Doug
> 
> 



More information about the freebsd-net mailing list