Skip to content

Commit f56f3c5

Browse files
hawkbeeQun He
andauthored
Enable IPv4 mapped address conversion in linux version getAddressList (#14916)
It seems like the original code of setsockopt is not effective because i catch the EINVAL branch when uncomment this code, it should call setsockopt before the bind call. This should fix issue #14900. Co-authored-by: Qun He <[email protected]>
1 parent 71e8737 commit f56f3c5

File tree

1 file changed

+24
-21
lines changed

1 file changed

+24
-21
lines changed

lib/std/net.zig

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ pub fn tcpConnectToAddress(address: Address) TcpConnectToAddressError!Stream {
741741
return Stream{ .handle = sockfd };
742742
}
743743

744-
const GetAddressListError = std.mem.Allocator.Error || std.fs.File.OpenError || std.fs.File.ReadError || std.os.SocketError || std.os.BindError || error{
744+
const GetAddressListError = std.mem.Allocator.Error || std.fs.File.OpenError || std.fs.File.ReadError || std.os.SocketError || std.os.BindError || std.os.SetSockOptError || error{
745745
// TODO: break this up into error sets from the various underlying functions
746746

747747
TemporaryNameServerFailure,
@@ -1534,15 +1534,10 @@ fn resMSendRc(
15341534
ns[i] = iplit.addr;
15351535
assert(ns[i].getPort() == 53);
15361536
if (iplit.addr.any.family != os.AF.INET) {
1537-
sl = @sizeOf(os.sockaddr.in6);
15381537
family = os.AF.INET6;
15391538
}
15401539
}
15411540

1542-
// Get local address and open/bind a socket
1543-
var sa: Address = undefined;
1544-
@memset(@ptrCast([*]u8, &sa), 0, @sizeOf(Address));
1545-
sa.any.family = family;
15461541
const flags = os.SOCK.DGRAM | os.SOCK.CLOEXEC | os.SOCK.NONBLOCK;
15471542
const fd = os.socket(family, flags, 0) catch |err| switch (err) {
15481543
error.AddressFamilyNotSupported => blk: {
@@ -1556,27 +1551,35 @@ fn resMSendRc(
15561551
else => |e| return e,
15571552
};
15581553
defer os.closeSocket(fd);
1559-
try os.bind(fd, &sa.any, sl);
15601554

15611555
// Past this point, there are no errors. Each individual query will
15621556
// yield either no reply (indicated by zero length) or an answer
15631557
// packet which is up to the caller to interpret.
15641558

15651559
// Convert any IPv4 addresses in a mixed environment to v4-mapped
1566-
// TODO
1567-
//if (family == AF.INET6) {
1568-
// setsockopt(fd, IPPROTO.IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0);
1569-
// for (i=0; i<nns; i++) {
1570-
// if (ns[i].sin.sin_family != AF.INET) continue;
1571-
// memcpy(ns[i].sin6.sin6_addr.s6_addr+12,
1572-
// &ns[i].sin.sin_addr, 4);
1573-
// memcpy(ns[i].sin6.sin6_addr.s6_addr,
1574-
// "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
1575-
// ns[i].sin6.sin6_family = AF.INET6;
1576-
// ns[i].sin6.sin6_flowinfo = 0;
1577-
// ns[i].sin6.sin6_scope_id = 0;
1578-
// }
1579-
//}
1560+
if (family == os.AF.INET6) {
1561+
try os.setsockopt(
1562+
fd,
1563+
os.SOL.IPV6,
1564+
os.linux.IPV6.V6ONLY,
1565+
&mem.toBytes(@as(c_int, 0)),
1566+
);
1567+
for (0..ns.len) |i| {
1568+
if (ns[i].any.family != os.AF.INET) continue;
1569+
mem.writeIntNative(u32, ns[i].in6.sa.addr[12..], ns[i].in.sa.addr);
1570+
mem.copy(u8, ns[i].in6.sa.addr[0..12], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff");
1571+
ns[i].any.family = os.AF.INET6;
1572+
ns[i].in6.sa.flowinfo = 0;
1573+
ns[i].in6.sa.scope_id = 0;
1574+
}
1575+
sl = @sizeOf(os.sockaddr.in6);
1576+
}
1577+
1578+
// Get local address and open/bind a socket
1579+
var sa: Address = undefined;
1580+
@memset(@ptrCast([*]u8, &sa), 0, @sizeOf(Address));
1581+
sa.any.family = family;
1582+
try os.bind(fd, &sa.any, sl);
15801583

15811584
var pfd = [1]os.pollfd{os.pollfd{
15821585
.fd = fd,

0 commit comments

Comments
 (0)