Commit 6e786b60d4

Vexu <15308111+Vexu@users.noreply.github.com>
2019-11-04 18:54:36
support ipv4-mapped ipv6 addresses
1 parent 32ac1b5
Changed files (2)
lib
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" {
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 });