From 22a703b669f399613c33b9d58bc5333d46d05061 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Tue, 11 May 2021 12:33:40 -0700 Subject: [PATCH] fix DONT_FRAGMENT error when using a IPv6 connection on Windows The syscall setting the IP_DONTFRAGMENT socket option will fail if the underlying connection is a IPv6 connection. Since Go doesn't allow us to distinguish between IPv6 and dual-stack connections, we can only ignore the error here. --- conn_windows.go | 18 +++++++----------- conn_windows_test.go | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/conn_windows.go b/conn_windows.go index d1f0240a4..2540d8516 100644 --- a/conn_windows.go +++ b/conn_windows.go @@ -13,24 +13,20 @@ import ( const IP_DONTFRAGMENT = 14 -func newConn(c net.PacketConn) (connection, error) { - conn, ok := c.(interface { - SyscallConn() (syscall.RawConn, error) - }) - if !ok { - return nil, errors.New("doesn't have a SyscallConn") - } - rawConn, err := conn.SyscallConn() +func newConn(c OOBCapablePacketConn) (connection, error) { + rawConn, err := c.SyscallConn() if err != nil { return nil, fmt.Errorf("couldn't get syscall.RawConn: %w", err) } - var serr error if err := rawConn.Control(func(fd uintptr) { - serr = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, IP_DONTFRAGMENT, 1) + // This should succeed if the connection is a IPv4 or a dual-stack connection. + // It will fail for IPv6 connections. + // TODO: properly handle error. + _ = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, IP_DONTFRAGMENT, 1) }); err != nil { return nil, err } - return &basicConn{PacketConn: c}, serr + return &basicConn{PacketConn: c}, nil } func inspectReadBuffer(c net.PacketConn) (int, error) { diff --git a/conn_windows_test.go b/conn_windows_test.go index 8e6ef9c29..de6758366 100644 --- a/conn_windows_test.go +++ b/conn_windows_test.go @@ -10,13 +10,23 @@ import ( ) var _ = Describe("Windows Conn Test", func() { - It("try newConn", func() { + It("works on IPv4", func() { addr, err := net.ResolveUDPAddr("udp4", "localhost:0") Expect(err).ToNot(HaveOccurred()) udpConn, err := net.ListenUDP("udp4", addr) Expect(err).ToNot(HaveOccurred()) conn, err := newConn(udpConn) Expect(err).ToNot(HaveOccurred()) - _ = conn.Close() + Expect(conn.Close()).To(Succeed()) + }) + + It("works on IPv6", func() { + addr, err := net.ResolveUDPAddr("udp6", "[::1]:0") + Expect(err).ToNot(HaveOccurred()) + udpConn, err := net.ListenUDP("udp6", addr) + Expect(err).ToNot(HaveOccurred()) + conn, err := newConn(udpConn) + Expect(err).ToNot(HaveOccurred()) + Expect(conn.Close()).To(Succeed()) }) })