Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions lib/net.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const {
const assert = require('internal/assert');
const {
UV_EADDRINUSE,
UV_EAFNOSUPPORT,
UV_EBADF,
UV_EINVAL,
UV_ENOTCONN,
Expand Down Expand Up @@ -2264,6 +2265,19 @@ function createServerHandle(address, port, addressType, fd, flags) {
}
} else if (addressType === 6) {
err = handle.bind6(address, port, flags);
// On IPv6-only systems, setting IPV6_V6ONLY to false can fail with
// EAFNOSUPPORT because the IPv4 address family is unavailable. In that
// case, retry with an IPv6-only socket before falling back to IPv4.
if (err === UV_EAFNOSUPPORT &&
!(flags & TCPConstants.UV_TCP_IPV6ONLY)) {
handle.close();
handle = new TCP(TCPConstants.SERVER);
err = handle.bind6(
address,
port,
flags | TCPConstants.UV_TCP_IPV6ONLY,
);
}
} else {
err = handle.bind(address, port, flags);
}
Expand Down
38 changes: 38 additions & 0 deletions test/sequential/test-net-server-listen-ipv6-only-system.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Flags: --expose-internals
'use strict';

const common = require('../common');
const assert = require('assert');
const net = require('net');
const { internalBinding } = require('internal/test/binding');
const { TCP, constants: TCPConstants } = internalBinding('tcp_wrap');
const { UV_EAFNOSUPPORT } = internalBinding('uv');

const probe = new TCP(TCPConstants.SOCKET);
if (probe.bind6('::1', 0, TCPConstants.UV_TCP_IPV6ONLY) !== 0) {
probe.close();
common.skip('no IPv6 support');
}
probe.close();

const bind6 = TCP.prototype.bind6;
let firstBind = true;

TCP.prototype.bind6 = function(...args) {
if (firstBind && args[2] === 0) {
firstBind = false;
return UV_EAFNOSUPPORT;
}
return bind6.apply(this, args);
};

const server = net.createServer();
server.on('error', common.mustNotCall());

server.listen({ port: 0 }, common.mustCall(() => {
assert.strictEqual(server.address().family, 'IPv6');

server.close(common.mustCall(() => {
TCP.prototype.bind6 = bind6;
}));
}));
Loading