diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-01-15 00:47:12 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-01-15 00:47:12 +0100 |
| commit | ba0f72363accc19edbfc5a7ae42d5a8970f56f64 (patch) | |
| tree | 324b3c9a6fefd0399fd01722a7be78cbaf45f553 /lib/std | |
| parent | b3471ef3009c4e3164145692b1b5d0662077d949 (diff) | |
| parent | c992164dc71ec38c42d14a0c9380a19b8e357880 (diff) | |
| download | zig-ba0f72363accc19edbfc5a7ae42d5a8970f56f64.tar.gz zig-ba0f72363accc19edbfc5a7ae42d5a8970f56f64.zip | |
Merge pull request #10576 from schmee/macos-resolve-ip
Use libc if_nametoindex for macOS when parsing IPs
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/c.zig | 2 | ||||
| -rw-r--r-- | lib/std/c/darwin.zig | 2 | ||||
| -rw-r--r-- | lib/std/net.zig | 34 | ||||
| -rw-r--r-- | lib/std/net/test.zig | 4 | ||||
| -rw-r--r-- | lib/std/x/os/net.zig | 27 |
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 1a74c5283b..0853a08c53 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 (comptime builtin.target.os.tag.isDarwin()) { + 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..f2946777bd 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 comptime builtin.os.tag.isDarwin()) { 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 comptime !builtin.os.tag.isDarwin()) { // 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..d4a17f8679 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 comptime native_os.tag.isDarwin()) { 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; |
