The intention for V4MAPPED is to allow "single-stack" usage of V4 and V6 addresses (or am I misunderstanding the purpose of the V4MAPPED socket option here?). The application only handles V6 addresses, and the system transparently converts from mapped addresses to "proper" IPv4 addresses.
Unfortunately, when V6ONLY is set on a socket, this does not work. `man ipv6` states:
IPV6_V6ONLY (since Linux 2.4.21 and 2.6)
If this flag is set to false (zero), then the socket can be
used to send and receive packets to and from an IPv6 address
or an IPv4-mapped IPv6 address.
If IPV6_V6ONLY is always set, the V4MAPPED socket option is nonsensical, as the socket can't send IPv4 packages.
This is what the test_bad script is trying to simulate (badly☺): The lookup for neverssl.com returns only an IPv4 address (since the running system doesn't have IPv6 connectivity). If V6ONLY was 0, this would work, and we would get a mapped V4 address (something like '::ffff:52.222.163.80'). With V6ONLY=1, we cannot connect to this mapped address.
A better test script would have this main method (I've attached the new version as well):
async def main():
on_con_lost = asyncio.Future()
transport, protocol = await asyncio.get_event_loop().create_connection(
lambda: TestProtocol(on_con_lost),
family=socket.AF_INET6,
flags=socket.AI_V4MAPPED,
host='neverssl.com',
port=80)
try:
await on_con_lost
finally:
transport.close()
On my system, the lookup returns a V4 address. Since I've enabled AI_V4MAPPED, I get a mapped V6 address that I would be able to connect to if V6ONLY is disabled. However, with V6ONLY enabled, the address is not connectable.
|