diff --git a/hack/integration-ipv6.sh b/hack/integration-ipv6.sh index 4123b2fe..ebd9f578 100755 --- a/hack/integration-ipv6.sh +++ b/hack/integration-ipv6.sh @@ -15,11 +15,17 @@ echo "hello ipv6" >${tmp}/index.html busybox httpd -f -p "[${parent_ipv6}]:8080" -h "${tmp}" & pid=$! -$ROOTLESSKIT \ - --net=slirp4netns \ - --ipv6 \ - sh -euc "sleep 3; exec curl -fsSL http://[${parent_ipv6}]:8080" +cleanup() { + kill -9 $pid || true + sudo ip link del ${parent_dummy} || true + rm -rf ${tmp} +} +trap cleanup EXIT -kill -9 $pid || true -sudo ip link del ${parent_dummy} -rm -rf ${tmp} +for net in 'slirp4netns' 'pasta' +do + $ROOTLESSKIT \ + --net=${net} \ + --ipv6 \ + sh -euc "sleep 3; exec curl -fsSL http://[${parent_ipv6}]:8080" +done diff --git a/pkg/network/iputils/iputils.go b/pkg/network/iputils/iputils.go index 7a615c43..d200018d 100644 --- a/pkg/network/iputils/iputils.go +++ b/pkg/network/iputils/iputils.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "fmt" "math" + "math/big" "net" ) @@ -21,3 +22,18 @@ func AddIPInt(ip net.IP, i int) (net.IP, error) { binary.BigEndian.PutUint32(res, uint32(resInt64)) return res, nil } + +func AddIPInt6(ip net.IP, i int) (net.IP, error) { + ip6 := ip.To16() + if ip.To4() != nil || ip6 == nil { + return nil, fmt.Errorf("expected IPv6 address, got %s", ip.String()) + } + b := new(big.Int).SetBytes(ip6) + b.Add(b, big.NewInt(int64(i))) + if b.Sign() < 0 || b.BitLen() > 128 { + return nil, fmt.Errorf("%s + %d overflows", ip.String(), i) + } + res := make(net.IP, net.IPv6len) + b.FillBytes(res) + return res, nil +} diff --git a/pkg/network/iputils/iputils_test.go b/pkg/network/iputils/iputils_test.go index 9cf6d122..8d6ae79d 100644 --- a/pkg/network/iputils/iputils_test.go +++ b/pkg/network/iputils/iputils_test.go @@ -49,3 +49,58 @@ func TestAddIPInt(t *testing.T) { } } } + +func TestAddIPInt6(t *testing.T) { + type testCase struct { + s string + i int + expected string + } + testCases := []testCase{ + { + "fd00::", + 0x2, + "fd00::2", + }, + { + "fd00::", + 0x100, + "fd00::100", + }, + { + "fd00::ffff", + 0x1, + "fd00::1:0", + }, + { + "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + 0x1, + "", + }, + { + "10.0.2.0", + 100, + "", + }, + } + for i, tc := range testCases { + ip := net.ParseIP(tc.s) + if ip == nil { + t.Fatalf("invalid IP: %q", tc.s) + } + gotIP, err := AddIPInt6(ip, tc.i) + if tc.expected == "" { + if err == nil { + t.Fatalf("#%d: expected error, got no error", i) + } + } else { + if err != nil { + t.Fatalf("#%d: expected no error, got %q", i, err) + } + got := gotIP.String() + if got != tc.expected { + t.Fatalf("#%d: expected %q, got %q", i, tc.expected, got) + } + } + } +} diff --git a/pkg/network/pasta/pasta.go b/pkg/network/pasta/pasta.go index dcb1b407..3bb3a8c3 100644 --- a/pkg/network/pasta/pasta.go +++ b/pkg/network/pasta/pasta.go @@ -76,6 +76,10 @@ func NewParentDriver(logWriter io.Writer, binary string, mtu int, ipnet *net.IPN return nil, err } } + _, ipnet6, err := net.ParseCIDR("fd00::/64") + if err != nil { + return nil, err + } if ifname == "" { ifname = "tap0" @@ -95,6 +99,7 @@ func NewParentDriver(logWriter io.Writer, binary string, mtu int, ipnet *net.IPN binary: binary, mtu: mtu, ipnet: ipnet, + ipnet6: ipnet6, disableHostLoopback: disableHostLoopback, enableIPv6: enableIPv6, ifname: ifname, @@ -109,6 +114,7 @@ type parentDriver struct { binary string mtu int ipnet *net.IPNet + ipnet6 *net.IPNet disableHostLoopback bool enableIPv6 bool ifname string @@ -170,7 +176,23 @@ func (d *parentDriver) ConfigureNetwork(childPID int, stateDir, detachedNetNSPat if d.disableHostLoopback { opts = append(opts, "--no-map-gw", "--tcp-ns=none", "--udp-ns=none") } - if !d.enableIPv6 { + if d.enableIPv6 { + // 0x100, so that the address is rendered as fd00::100 + address, err := iputils.AddIPInt6(d.ipnet6.IP, 0x100) + if err != nil { + return nil, common.Seq(cleanups), err + } + gateway, err := iputils.AddIPInt6(d.ipnet6.IP, 2) + if err != nil { + return nil, common.Seq(cleanups), err + } + dns, err := iputils.AddIPInt6(d.ipnet6.IP, 3) + if err != nil { + return nil, common.Seq(cleanups), err + } + opts = append(opts, "--address="+address.String(), "--gateway="+gateway.String(), + "--dns-forward="+dns.String()) + } else { opts = append(opts, "--ipv4-only") } if d.implicitPortForwarding {