diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index da726e9dc..fc97722f0 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -1176,7 +1176,9 @@ func (c *Conn) mkReceiveFunc(ruc *RebindingUDPConn, healthItem *health.ReceiveFu if neterror.PacketWasTruncated(err) { continue } - //_, err := ruc.ReadBatch(batch.msgs[:len(buffs)], MSG_ERRQUE) rcv message ip recv here + if c.peerMTUEnabled.Load() { + ruc.ReadICMPErrors(batch.msgs[:len(buffs)], c.logf) + } return 0, err } diff --git a/wgengine/magicsock/peermtu.go b/wgengine/magicsock/peermtu.go index 199585323..7de0d66c6 100644 --- a/wgengine/magicsock/peermtu.go +++ b/wgengine/magicsock/peermtu.go @@ -104,6 +104,15 @@ func (c *Conn) UpdatePMTUD() { _ = c.setDontFragment("udp6", false) newStatus = false } + err4 = c.setReceiveICMPErrors("udp4", enable) + err6 = c.setReceiveICMPErrors("udp6", enable) + + if err4 != nil || err6 != nil { + c.logf("[unexpected] magicsock: peermtu: enabling receive ICMP errors to %v failed (v4: %v, v6: %v), disabling", enable, err4, err6) + _ = c.setReceiveICMPErrors("udp4", false) + _ = c.setReceiveICMPErrors("udp6", false) + } + if debugPMTUD() { c.logf("magicsock: peermtu: peer MTU probes are %v", tstun.WireMTUsToProbe) } diff --git a/wgengine/magicsock/peermtu_darwin.go b/wgengine/magicsock/peermtu_darwin.go index a0a1aacb5..4fdc2c19e 100644 --- a/wgengine/magicsock/peermtu_darwin.go +++ b/wgengine/magicsock/peermtu_darwin.go @@ -49,3 +49,7 @@ func (c *Conn) getDontFragment(network string) (bool, error) { } return false, err } + +func (c *Conn) setReceiveICMPErrors(network string, enable bool) error { + return nil +} diff --git a/wgengine/magicsock/rebinding_conn.go b/wgengine/magicsock/rebinding_conn.go index 0a78ae397..23bd25635 100644 --- a/wgengine/magicsock/rebinding_conn.go +++ b/wgengine/magicsock/rebinding_conn.go @@ -10,9 +10,12 @@ import ( "sync" "sync/atomic" "syscall" + "unsafe" "golang.org/x/net/ipv6" + "golang.org/x/sys/unix" "tailscale.com/net/netaddr" + "tailscale.com/types/logger" "tailscale.com/types/nettype" ) @@ -178,11 +181,25 @@ func (c *RebindingUDPConn) SyscallConn() (syscall.RawConn, error) { return sc.SyscallConn() } -/*func (c *RebindingUDPConn) ReadICMPErrors(msgs []ipv6.Message) (int, error) { +func (c *RebindingUDPConn) ReadICMPErrors(msgs []ipv6.Message, logf logger.Logf) (int, error) { for { - sc, ok := c.pconn.(syscall.Conn) - a, err := sc.SyscallConn() - err := syscall.SetsockoptInt(sc.SyscallConn(), syscall.SOL_IP, syscall.IP_RECVERR, 1) - return n, err + rc, err := c.SyscallConn() + if err == nil { + rc.Control(func(fd uintptr) { + err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVERR, 1) + var p = make([]byte, 1500) + var oob = make([]byte, 1500) + _, oobn, _, _, err := syscall.Recvmsg(int(fd), p, oob, syscall.MSG_ERRQUEUE) + if err != nil { + logf("magicsock: failed to receive ICMP message %v", err) + } else if oobn <= 0 { + logf("magicsock: failed to receive ICMP message oobn") + } + se := (*unix.SockExtendedErr)(unsafe.Pointer(&oob[syscall.SizeofCmsghdr])) + if se.Origin == 2 { + logf("magicsock: received ICMP error type %v info %v", se.Type, se.Info) + } + }) + } } -}*/ +}