Bug 279881 - socket support for IPv4-mapped IPv6 misbehave
Summary: socket support for IPv4-mapped IPv6 misbehave
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 14.1-STABLE
Hardware: Any Any
: --- Affects Many People
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-06-20 16:30 UTC by zonyitoo
Modified: 2024-06-21 12:41 UTC (History)
1 user (show)

See Also:


Attachments
test program (1.78 KB, text/plain)
2024-06-21 12:36 UTC, Andrey V. Elsukov
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description zonyitoo 2024-06-20 16:30:32 UTC
When using IPv4-mapped IPv6 address with socket, no matter sysctl net.inet6.ip6.v6only was set to 0 or 1, operations will always success.

Here is a test program in Python:

import socket
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, 0)
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
s.connect(('::ffff:169.254.1.1', 53))
print(s.getsockname())

1. No matter net.inet6.ip6.v6only was set to 0 or 1, the program above will always run without any errors.

2. No matter net.inet6.ip6.v6only was set to 0 or 1, delete the call setsockopt(IPV6_V6ONLY) will always run without any errors. (UNEXPECTED)

3. If changed the set(IPV6_V6ONLY) line to 1, then the connect() call will fail with an EINVAL error. (EXPECTED)

Based on my experience on Linux, if sockopt IPV6_V6ONLY was not set explicitly, it should derived from the system's global configuration, in FreeBSD it should be net.inet6.ip6.v6only.

Here is another problem, which I think it should be a special design in FreeBSD:

If net.inet6.ip6.v6only was set to 1, even the problem like above could run without error, and then send packets to the target address (IPv4-mapped IPv6) with sendto(), the target socket couldn't receive the packet from recvfrom().

I suspected that it is because net.inet6.ip6.v6only=1 disables routing IPv4-mapped IPv6 to IPv4 target.

Overall, in this issue I want to suggest:

1. sockopt IPV6_V6ONLY default value should derive from net.inet6.ip6.v6only
2. If sockopt IPV6_V6ONLY was set to 0 explicitly, then IPv4-mapped IPv6 packets send from or receive by this socket should be allowed / properly routed.
Comment 1 Andrey V. Elsukov freebsd_committer freebsd_triage 2024-06-21 12:36:09 UTC
Created attachment 251601 [details]
test program
Comment 2 Andrey V. Elsukov freebsd_committer freebsd_triage 2024-06-21 12:41:08 UTC
So, I used attached test program:

% clang main.c -o test
% sudo ifconfig lo0 inet 10.0.0.1/24 alias
% ./test
main:74: sysctlbyname(net.inet6.ip6.v6only) = 1
test:29: socket fd = 3
test:35: getsockopt(IPV6_V6ONLY) = 1
test:41: setsockopt(IPV6_V6ONLY) -> 0
test:58: connect(::ffff:10.0.0.2) -> 0
test:60: ----------
test:29: socket fd = 3
test:35: getsockopt(IPV6_V6ONLY) = 1
test:56: connect(::ffff:10.0.0.2): Invalid argument
test:60: ----------
% sudo sysctl net.inet6.ip6.v6only=0
net.inet6.ip6.v6only: 1 -> 0
% ./test
main:74: sysctlbyname(net.inet6.ip6.v6only) = 0
test:29: socket fd = 3
test:35: getsockopt(IPV6_V6ONLY) = 0
test:58: connect(::ffff:10.0.0.2) -> 0
test:60: ----------
test:29: socket fd = 3
test:35: getsockopt(IPV6_V6ONLY) = 0
test:41: setsockopt(IPV6_V6ONLY) -> 1
test:56: connect(::ffff:10.0.0.2): Invalid argument
test:60: ----------

1. As you can see, getsockopt() returns default value of socket option, that depends on sysctl variable.
2. Depending on V6ONLY sockopt your app can or can not connect.

Probably your problem is python related.