aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorJohn Schmidt <john.schmidt.h@gmail.com>2022-01-11 17:38:49 +0100
committerJohn Schmidt <john.schmidt.h@gmail.com>2022-01-12 19:32:46 +0100
commit66fe5bb0d8c5e6279e2b68459b6b37d9244210bc (patch)
tree0de1bbb4cef77af19e3fb20abf32f20fffd76ef3 /lib/std
parentc4681b4889652d5228a84ac7af5ad5e17ac39055 (diff)
downloadzig-66fe5bb0d8c5e6279e2b68459b6b37d9244210bc.tar.gz
zig-66fe5bb0d8c5e6279e2b68459b6b37d9244210bc.zip
Use libc if_nametoindex if available when parsing IPs
Fixes https://github.com/ziglang/zig/issues/10521 and makes a couple of additional tests pass when linking libc.
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/c.zig2
-rw-r--r--lib/std/c/darwin.zig2
-rw-r--r--lib/std/net.zig34
-rw-r--r--lib/std/net/test.zig4
-rw-r--r--lib/std/x/os/net.zig27
5 files changed, 50 insertions, 19 deletions
diff --git a/lib/std/c.zig b/lib/std/c.zig
index 9203232e6b..ed9ceada00 100644
--- a/lib/std/c.zig
+++ b/lib/std/c.zig
@@ -357,6 +357,8 @@ pub extern "c" fn openlog(ident: [*:0]const u8, logopt: c_int, facility: c_int)
pub extern "c" fn closelog() void;
pub extern "c" fn setlogmask(maskpri: c_int) c_int;
+pub extern "c" fn if_nametoindex([*:0]const u8) c_int;
+
pub const max_align_t = if (builtin.abi == .msvc)
f64
else if (builtin.target.isDarwin())
diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig
index bfb805c36c..2a4541ea74 100644
--- a/lib/std/c/darwin.zig
+++ b/lib/std/c/darwin.zig
@@ -108,6 +108,8 @@ pub fn sigaddset(set: *sigset_t, signo: u5) void {
pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
+pub const IFNAMESIZE = 16;
+
pub const AI = struct {
/// get address to use bind()
pub const PASSIVE = 0x00000001;
diff --git a/lib/std/net.zig b/lib/std/net.zig
index 1165ac6073..78d59ae9c0 100644
--- a/lib/std/net.zig
+++ b/lib/std/net.zig
@@ -636,17 +636,35 @@ pub fn connectUnixSocket(path: []const u8) !Stream {
}
fn if_nametoindex(name: []const u8) !u32 {
- var ifr: os.ifreq = undefined;
- var sockfd = try os.socket(os.AF.UNIX, os.SOCK.DGRAM | os.SOCK.CLOEXEC, 0);
- defer os.closeSocket(sockfd);
+ if (builtin.target.os.tag == .linux) {
+ var ifr: os.ifreq = undefined;
+ var sockfd = try os.socket(os.AF.UNIX, os.SOCK.DGRAM | os.SOCK.CLOEXEC, 0);
+ defer os.closeSocket(sockfd);
+
+ std.mem.copy(u8, &ifr.ifrn.name, name);
+ ifr.ifrn.name[name.len] = 0;
+
+ // TODO investigate if this needs to be integrated with evented I/O.
+ try os.ioctl_SIOCGIFINDEX(sockfd, &ifr);
- std.mem.copy(u8, &ifr.ifrn.name, name);
- ifr.ifrn.name[name.len] = 0;
+ return @bitCast(u32, ifr.ifru.ivalue);
+ }
+
+ if (builtin.link_libc) {
+ if (name.len >= os.IFNAMESIZE)
+ return error.NameTooLong;
- // TODO investigate if this needs to be integrated with evented I/O.
- try os.ioctl_SIOCGIFINDEX(sockfd, &ifr);
+ var if_name: [os.IFNAMESIZE:0]u8 = undefined;
+ std.mem.copy(u8, &if_name, name);
+ if_name[name.len] = 0;
+ const if_slice = if_name[0..name.len :0];
+ const index = os.system.if_nametoindex(if_slice);
+ if (index == 0)
+ return error.InterfaceNotFound;
+ return @bitCast(u32, index);
+ }
- return @bitCast(u32, ifr.ifru.ivalue);
+ @compileError("std.net.if_nametoindex unimplemented for this OS");
}
pub const AddressList = struct {
diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig
index f181bb49ea..0fa853151a 100644
--- a/lib/std/net/test.zig
+++ b/lib/std/net/test.zig
@@ -49,7 +49,7 @@ test "parse and render IPv6 addresses" {
try testing.expectError(error.Incomplete, net.Address.parseIp6("FF01:", 0));
try testing.expectError(error.InvalidIpv4Mapping, net.Address.parseIp6("::123.123.123.123", 0));
// TODO Make this test pass on other operating systems.
- if (builtin.os.tag == .linux) {
+ if (builtin.os.tag == .linux or builtin.link_libc) {
try testing.expectError(error.Incomplete, net.Address.resolveIp6("ff01::fb%", 0));
try testing.expectError(error.Overflow, net.Address.resolveIp6("ff01::fb%wlp3s0s0s0s0s0s0s0s0", 0));
try testing.expectError(error.Overflow, net.Address.resolveIp6("ff01::fb%12345678901234", 0));
@@ -57,7 +57,7 @@ test "parse and render IPv6 addresses" {
}
test "invalid but parseable IPv6 scope ids" {
- if (builtin.os.tag != .linux) {
+ if (builtin.os.tag != .linux or !builtin.link_libc) {
// Currently, resolveIp6 with alphanumerical scope IDs only works on Linux.
// TODO Make this test pass on other operating systems.
return error.SkipZigTest;
diff --git a/lib/std/x/os/net.zig b/lib/std/x/os/net.zig
index c71bc5bd22..37a1d98137 100644
--- a/lib/std/x/os/net.zig
+++ b/lib/std/x/os/net.zig
@@ -16,28 +16,37 @@ pub fn resolveScopeId(name: []const u8) !u32 {
if (have_ifnamesize) {
if (name.len >= os.IFNAMESIZE) return error.NameTooLong;
- if (native_os.tag == .windows) {
+ if (native_os.tag == .windows or builtin.link_libc) {
var interface_name: [os.IFNAMESIZE:0]u8 = undefined;
mem.copy(u8, &interface_name, name);
interface_name[name.len] = 0;
- const rc = os.windows.ws2_32.if_nametoindex(@ptrCast([*:0]const u8, &interface_name));
+ const rc = blk: {
+ if (native_os.tag == .windows) {
+ break :blk os.windows.ws2_32.if_nametoindex(@ptrCast([*:0]const u8, &interface_name));
+ } else {
+ const index = os.system.if_nametoindex(@ptrCast([*:0]const u8, &interface_name));
+ break :blk @bitCast(u32, index);
+ }
+ };
if (rc == 0) {
return error.InterfaceNotFound;
}
return rc;
}
- const fd = try os.socket(os.AF.INET, os.SOCK.DGRAM, 0);
- defer os.closeSocket(fd);
+ if (native_os.tag == .linux) {
+ const fd = try os.socket(os.AF.INET, os.SOCK.DGRAM, 0);
+ defer os.closeSocket(fd);
- var f: os.ifreq = undefined;
- mem.copy(u8, &f.ifrn.name, name);
- f.ifrn.name[name.len] = 0;
+ var f: os.ifreq = undefined;
+ mem.copy(u8, &f.ifrn.name, name);
+ f.ifrn.name[name.len] = 0;
- try os.ioctl_SIOCGIFINDEX(fd, &f);
+ try os.ioctl_SIOCGIFINDEX(fd, &f);
- return @bitCast(u32, f.ifru.ivalue);
+ return @bitCast(u32, f.ifru.ivalue);
+ }
}
return error.InterfaceNotFound;