From 32ac1b5927ba9314b9fa0ec2bb21dba4b2e66c66 Mon Sep 17 00:00:00 2001 From: Vexu <15308111+Vexu@users.noreply.github.com> Date: Mon, 4 Nov 2019 18:59:14 +0200 Subject: improve ipv6 parsing and formatting --- lib/std/net/test.zig | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'lib/std/net') diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig index 54fd40f23e..ae3c62d7f0 100644 --- a/lib/std/net/test.zig +++ b/lib/std/net/test.zig @@ -4,10 +4,38 @@ const mem = std.mem; const testing = std.testing; test "parse and render IPv6 addresses" { - const addr = try net.IpAddress.parseIp6("FF01:0:0:0:0:0:0:FB", 80); - var buf: [100]u8 = undefined; - const printed = try std.fmt.bufPrint(&buf, "{}", addr); - std.testing.expect(mem.eql(u8, "[ff01::fb]:80", printed)); + var buffer: [100]u8 = undefined; + const ips = [_][]const u8{ + "FF01:0:0:0:0:0:0:FB", + "FF01::Fb", + "::1", + "::", + "2001:db8::", + "::1234:5678", + "2001:db8::1234:5678", + "FF01::FB%1234", + }; + const printed = [_][]const u8{ + "ff01::fb", + "ff01::fb", + "::1", + "::", + "2001:db8::", + "::1234:5678", + "2001:db8::1234:5678", + "ff01::fb" + }; + for (ips) |ip, i| { + var addr = net.IpAddress.parseIp6(ip, 0) catch unreachable; + var newIp = std.fmt.bufPrint(buffer[0..], "{}", addr) catch unreachable; + std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3])); + } + + testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6(":::", 0)); + testing.expectError(error.Overflow, net.IpAddress.parseIp6("FF001::FB", 0)); + testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6("FF01::Fb:zig", 0)); + testing.expectError(error.InvalidEnd, net.IpAddress.parseIp6("FF01:0:0:0:0:0:0:FB:", 0)); + testing.expectError(error.Incomplete, net.IpAddress.parseIp6("FF01:", 0)); } test "parse and render IPv4 addresses" { @@ -19,7 +47,7 @@ test "parse and render IPv4 addresses" { "123.255.0.91", "127.0.0.1", }) |ip| { - var addr = net.IpAddress.parseIp4(ip, 0); + var addr = net.IpAddress.parseIp4(ip, 0) catch unreachable; var newIp = std.fmt.bufPrint(buffer[0..], "{}", addr) catch unreachable; std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2])); } -- cgit v1.2.3 From 6e786b60d4fb3a39b717e077d034131be613d6aa Mon Sep 17 00:00:00 2001 From: Vexu <15308111+Vexu@users.noreply.github.com> Date: Mon, 4 Nov 2019 19:54:36 +0200 Subject: support ipv4-mapped ipv6 addresses --- lib/std/net.zig | 20 ++++++++++++++++++++ lib/std/net/test.zig | 5 ++++- 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'lib/std/net') diff --git a/lib/std/net.zig b/lib/std/net.zig index 8fa6e4432d..f4464b46c6 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -32,6 +32,7 @@ pub const IpAddress = extern union { error.InvalidEnd, error.InvalidCharacter, error.Incomplete, + error.InvalidIpv4Mapping, => {}, } @@ -103,6 +104,24 @@ pub const IpAddress = extern union { } scope_id = true; saw_any_digits = false; + } else if (c == '.') { + if (!abbrv or ip_slice[0] != 0xff or ip_slice[1] != 0xff) { + // must start with '::ffff:' + return error.InvalidIpv4Mapping; + } + const start_index = mem.lastIndexOfScalar(u8, buf[0..i], ':').? + 1; + const addr = (parseIp4(buf[start_index..], 0) catch { + return error.InvalidIpv4Mapping; + }).in.addr; + ip_slice = result.in6.addr[0..]; + ip_slice[10] = 0xff; + ip_slice[11] = 0xff; + + ip_slice[12] = @truncate(u8, addr >> 24 & 0xff); + ip_slice[13] = @truncate(u8, addr >> 16 & 0xff); + ip_slice[14] = @truncate(u8, addr >> 8 & 0xff); + ip_slice[15] = @truncate(u8, addr & 0xff); + return result; } else { const digit = try std.fmt.charToDigit(c, 16); if (@mulWithOverflow(u16, x, 16, &x)) { @@ -783,6 +802,7 @@ fn linuxLookupNameFromHosts( error.InvalidCharacter, error.Incomplete, error.InvalidIPAddressFormat, + error.InvalidIpv4Mapping, => continue, }; try addrs.append(LookupAddr{ .addr = addr }); diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig index ae3c62d7f0..178ca9d148 100644 --- a/lib/std/net/test.zig +++ b/lib/std/net/test.zig @@ -14,6 +14,7 @@ test "parse and render IPv6 addresses" { "::1234:5678", "2001:db8::1234:5678", "FF01::FB%1234", + "::ffff:123.123.123.123", }; const printed = [_][]const u8{ "ff01::fb", @@ -23,7 +24,8 @@ test "parse and render IPv6 addresses" { "2001:db8::", "::1234:5678", "2001:db8::1234:5678", - "ff01::fb" + "ff01::fb", + "::ffff:7b7b:7b7b", }; for (ips) |ip, i| { var addr = net.IpAddress.parseIp6(ip, 0) catch unreachable; @@ -36,6 +38,7 @@ test "parse and render IPv6 addresses" { testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6("FF01::Fb:zig", 0)); testing.expectError(error.InvalidEnd, net.IpAddress.parseIp6("FF01:0:0:0:0:0:0:FB:", 0)); testing.expectError(error.Incomplete, net.IpAddress.parseIp6("FF01:", 0)); + testing.expectError(error.InvalidIpv4Mapping, net.IpAddress.parseIp6("::123.123.123.123", 0)); } test "parse and render IPv4 addresses" { -- cgit v1.2.3