diff --git a/ipv4/batch.go b/ipv4/batch.go index fbe0cfd5..1a3a4fc0 100644 --- a/ipv4/batch.go +++ b/ipv4/batch.go @@ -89,6 +89,9 @@ func (c *payloadHandler) ReadBatch(ms []Message, flags int) (int, error) { n = 0 err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} } + if compatFreeBSD32 && ms[0].NN > 0 { + adjustFreeBSD32(&ms[0]) + } return n, err } } @@ -152,6 +155,9 @@ func (c *packetHandler) ReadBatch(ms []Message, flags int) (int, error) { n = 0 err = &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err} } + if compatFreeBSD32 && ms[0].NN > 0 { + adjustFreeBSD32(&ms[0]) + } return n, err } } diff --git a/ipv4/helper.go b/ipv4/helper.go index d0549523..a4457d60 100644 --- a/ipv4/helper.go +++ b/ipv4/helper.go @@ -8,6 +8,8 @@ import ( "errors" "net" "runtime" + + "golang.org/x/net/internal/socket" ) var ( @@ -23,9 +25,20 @@ var ( errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH) // See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html. - freebsdVersion uint32 + freebsdVersion uint32 + compatFreeBSD32 bool // 386 emulation on amd64 ) +// See golang.org/issue/30899. +func adjustFreeBSD32(m *socket.Message) { + if freebsdVersion >= 1103000 { + l := (m.NN + 4 - 1) &^ (4 - 1) + if m.NN < l && l <= len(m.OOB) { + m.NN = l + } + } +} + func boolint(b bool) int { if b { return 1 diff --git a/ipv4/packet.go b/ipv4/packet.go index 30e09515..7d784e06 100644 --- a/ipv4/packet.go +++ b/ipv4/packet.go @@ -46,6 +46,9 @@ func (c *packetHandler) ReadFrom(b []byte) (h *Header, p []byte, cm *ControlMess return nil, nil, nil, &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err} } if m.NN > 0 { + if compatFreeBSD32 { + adjustFreeBSD32(&m) + } cm = new(ControlMessage) if err := cm.Parse(m.OOB[:m.NN]); err != nil { return nil, nil, nil, &net.OpError{Op: "read", Net: c.IPConn.LocalAddr().Network(), Source: c.IPConn.LocalAddr(), Err: err} diff --git a/ipv4/payload_cmsg.go b/ipv4/payload_cmsg.go index e8b21c54..06930671 100644 --- a/ipv4/payload_cmsg.go +++ b/ipv4/payload_cmsg.go @@ -49,6 +49,9 @@ func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net. return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: errInvalidConnType} } if m.NN > 0 { + if compatFreeBSD32 { + adjustFreeBSD32(&m) + } cm = new(ControlMessage) if err := cm.Parse(m.OOB[:m.NN]); err != nil { return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} diff --git a/ipv4/sys_ssmreq.go b/ipv4/sys_ssmreq.go index 95eea2b6..eeced7f3 100644 --- a/ipv4/sys_ssmreq.go +++ b/ipv4/sys_ssmreq.go @@ -13,8 +13,6 @@ import ( "golang.org/x/net/internal/socket" ) -var compatFreeBSD32 bool // 386 emulation on amd64 - func (so *sockOpt) setGroupReq(c *socket.Conn, ifi *net.Interface, grp net.IP) error { var gr groupReq if ifi != nil {