authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-28 20:03:04+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-28 20:03:04+02:00
log2faf8debf18f6be1f8627a69aca0bfe0d5a736fb
treea9e9e20868d8ebc12dc4242f466e7e55d2dcc4b6
parent3f1dead2fc5922b588fbfb108f421ca957d6934a
parent109e4d85c09339b35e25b5aba2dbd9b83074cfb7

Merge pull request 'DNS fixes' (#35501) from dns-fixes into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35501

6 files changed, 21 insertions(+), 15 deletions(-)

lib/std/Io/Kqueue.zig+2-2
...@@ -1401,9 +1401,9 @@ fn openSocketPosix(...@@ -1401,9 +1401,9 @@ fn openSocketPosix(
1401 };1401 };
1402 errdefer closeFd(socket_fd);1402 errdefer closeFd(socket_fd);
14031403
1404 if (options.ip6_only) {1404 if (options.ip6_only) |ip6_only| {
1405 if (posix.IPV6 == void) return error.OptionUnsupported;1405 if (posix.IPV6 == void) return error.OptionUnsupported;
1406 try setSocketOption(k, socket_fd, posix.IPPROTO.IPV6, posix.IPV6.V6ONLY, 1);1406 try setSocketOption(k, socket_fd, posix.IPPROTO.IPV6, posix.IPV6.V6ONLY, @intFromBool(ip6_only));
1407 }1407 }
14081408
1409 return socket_fd;1409 return socket_fd;
lib/std/Io/Threaded.zig+8-5
...@@ -12407,9 +12407,9 @@ fn openSocketPosix(...@@ -12407,9 +12407,9 @@ fn openSocketPosix(
12407 };12407 };
12408 errdefer closeFd(socket_fd);12408 errdefer closeFd(socket_fd);
1240912409
12410 if (options.ip6_only) {12410 if (options.ip6_only) |ip6_only| {
12411 if (posix.IPV6 == void) return error.OptionUnsupported;12411 if (posix.IPV6 == void) return error.OptionUnsupported;
12412 try setSocketOptionPosix(socket_fd, posix.IPPROTO.IPV6, posix.IPV6.V6ONLY, 1);12412 try setSocketOptionPosix(socket_fd, posix.IPPROTO.IPV6, posix.IPV6.V6ONLY, @intFromBool(ip6_only));
12413 }12413 }
1241412414
12415 return socket_fd;12415 return socket_fd;
...@@ -13627,12 +13627,15 @@ fn netLookupFallible(...@@ -13627,12 +13627,15 @@ fn netLookupFallible(
1362713627
13628 // On Linux, glibc provides getaddrinfo_a which is capable of supporting our semantics.13628 // On Linux, glibc provides getaddrinfo_a which is capable of supporting our semantics.
13629 // However, musl's POSIX-compliant getaddrinfo is not, so we bypass it.13629 // However, musl's POSIX-compliant getaddrinfo is not, so we bypass it.
13630 const is_glibc = builtin.link_libc and builtin.target.isGnuLibC();
1363013631
13631 if (builtin.target.isGnuLibC()) {13632 if (is_glibc) {
13632 // TODO use getaddrinfo_a / gai_cancel13633 // TODO use getaddrinfo_a / gai_cancel
13633 }13634 }
1363413635
13635 if (native_os == .linux or is_windows) {13636 // On Linux, we have to go through glibc because of the Name Service Switch feature.
13637 const non_glibc_linux = native_os == .linux and !is_glibc;
13638 if (non_glibc_linux or is_windows) {
13636 if (IpAddress.parseIp6(name, options.port)) |addr| {13639 if (IpAddress.parseIp6(name, options.port)) |addr| {
13637 if (options.family == .ip4) return error.UnknownHostName;13640 if (options.family == .ip4) return error.UnknownHostName;
13638 if (copyCanon(options.canonical_name_buffer, name)) |canon| {13641 if (copyCanon(options.canonical_name_buffer, name)) |canon| {
...@@ -14493,7 +14496,7 @@ fn lookupDns(...@@ -14493,7 +14496,7 @@ fn lookupDns(
14493 var socket = s: {14496 var socket = s: {
14494 if (any_ip6) ip6: {14497 if (any_ip6) ip6: {
14495 const ip6_addr: IpAddress = .{ .ip6 = .unspecified(0) };14498 const ip6_addr: IpAddress = .{ .ip6 = .unspecified(0) };
14496 const socket = ip6_addr.bind(t_io, .{ .ip6_only = true, .mode = .dgram }) catch |err| switch (err) {14499 const socket = ip6_addr.bind(t_io, .{ .ip6_only = false, .mode = .dgram }) catch |err| switch (err) {
14497 error.AddressFamilyUnsupported => break :ip6,14500 error.AddressFamilyUnsupported => break :ip6,
14498 else => |e| return e,14501 else => |e| return e,
14499 };14502 };
lib/std/Io/Uring.zig+2-2
...@@ -5984,9 +5984,9 @@ fn socket(...@@ -5984,9 +5984,9 @@ fn socket(
5984 };5984 };
5985 errdefer ev.closeAsync(socket_fd);5985 errdefer ev.closeAsync(socket_fd);
59865986
5987 if (options.ip6_only) {5987 if (options.ip6_only) |ip6_only| {
5988 if (linux.IPV6 == void) return error.OptionUnsupported;5988 if (linux.IPV6 == void) return error.OptionUnsupported;
5989 try ev.setsockopt(cancel_region, socket_fd, linux.IPPROTO.IPV6, linux.IPV6.V6ONLY, 1);5989 try ev.setsockopt(cancel_region, socket_fd, linux.IPPROTO.IPV6, linux.IPV6.V6ONLY, @intFromBool(ip6_only));
5990 }5990 }
59915991
5992 return socket_fd;5992 return socket_fd;
lib/std/Io/net.zig+3-1
...@@ -281,7 +281,9 @@ pub const IpAddress = union(enum) {...@@ -281,7 +281,9 @@ pub const IpAddress = union(enum) {
281 /// The socket is restricted to sending and receiving IPv6 packets only.281 /// The socket is restricted to sending and receiving IPv6 packets only.
282 /// In this case, an IPv4 and an IPv6 application can bind to a single port282 /// In this case, an IPv4 and an IPv6 application can bind to a single port
283 /// at the same time.283 /// at the same time.
284 ip6_only: bool = false,284 ///
285 /// The default is determined by system configuration.
286 ip6_only: ?bool = null,
285 /// Allow the socket to send datagrams to broadcast addresses.287 /// Allow the socket to send datagrams to broadcast addresses.
286 /// When not enabled any attempt to send datagrams to a broadcast address288 /// When not enabled any attempt to send datagrams to a broadcast address
287 /// will fail with `error.AccessDenied`289 /// will fail with `error.AccessDenied`
lib/std/Io/net/test.zig+5-4
...@@ -136,21 +136,22 @@ test "resolve DNS" {...@@ -136,21 +136,22 @@ test "resolve DNS" {
136 };136 };
137137
138 var addresses_found: usize = 0;138 var addresses_found: usize = 0;
139 var found_canonical_name = false;
139140
140 while (results.getOne(io)) |result| switch (result) {141 while (results.getOne(io)) |result| switch (result) {
141 .address => |address| {142 .address => |address| {
142 if (address.eql(&localhost_v4) or address.eql(&localhost_v6))143 if (address.eql(&localhost_v4) or address.eql(&localhost_v6))
143 addresses_found += 1;144 addresses_found += 1;
144 },145 },
145 .canonical_name => |canonical_name| try testing.expectEqualStrings(146 // We can't test the actual string here because it might be "localhost.localdomain"
146 if (canonical_name.bytes[canonical_name.bytes.len - 1] == '.') "localhost." else "localhost",147 // or even the computer host name (as on Windows).
147 canonical_name.bytes,148 .canonical_name => found_canonical_name = true,
148 ),
149 } else |err| switch (err) {149 } else |err| switch (err) {
150 error.Closed => {},150 error.Closed => {},
151 error.Canceled => |e| return e,151 error.Canceled => |e| return e,
152 }152 }
153153
154 try testing.expect(found_canonical_name);
154 try testing.expect(addresses_found != 0);155 try testing.expect(addresses_found != 0);
155 }156 }
156157
src/Package/Fetch.zig+1-1
...@@ -1212,7 +1212,7 @@ fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u...@@ -1212,7 +1212,7 @@ fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u
1212 {1212 {
1213 resource.* = .{ .http_request = .{1213 resource.* = .{ .http_request = .{
1214 .request = http_client.request(.GET, uri, .{}) catch |err|1214 .request = http_client.request(.GET, uri, .{}) catch |err|
1215 return f.fail(f.location_tok, try eb.printString("unable to connect to server: {t}", .{err})),1215 return f.fail(f.location_tok, try eb.printString("server connection failed: {t}", .{err})),
1216 .response = undefined,1216 .response = undefined,
1217 .transfer_buffer = reader_buffer,1217 .transfer_buffer = reader_buffer,
1218 .decompress_buffer = &.{},1218 .decompress_buffer = &.{},