From 9a518991035b3a8f23c03004d4db041a7fa6c06f Mon Sep 17 00:00:00 2001 From: WeidiDeng Date: Fri, 22 Nov 2024 00:25:03 +0000 Subject: [PATCH 1/7] http2: add SETTINGS_ENABLE_CONNECT_PROTOCOL support For golang/go#49918 Change-Id: Ibcd8fb189200c0976cf1bd03a796abae4afa4cfd GitHub-Last-Rev: cba5ecd7b7ecf842317301c425ef5107c54bc2ae GitHub-Pull-Request: golang/net#221 Reviewed-on: https://go-review.googlesource.com/c/net/+/610977 Reviewed-by: Damien Neil Auto-Submit: Damien Neil LUCI-TryBot-Result: Go LUCI Reviewed-by: Roland Shoemaker --- http2/frame.go | 4 +- http2/http2.go | 42 +++++++++++-------- http2/server.go | 35 ++++++++++++---- http2/transport.go | 91 +++++++++++++++++++++++++++++++---------- http2/transport_test.go | 62 ++++++++++++++++++++++++++++ 5 files changed, 185 insertions(+), 49 deletions(-) diff --git a/http2/frame.go b/http2/frame.go index 105c3b279c..81faec7e75 100644 --- a/http2/frame.go +++ b/http2/frame.go @@ -1490,7 +1490,7 @@ func (mh *MetaHeadersFrame) checkPseudos() error { pf := mh.PseudoFields() for i, hf := range pf { switch hf.Name { - case ":method", ":path", ":scheme", ":authority": + case ":method", ":path", ":scheme", ":authority", ":protocol": isRequest = true case ":status": isResponse = true @@ -1498,7 +1498,7 @@ func (mh *MetaHeadersFrame) checkPseudos() error { return pseudoHeaderError(hf.Name) } // Check for duplicates. - // This would be a bad algorithm, but N is 4. + // This would be a bad algorithm, but N is 5. // And this doesn't allocate. for _, hf2 := range pf[:i] { if hf.Name == hf2.Name { diff --git a/http2/http2.go b/http2/http2.go index 7688c356b7..c7601c909f 100644 --- a/http2/http2.go +++ b/http2/http2.go @@ -34,10 +34,11 @@ import ( ) var ( - VerboseLogs bool - logFrameWrites bool - logFrameReads bool - inTests bool + VerboseLogs bool + logFrameWrites bool + logFrameReads bool + inTests bool + disableExtendedConnectProtocol bool ) func init() { @@ -50,6 +51,9 @@ func init() { logFrameWrites = true logFrameReads = true } + if strings.Contains(e, "http2xconnect=0") { + disableExtendedConnectProtocol = true + } } const ( @@ -141,6 +145,10 @@ func (s Setting) Valid() error { if s.Val < 16384 || s.Val > 1<<24-1 { return ConnectionError(ErrCodeProtocol) } + case SettingEnableConnectProtocol: + if s.Val != 1 && s.Val != 0 { + return ConnectionError(ErrCodeProtocol) + } } return nil } @@ -150,21 +158,23 @@ func (s Setting) Valid() error { type SettingID uint16 const ( - SettingHeaderTableSize SettingID = 0x1 - SettingEnablePush SettingID = 0x2 - SettingMaxConcurrentStreams SettingID = 0x3 - SettingInitialWindowSize SettingID = 0x4 - SettingMaxFrameSize SettingID = 0x5 - SettingMaxHeaderListSize SettingID = 0x6 + SettingHeaderTableSize SettingID = 0x1 + SettingEnablePush SettingID = 0x2 + SettingMaxConcurrentStreams SettingID = 0x3 + SettingInitialWindowSize SettingID = 0x4 + SettingMaxFrameSize SettingID = 0x5 + SettingMaxHeaderListSize SettingID = 0x6 + SettingEnableConnectProtocol SettingID = 0x8 ) var settingName = map[SettingID]string{ - SettingHeaderTableSize: "HEADER_TABLE_SIZE", - SettingEnablePush: "ENABLE_PUSH", - SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS", - SettingInitialWindowSize: "INITIAL_WINDOW_SIZE", - SettingMaxFrameSize: "MAX_FRAME_SIZE", - SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE", + SettingHeaderTableSize: "HEADER_TABLE_SIZE", + SettingEnablePush: "ENABLE_PUSH", + SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS", + SettingInitialWindowSize: "INITIAL_WINDOW_SIZE", + SettingMaxFrameSize: "MAX_FRAME_SIZE", + SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE", + SettingEnableConnectProtocol: "ENABLE_CONNECT_PROTOCOL", } func (s SettingID) String() string { diff --git a/http2/server.go b/http2/server.go index 832414b450..b55547aec6 100644 --- a/http2/server.go +++ b/http2/server.go @@ -932,14 +932,18 @@ func (sc *serverConn) serve(conf http2Config) { sc.vlogf("http2: server connection from %v on %p", sc.conn.RemoteAddr(), sc.hs) } + settings := writeSettings{ + {SettingMaxFrameSize, conf.MaxReadFrameSize}, + {SettingMaxConcurrentStreams, sc.advMaxStreams}, + {SettingMaxHeaderListSize, sc.maxHeaderListSize()}, + {SettingHeaderTableSize, conf.MaxDecoderHeaderTableSize}, + {SettingInitialWindowSize, uint32(sc.initialStreamRecvWindowSize)}, + } + if !disableExtendedConnectProtocol { + settings = append(settings, Setting{SettingEnableConnectProtocol, 1}) + } sc.writeFrame(FrameWriteRequest{ - write: writeSettings{ - {SettingMaxFrameSize, conf.MaxReadFrameSize}, - {SettingMaxConcurrentStreams, sc.advMaxStreams}, - {SettingMaxHeaderListSize, sc.maxHeaderListSize()}, - {SettingHeaderTableSize, conf.MaxDecoderHeaderTableSize}, - {SettingInitialWindowSize, uint32(sc.initialStreamRecvWindowSize)}, - }, + write: settings, }) sc.unackedSettings++ @@ -1801,6 +1805,9 @@ func (sc *serverConn) processSetting(s Setting) error { sc.maxFrameSize = int32(s.Val) // the maximum valid s.Val is < 2^31 case SettingMaxHeaderListSize: sc.peerMaxHeaderListSize = s.Val + case SettingEnableConnectProtocol: + // Receipt of this parameter by a server does not + // have any impact default: // Unknown setting: "An endpoint that receives a SETTINGS // frame with any unknown or unsupported identifier MUST @@ -2231,11 +2238,17 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res scheme: f.PseudoValue("scheme"), authority: f.PseudoValue("authority"), path: f.PseudoValue("path"), + protocol: f.PseudoValue("protocol"), + } + + // extended connect is disabled, so we should not see :protocol + if disableExtendedConnectProtocol && rp.protocol != "" { + return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol)) } isConnect := rp.method == "CONNECT" if isConnect { - if rp.path != "" || rp.scheme != "" || rp.authority == "" { + if rp.protocol == "" && (rp.path != "" || rp.scheme != "" || rp.authority == "") { return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol)) } } else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") { @@ -2259,6 +2272,9 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res if rp.authority == "" { rp.authority = rp.header.Get("Host") } + if rp.protocol != "" { + rp.header.Set(":protocol", rp.protocol) + } rw, req, err := sc.newWriterAndRequestNoBody(st, rp) if err != nil { @@ -2285,6 +2301,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res type requestParam struct { method string scheme, authority, path string + protocol string header http.Header } @@ -2326,7 +2343,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r var url_ *url.URL var requestURI string - if rp.method == "CONNECT" { + if rp.method == "CONNECT" && rp.protocol == "" { url_ = &url.URL{Host: rp.authority} requestURI = rp.authority // mimic HTTP/1 server behavior } else { diff --git a/http2/transport.go b/http2/transport.go index f5968f4407..7fcfa89e05 100644 --- a/http2/transport.go +++ b/http2/transport.go @@ -368,25 +368,26 @@ type ClientConn struct { idleTimeout time.Duration // or 0 for never idleTimer timer - mu sync.Mutex // guards following - cond *sync.Cond // hold mu; broadcast on flow/closed changes - flow outflow // our conn-level flow control quota (cs.outflow is per stream) - inflow inflow // peer's conn-level flow control - doNotReuse bool // whether conn is marked to not be reused for any future requests - closing bool - closed bool - seenSettings bool // true if we've seen a settings frame, false otherwise - wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back - goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received - goAwayDebug string // goAway frame's debug data, retained as a string - streams map[uint32]*clientStream // client-initiated - streamsReserved int // incr by ReserveNewRequest; decr on RoundTrip - nextStreamID uint32 - pendingRequests int // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams - pings map[[8]byte]chan struct{} // in flight ping data to notification channel - br *bufio.Reader - lastActive time.Time - lastIdle time.Time // time last idle + mu sync.Mutex // guards following + cond *sync.Cond // hold mu; broadcast on flow/closed changes + flow outflow // our conn-level flow control quota (cs.outflow is per stream) + inflow inflow // peer's conn-level flow control + doNotReuse bool // whether conn is marked to not be reused for any future requests + closing bool + closed bool + seenSettings bool // true if we've seen a settings frame, false otherwise + seenSettingsChan chan struct{} // closed when seenSettings is true or frame reading fails + wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back + goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received + goAwayDebug string // goAway frame's debug data, retained as a string + streams map[uint32]*clientStream // client-initiated + streamsReserved int // incr by ReserveNewRequest; decr on RoundTrip + nextStreamID uint32 + pendingRequests int // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams + pings map[[8]byte]chan struct{} // in flight ping data to notification channel + br *bufio.Reader + lastActive time.Time + lastIdle time.Time // time last idle // Settings from peer: (also guarded by wmu) maxFrameSize uint32 maxConcurrentStreams uint32 @@ -396,6 +397,7 @@ type ClientConn struct { initialStreamRecvWindowSize int32 readIdleTimeout time.Duration pingTimeout time.Duration + extendedConnectAllowed bool // pendingResets is the number of RST_STREAM frames we have sent to the peer, // without confirming that the peer has received them. When we send a RST_STREAM, @@ -819,6 +821,7 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead. streams: make(map[uint32]*clientStream), singleUse: singleUse, + seenSettingsChan: make(chan struct{}), wantSettingsAck: true, readIdleTimeout: conf.SendPingTimeout, pingTimeout: conf.PingTimeout, @@ -1466,6 +1469,8 @@ func (cs *clientStream) doRequest(req *http.Request, streamf func(*clientStream) cs.cleanupWriteRequest(err) } +var errExtendedConnectNotSupported = errors.New("net/http: extended connect not supported by peer") + // writeRequest sends a request. // // It returns nil after the request is written, the response read, @@ -1481,12 +1486,31 @@ func (cs *clientStream) writeRequest(req *http.Request, streamf func(*clientStre return err } + // wait for setting frames to be received, a server can change this value later, + // but we just wait for the first settings frame + var isExtendedConnect bool + if req.Method == "CONNECT" && req.Header.Get(":protocol") != "" { + isExtendedConnect = true + } + // Acquire the new-request lock by writing to reqHeaderMu. // This lock guards the critical section covering allocating a new stream ID // (requires mu) and creating the stream (requires wmu). if cc.reqHeaderMu == nil { panic("RoundTrip on uninitialized ClientConn") // for tests } + if isExtendedConnect { + select { + case <-cs.reqCancel: + return errRequestCanceled + case <-ctx.Done(): + return ctx.Err() + case <-cc.seenSettingsChan: + if !cc.extendedConnectAllowed { + return errExtendedConnectNotSupported + } + } + } select { case cc.reqHeaderMu <- struct{}{}: case <-cs.reqCancel: @@ -2030,7 +2054,7 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error) func validateHeaders(hdrs http.Header) string { for k, vv := range hdrs { - if !httpguts.ValidHeaderFieldName(k) { + if !httpguts.ValidHeaderFieldName(k) && k != ":protocol" { return fmt.Sprintf("name %q", k) } for _, v := range vv { @@ -2046,6 +2070,10 @@ func validateHeaders(hdrs http.Header) string { var errNilRequestURL = errors.New("http2: Request.URI is nil") +func isNormalConnect(req *http.Request) bool { + return req.Method == "CONNECT" && req.Header.Get(":protocol") == "" +} + // requires cc.wmu be held. func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) { cc.hbuf.Reset() @@ -2066,7 +2094,7 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail } var path string - if req.Method != "CONNECT" { + if !isNormalConnect(req) { path = req.URL.RequestURI() if !validPseudoPath(path) { orig := path @@ -2103,7 +2131,7 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail m = http.MethodGet } f(":method", m) - if req.Method != "CONNECT" { + if !isNormalConnect(req) { f(":path", path) f(":scheme", req.URL.Scheme) } @@ -2507,6 +2535,9 @@ func (rl *clientConnReadLoop) run() error { if VerboseLogs { cc.vlogf("http2: Transport conn %p received error from processing frame %v: %v", cc, summarizeFrame(f), err) } + if !cc.seenSettings { + close(cc.seenSettingsChan) + } return err } } @@ -3073,6 +3104,21 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error { case SettingHeaderTableSize: cc.henc.SetMaxDynamicTableSize(s.Val) cc.peerMaxHeaderTableSize = s.Val + case SettingEnableConnectProtocol: + if err := s.Valid(); err != nil { + return err + } + // If the peer wants to send us SETTINGS_ENABLE_CONNECT_PROTOCOL, + // we require that it do so in the first SETTINGS frame. + // + // When we attempt to use extended CONNECT, we wait for the first + // SETTINGS frame to see if the server supports it. If we let the + // server enable the feature with a later SETTINGS frame, then + // users will see inconsistent results depending on whether we've + // seen that frame or not. + if !cc.seenSettings { + cc.extendedConnectAllowed = s.Val == 1 + } default: cc.vlogf("Unhandled Setting: %v", s) } @@ -3090,6 +3136,7 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error { // connection can establish to our default. cc.maxConcurrentStreams = defaultMaxConcurrentStreams } + close(cc.seenSettingsChan) cc.seenSettings = true } diff --git a/http2/transport_test.go b/http2/transport_test.go index 100da8bd1c..746f6e3eee 100644 --- a/http2/transport_test.go +++ b/http2/transport_test.go @@ -5751,3 +5751,65 @@ func TestTransportTLSNextProtoConnImmediateFailureUnused(t *testing.T) { t.Fatalf("RoundTrip after broken conn expires: got %v, want ErrNoCachedConn", err) } } + +func TestExtendedConnectClientWithServerSupport(t *testing.T) { + disableExtendedConnectProtocol = false + ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get(":protocol") != "extended-connect" { + t.Fatalf("unexpected :protocol header received") + } + t.Log(io.Copy(w, r.Body)) + }) + tr := &Transport{ + TLSClientConfig: tlsConfigInsecure, + AllowHTTP: true, + } + defer tr.CloseIdleConnections() + pr, pw := io.Pipe() + pwDone := make(chan struct{}) + req, _ := http.NewRequest("CONNECT", ts.URL, pr) + req.Header.Set(":protocol", "extended-connect") + go func() { + pw.Write([]byte("hello, extended connect")) + pw.Close() + close(pwDone) + }() + + res, err := tr.RoundTrip(req) + if err != nil { + t.Fatal(err) + } + body, err := io.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(body, []byte("hello, extended connect")) { + t.Fatal("unexpected body received") + } +} + +func TestExtendedConnectClientWithoutServerSupport(t *testing.T) { + disableExtendedConnectProtocol = true + ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) { + io.Copy(w, r.Body) + }) + tr := &Transport{ + TLSClientConfig: tlsConfigInsecure, + AllowHTTP: true, + } + defer tr.CloseIdleConnections() + pr, pw := io.Pipe() + pwDone := make(chan struct{}) + req, _ := http.NewRequest("CONNECT", ts.URL, pr) + req.Header.Set(":protocol", "extended-connect") + go func() { + pw.Write([]byte("hello, extended connect")) + pw.Close() + close(pwDone) + }() + + _, err := tr.RoundTrip(req) + if !errors.Is(err, errExtendedConnectNotSupported) { + t.Fatalf("expected error errExtendedConnectNotSupported, got: %v", err) + } +} From e9cd716925e5c6cfb200c82f9d9bf6bc4118d47a Mon Sep 17 00:00:00 2001 From: James Tucker Date: Mon, 25 Nov 2024 22:52:41 +0000 Subject: [PATCH 2/7] route: fix parse of zero-length sockaddrs in RIBs Zero-length sockaddrs were observed in RIBs within golang/go#70528. These records are to be skipped, and an invariant for later slice manipulation is to be enforced by a defensive check in parseAddr. Fixes golang/go#70528 Change-Id: I4b8b5bd2339bbadc1d1be1ce14deeb6dd3b8e536 GitHub-Last-Rev: 066ba8a559e8ff543a445246279ad808cc67660f GitHub-Pull-Request: golang/net#228 Reviewed-on: https://go-review.googlesource.com/c/net/+/631475 Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Reviewed-by: Damien Neil --- route/address.go | 18 ++++++----- route/address_darwin_test.go | 58 ++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/route/address.go b/route/address.go index bae63003f0..b649f43141 100644 --- a/route/address.go +++ b/route/address.go @@ -176,7 +176,7 @@ func parseInetAddr(af int, b []byte) (Addr, error) { ) switch af { case syscall.AF_INET: - if len(b) < (off4+1) || len(b) < int(b[0]) { + if len(b) < (off4+1) || len(b) < int(b[0]) || b[0] == 0 { return nil, errInvalidAddr } sockAddrLen := int(b[0]) @@ -188,7 +188,7 @@ func parseInetAddr(af int, b []byte) (Addr, error) { copy(a.IP[:], b[off4:n]) return a, nil case syscall.AF_INET6: - if len(b) < (off6+1) || len(b) < int(b[0]) { + if len(b) < (off6+1) || len(b) < int(b[0]) || b[0] == 0 { return nil, errInvalidAddr } sockAddrLen := int(b[0]) @@ -404,12 +404,16 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ( } b = b[l:] case syscall.AF_INET, syscall.AF_INET6: - af = int(b[1]) - a, err := parseInetAddr(af, b) - if err != nil { - return nil, err + // #70528: if the sockaddrlen is 0, no address to parse inside, + // skip over the record. + if b[0] > 0 { + af = int(b[1]) + a, err := parseInetAddr(af, b) + if err != nil { + return nil, err + } + as[i] = a } - as[i] = a l := roundup(int(b[0])) if len(b) < l { return nil, errMessageTooShort diff --git a/route/address_darwin_test.go b/route/address_darwin_test.go index 0b5c72d1dc..add72e37ec 100644 --- a/route/address_darwin_test.go +++ b/route/address_darwin_test.go @@ -86,9 +86,61 @@ var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, }, []Addr{ - &Inet6Addr{IP: [16]byte{ 0xfd, 0x84, 0x1b, 0x4e, 0x62, 0x81 }}, - &Inet6Addr{IP: [16]byte{ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff }, ZoneID: 33}, - &Inet6Addr{IP: [16]byte{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,}}, + &Inet6Addr{IP: [16]byte{0xfd, 0x84, 0x1b, 0x4e, 0x62, 0x81}}, + &Inet6Addr{IP: [16]byte{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff}, ZoneID: 33}, + &Inet6Addr{IP: [16]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + nil, + nil, + nil, + nil, + nil, + }, + }, + // golang/go#70528, the kernel can produce addresses of length 0 + { + syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK, + parseKernelInetAddr, + []byte{ + 0x00, 0x1e, 0x00, 0x00, + + 0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, + 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff, + 0x00, 0x00, 0x00, 0x00, + + 0x0e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + }, + []Addr{ + nil, + &Inet6Addr{IP: [16]byte{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff}, ZoneID: 33}, + &Inet6Addr{IP: [16]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + nil, + nil, + nil, + nil, + nil, + }, + }, + // Additional case: golang/go/issues/70528#issuecomment-2498692877 + { + syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK, + parseKernelInetAddr, + []byte{ + 0x84, 0x00, 0x05, 0x04, 0x01, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00, 0x01, 0x15, 0x00, 0x00, 0x00, + 0x1B, 0x01, 0x00, 0x00, 0xF5, 0x5A, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x14, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }, + []Addr{ + &Inet4Addr{IP: [4]byte{0x0, 0x0, 0x0, 0x0}}, + nil, + nil, nil, nil, nil, From bc37675919d77638c33240a80610699db46fb739 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 2 Dec 2024 10:30:06 -0800 Subject: [PATCH 3/7] http2: limit number of PINGs bundled with RST_STREAMs gRPC has an unfortunate behavior of stictly rate limiting the number of PING frames that it will receive. The default is two PING frames every two hours when no requests are in flight; two PING frames every five minutes when a request is in flight; and the limit resets every time the gRPC endpoint sends a HEADERS or DATA frame. When sending a RST_STREAM frame, the Transport can bundle a PING frame with it to confirm the server is responding. When canceling several requests in succession, this can result in hitting the gRPC ping limit. Work around this gRPC behavior by sending at most one bundled PING per HEADERS or DATA frame received. We already limit ourselves to one PING in flight at a time; now, when we receive a PING response, disable sending additional bundled PINGs until we read a HEADERS/DATA frame. This does not affect keep-alive pings. Fixes golang/go#70575. Change-Id: I7c4003039bd2dc52106b2806ca31eeeee37b7e09 Reviewed-on: https://go-review.googlesource.com/c/net/+/632995 Reviewed-by: Jonathan Amsterdam Auto-Submit: Damien Neil LUCI-TryBot-Result: Go LUCI --- http2/transport.go | 46 ++++++++++++++++++++------ http2/transport_test.go | 71 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 9 deletions(-) diff --git a/http2/transport.go b/http2/transport.go index 7fcfa89e05..090d0e1bdb 100644 --- a/http2/transport.go +++ b/http2/transport.go @@ -399,6 +399,16 @@ type ClientConn struct { pingTimeout time.Duration extendedConnectAllowed bool + // rstStreamPingsBlocked works around an unfortunate gRPC behavior. + // gRPC strictly limits the number of PING frames that it will receive. + // The default is two pings per two hours, but the limit resets every time + // the gRPC endpoint sends a HEADERS or DATA frame. See golang/go#70575. + // + // rstStreamPingsBlocked is set after receiving a response to a PING frame + // bundled with an RST_STREAM (see pendingResets below), and cleared after + // receiving a HEADERS or DATA frame. + rstStreamPingsBlocked bool + // pendingResets is the number of RST_STREAM frames we have sent to the peer, // without confirming that the peer has received them. When we send a RST_STREAM, // we bundle it with a PING frame, unless a PING is already in flight. We count @@ -1738,10 +1748,14 @@ func (cs *clientStream) cleanupWriteRequest(err error) { ping := false if !closeOnIdle { cc.mu.Lock() - if cc.pendingResets == 0 { - ping = true + // rstStreamPingsBlocked works around a gRPC behavior: + // see comment on the field for details. + if !cc.rstStreamPingsBlocked { + if cc.pendingResets == 0 { + ping = true + } + cc.pendingResets++ } - cc.pendingResets++ cc.mu.Unlock() } cc.writeStreamReset(cs.ID, ErrCodeCancel, ping, err) @@ -2489,7 +2503,7 @@ func (rl *clientConnReadLoop) run() error { cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err) } if se, ok := err.(StreamError); ok { - if cs := rl.streamByID(se.StreamID); cs != nil { + if cs := rl.streamByID(se.StreamID, notHeaderOrDataFrame); cs != nil { if se.Cause == nil { se.Cause = cc.fr.errDetail } @@ -2544,7 +2558,7 @@ func (rl *clientConnReadLoop) run() error { } func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error { - cs := rl.streamByID(f.StreamID) + cs := rl.streamByID(f.StreamID, headerOrDataFrame) if cs == nil { // We'd get here if we canceled a request while the // server had its response still in flight. So if this @@ -2873,7 +2887,7 @@ func (b transportResponseBody) Close() error { func (rl *clientConnReadLoop) processData(f *DataFrame) error { cc := rl.cc - cs := rl.streamByID(f.StreamID) + cs := rl.streamByID(f.StreamID, headerOrDataFrame) data := f.Data() if cs == nil { cc.mu.Lock() @@ -3008,9 +3022,22 @@ func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) { cs.abortStream(err) } -func (rl *clientConnReadLoop) streamByID(id uint32) *clientStream { +// Constants passed to streamByID for documentation purposes. +const ( + headerOrDataFrame = true + notHeaderOrDataFrame = false +) + +// streamByID returns the stream with the given id, or nil if no stream has that id. +// If headerOrData is true, it clears rst.StreamPingsBlocked. +func (rl *clientConnReadLoop) streamByID(id uint32, headerOrData bool) *clientStream { rl.cc.mu.Lock() defer rl.cc.mu.Unlock() + if headerOrData { + // Work around an unfortunate gRPC behavior. + // See comment on ClientConn.rstStreamPingsBlocked for details. + rl.cc.rstStreamPingsBlocked = false + } cs := rl.cc.streams[id] if cs != nil && !cs.readAborted { return cs @@ -3145,7 +3172,7 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error { func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error { cc := rl.cc - cs := rl.streamByID(f.StreamID) + cs := rl.streamByID(f.StreamID, notHeaderOrDataFrame) if f.StreamID != 0 && cs == nil { return nil } @@ -3174,7 +3201,7 @@ func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error { } func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error { - cs := rl.streamByID(f.StreamID) + cs := rl.streamByID(f.StreamID, notHeaderOrDataFrame) if cs == nil { // TODO: return error if server tries to RST_STREAM an idle stream return nil @@ -3252,6 +3279,7 @@ func (rl *clientConnReadLoop) processPing(f *PingFrame) error { if cc.pendingResets > 0 { // See clientStream.cleanupWriteRequest. cc.pendingResets = 0 + cc.rstStreamPingsBlocked = true cc.cond.Broadcast() } return nil diff --git a/http2/transport_test.go b/http2/transport_test.go index 746f6e3eee..0e12e0f1c7 100644 --- a/http2/transport_test.go +++ b/http2/transport_test.go @@ -5562,6 +5562,10 @@ func TestTransportSendPingWithReset(t *testing.T) { tc.wantFrameType(FrameHeaders) tc.wantIdle() + // Receive a byte of data for the remaining stream, which resets our ability + // to send pings (see comment on ClientConn.rstStreamPingsBlocked). + tc.writeData(rts[2].streamID(), false, []byte{0}) + // Cancel the last request. We send another PING, since none are in flight. rts[2].response().Body.Close() tc.wantRSTStream(rts[2].streamID(), ErrCodeCancel) @@ -5569,6 +5573,73 @@ func TestTransportSendPingWithReset(t *testing.T) { tc.wantIdle() } +// Issue #70505: gRPC gets upset if we send more than 2 pings per HEADERS/DATA frame +// sent by the server. +func TestTransportSendNoMoreThanOnePingWithReset(t *testing.T) { + tc := newTestClientConn(t) + tc.greet() + + makeAndResetRequest := func() { + t.Helper() + ctx, cancel := context.WithCancel(context.Background()) + req := must(http.NewRequestWithContext(ctx, "GET", "https://dummy.tld/", nil)) + rt := tc.roundTrip(req) + tc.wantFrameType(FrameHeaders) + cancel() + tc.wantRSTStream(rt.streamID(), ErrCodeCancel) // client sends RST_STREAM + } + + // Create a request and cancel it. + // The client sends a PING frame along with the reset. + makeAndResetRequest() + pf1 := readFrame[*PingFrame](t, tc) // client sends PING + + // Create another request and cancel it. + // We do not send a PING frame along with the reset, + // because we haven't received a HEADERS or DATA frame from the server + // since the last PING we sent. + makeAndResetRequest() + + // Server belatedly responds to request 1. + // The server has not responded to our first PING yet. + tc.writeHeaders(HeadersFrameParam{ + StreamID: 1, + EndHeaders: true, + EndStream: true, + BlockFragment: tc.makeHeaderBlockFragment( + ":status", "200", + ), + }) + + // Create yet another request and cancel it. + // We still do not send a PING frame along with the reset. + // We've received a HEADERS frame, but it came before the response to the PING. + makeAndResetRequest() + + // The server responds to our PING. + tc.writePing(true, pf1.Data) + + // Create yet another request and cancel it. + // Still no PING frame; we got a response to the previous one, + // but no HEADERS or DATA. + makeAndResetRequest() + + // Server belatedly responds to the second request. + tc.writeHeaders(HeadersFrameParam{ + StreamID: 3, + EndHeaders: true, + EndStream: true, + BlockFragment: tc.makeHeaderBlockFragment( + ":status", "200", + ), + }) + + // One more request. + // This time we send a PING frame. + makeAndResetRequest() + tc.wantFrameType(FramePing) +} + func TestTransportConnBecomesUnresponsive(t *testing.T) { // We send a number of requests in series to an unresponsive connection. // Each request is canceled or times out without a response. From 4be12533d8e2957bafe945c501689eba78cbf0f6 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 2 Dec 2024 10:25:46 -0800 Subject: [PATCH 4/7] route: change from syscall to x/sys/unix This lets us drop some of the defs files and cgo usage. Change-Id: I5a00e77610da36c752d28ea07e40b8a9c7c59ae4 Reviewed-on: https://go-review.googlesource.com/c/net/+/632816 Auto-Submit: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Damien Neil LUCI-TryBot-Result: Go LUCI --- route/address.go | 45 +++++++++++----------- route/address_darwin_test.go | 13 ++++--- route/address_test.go | 7 ++-- route/defs_darwin.go | 15 +------- route/defs_dragonfly.go | 56 --------------------------- route/defs_freebsd.go | 12 ------ route/defs_netbsd.go | 32 ---------------- route/defs_openbsd.go | 27 ------------- route/interface_classic.go | 9 +++-- route/interface_freebsd.go | 12 +++--- route/interface_openbsd.go | 8 ++-- route/message_darwin_test.go | 7 ++-- route/message_freebsd_test.go | 15 ++++---- route/message_test.go | 71 ++++++++++++++++++----------------- route/route.go | 11 +++--- route/route_classic.go | 5 ++- route/route_openbsd.go | 14 +++---- route/route_test.go | 25 ++++++------ route/sys.go | 5 ++- route/sys_darwin.go | 48 +++++++++++------------ route/sys_dragonfly.go | 53 ++++++++++++++------------ route/sys_freebsd.go | 51 ++++++++++++------------- route/sys_netbsd.go | 36 +++++++++--------- route/sys_openbsd.go | 31 +++++++-------- route/zsys_darwin.go | 15 +------- route/zsys_dragonfly.go | 20 ---------- route/zsys_freebsd_386.go | 12 ------ route/zsys_freebsd_amd64.go | 12 ------ route/zsys_freebsd_arm.go | 12 ------ route/zsys_freebsd_arm64.go | 12 ------ route/zsys_freebsd_riscv64.go | 12 ------ route/zsys_netbsd.go | 17 --------- route/zsys_openbsd.go | 12 ------ 33 files changed, 243 insertions(+), 489 deletions(-) delete mode 100644 route/defs_dragonfly.go delete mode 100644 route/defs_netbsd.go delete mode 100644 route/defs_openbsd.go delete mode 100644 route/zsys_dragonfly.go delete mode 100644 route/zsys_netbsd.go delete mode 100644 route/zsys_openbsd.go diff --git a/route/address.go b/route/address.go index b649f43141..6f72c6cc35 100644 --- a/route/address.go +++ b/route/address.go @@ -8,7 +8,8 @@ package route import ( "runtime" - "syscall" + + "golang.org/x/sys/unix" ) // An Addr represents an address associated with packet routing. @@ -25,7 +26,7 @@ type LinkAddr struct { } // Family implements the Family method of Addr interface. -func (a *LinkAddr) Family() int { return syscall.AF_LINK } +func (a *LinkAddr) Family() int { return unix.AF_LINK } func (a *LinkAddr) lenAndSpace() (int, int) { l := 8 + len(a.Name) + len(a.Addr) @@ -42,7 +43,7 @@ func (a *LinkAddr) marshal(b []byte) (int, error) { return 0, errInvalidAddr } b[0] = byte(l) - b[1] = syscall.AF_LINK + b[1] = unix.AF_LINK if a.Index > 0 { nativeEndian.PutUint16(b[2:4], uint16(a.Index)) } @@ -64,7 +65,7 @@ func parseLinkAddr(b []byte) (Addr, error) { if len(b) < 8 { return nil, errInvalidAddr } - _, a, err := parseKernelLinkAddr(syscall.AF_LINK, b[4:]) + _, a, err := parseKernelLinkAddr(unix.AF_LINK, b[4:]) if err != nil { return nil, err } @@ -124,10 +125,10 @@ type Inet4Addr struct { } // Family implements the Family method of Addr interface. -func (a *Inet4Addr) Family() int { return syscall.AF_INET } +func (a *Inet4Addr) Family() int { return unix.AF_INET } func (a *Inet4Addr) lenAndSpace() (int, int) { - return sizeofSockaddrInet, roundup(sizeofSockaddrInet) + return unix.SizeofSockaddrInet4, roundup(unix.SizeofSockaddrInet4) } func (a *Inet4Addr) marshal(b []byte) (int, error) { @@ -136,7 +137,7 @@ func (a *Inet4Addr) marshal(b []byte) (int, error) { return 0, errShortBuffer } b[0] = byte(l) - b[1] = syscall.AF_INET + b[1] = unix.AF_INET copy(b[4:8], a.IP[:]) return ll, nil } @@ -148,10 +149,10 @@ type Inet6Addr struct { } // Family implements the Family method of Addr interface. -func (a *Inet6Addr) Family() int { return syscall.AF_INET6 } +func (a *Inet6Addr) Family() int { return unix.AF_INET6 } func (a *Inet6Addr) lenAndSpace() (int, int) { - return sizeofSockaddrInet6, roundup(sizeofSockaddrInet6) + return unix.SizeofSockaddrInet6, roundup(unix.SizeofSockaddrInet6) } func (a *Inet6Addr) marshal(b []byte) (int, error) { @@ -160,7 +161,7 @@ func (a *Inet6Addr) marshal(b []byte) (int, error) { return 0, errShortBuffer } b[0] = byte(l) - b[1] = syscall.AF_INET6 + b[1] = unix.AF_INET6 copy(b[8:24], a.IP[:]) if a.ZoneID > 0 { nativeEndian.PutUint32(b[24:28], uint32(a.ZoneID)) @@ -175,7 +176,7 @@ func parseInetAddr(af int, b []byte) (Addr, error) { off6 = 8 // offset of in6_addr ) switch af { - case syscall.AF_INET: + case unix.AF_INET: if len(b) < (off4+1) || len(b) < int(b[0]) || b[0] == 0 { return nil, errInvalidAddr } @@ -187,7 +188,7 @@ func parseInetAddr(af int, b []byte) (Addr, error) { } copy(a.IP[:], b[off4:n]) return a, nil - case syscall.AF_INET6: + case unix.AF_INET6: if len(b) < (off6+1) || len(b) < int(b[0]) || b[0] == 0 { return nil, errInvalidAddr } @@ -197,7 +198,7 @@ func parseInetAddr(af int, b []byte) (Addr, error) { n = sockAddrLen } a := &Inet6Addr{} - if sockAddrLen == sizeofSockaddrInet6 { + if sockAddrLen == unix.SizeofSockaddrInet6 { a.ZoneID = int(nativeEndian.Uint32(b[24:28])) } copy(a.IP[:], b[off6:n]) @@ -260,11 +261,11 @@ func parseKernelInetAddr(af int, b []byte) (int, Addr, error) { off6 = 8 // offset of in6_addr ) switch { - case b[0] == sizeofSockaddrInet6: + case b[0] == unix.SizeofSockaddrInet6: a := &Inet6Addr{} copy(a.IP[:], b[off6:off6+16]) return int(b[0]), a, nil - case af == syscall.AF_INET6: + case af == unix.AF_INET6: a := &Inet6Addr{} if l-1 < off6 { copy(a.IP[:], b[1:l]) @@ -272,7 +273,7 @@ func parseKernelInetAddr(af int, b []byte) (int, Addr, error) { copy(a.IP[:], b[l-off6:l]) } return int(b[0]), a, nil - case b[0] == sizeofSockaddrInet: + case b[0] == unix.SizeofSockaddrInet4: a := &Inet4Addr{} copy(a.IP[:], b[off4:off4+4]) return int(b[0]), a, nil @@ -384,15 +385,15 @@ func marshalAddrs(b []byte, as []Addr) (uint, error) { } func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ([]Addr, error) { - var as [syscall.RTAX_MAX]Addr - af := int(syscall.AF_UNSPEC) - for i := uint(0); i < syscall.RTAX_MAX && len(b) >= roundup(0); i++ { + var as [unix.RTAX_MAX]Addr + af := int(unix.AF_UNSPEC) + for i := uint(0); i < unix.RTAX_MAX && len(b) >= roundup(0); i++ { if attrs&(1< 0 { diff --git a/route/address_darwin_test.go b/route/address_darwin_test.go index add72e37ec..08eb8b7d1d 100644 --- a/route/address_darwin_test.go +++ b/route/address_darwin_test.go @@ -6,8 +6,9 @@ package route import ( "reflect" - "syscall" "testing" + + "golang.org/x/sys/unix" ) type parseAddrsOnDarwinTest struct { @@ -19,7 +20,7 @@ type parseAddrsOnDarwinTest struct { var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{ { - syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK, + unix.RTA_DST | unix.RTA_GATEWAY | unix.RTA_NETMASK, parseKernelInetAddr, []byte{ 0x10, 0x2, 0x0, 0x0, 0xc0, 0xa8, 0x56, 0x0, @@ -43,7 +44,7 @@ var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{ }, }, { - syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK, + unix.RTA_DST | unix.RTA_GATEWAY | unix.RTA_NETMASK, parseKernelInetAddr, []byte{ 0x10, 0x02, 0x00, 0x00, 0x64, 0x71, 0x00, 0x00, @@ -69,7 +70,7 @@ var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{ // route -n add -inet6 fd84:1b4e:6281:: -prefixlen 48 fe80::f22f:4bff:fe09:3bff%utun4319 // gw fe80:0000:0000:0000:f22f:4bff:fe09:3bff { - syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK, + unix.RTA_DST | unix.RTA_GATEWAY | unix.RTA_NETMASK, parseKernelInetAddr, []byte{ 0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -98,7 +99,7 @@ var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{ }, // golang/go#70528, the kernel can produce addresses of length 0 { - syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK, + unix.RTA_DST | unix.RTA_GATEWAY | unix.RTA_NETMASK, parseKernelInetAddr, []byte{ 0x00, 0x1e, 0x00, 0x00, @@ -124,7 +125,7 @@ var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{ }, // Additional case: golang/go/issues/70528#issuecomment-2498692877 { - syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK, + unix.RTA_DST | unix.RTA_GATEWAY | unix.RTA_NETMASK, parseKernelInetAddr, []byte{ 0x84, 0x00, 0x05, 0x04, 0x01, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00, 0x01, 0x15, 0x00, 0x00, 0x00, diff --git a/route/address_test.go b/route/address_test.go index 31087576ed..cd0f3ab499 100644 --- a/route/address_test.go +++ b/route/address_test.go @@ -8,8 +8,9 @@ package route import ( "reflect" - "syscall" "testing" + + "golang.org/x/sys/unix" ) type parseAddrsTest struct { @@ -21,7 +22,7 @@ type parseAddrsTest struct { var parseAddrsLittleEndianTests = []parseAddrsTest{ { - syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK | syscall.RTA_BRD, + unix.RTA_DST | unix.RTA_GATEWAY | unix.RTA_NETMASK | unix.RTA_BRD, parseKernelInetAddr, []byte{ 0x38, 0x12, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, @@ -58,7 +59,7 @@ var parseAddrsLittleEndianTests = []parseAddrsTest{ }, }, { - syscall.RTA_NETMASK | syscall.RTA_IFP | syscall.RTA_IFA, + unix.RTA_NETMASK | unix.RTA_IFP | unix.RTA_IFA, parseKernelInetAddr, []byte{ 0x7, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, diff --git a/route/defs_darwin.go b/route/defs_darwin.go index ec56ca02e1..0b95479c2e 100644 --- a/route/defs_darwin.go +++ b/route/defs_darwin.go @@ -19,19 +19,8 @@ package route import "C" const ( - sizeofIfMsghdrDarwin15 = C.sizeof_struct_if_msghdr - sizeofIfaMsghdrDarwin15 = C.sizeof_struct_ifa_msghdr - sizeofIfmaMsghdrDarwin15 = C.sizeof_struct_ifma_msghdr - sizeofIfMsghdr2Darwin15 = C.sizeof_struct_if_msghdr2 - sizeofIfmaMsghdr2Darwin15 = C.sizeof_struct_ifma_msghdr2 - sizeofIfDataDarwin15 = C.sizeof_struct_if_data - sizeofIfData64Darwin15 = C.sizeof_struct_if_data64 + sizeofIfMsghdr2Darwin15 = C.sizeof_struct_if_msghdr2 + sizeofIfData64Darwin15 = C.sizeof_struct_if_data64 - sizeofRtMsghdrDarwin15 = C.sizeof_struct_rt_msghdr sizeofRtMsghdr2Darwin15 = C.sizeof_struct_rt_msghdr2 - sizeofRtMetricsDarwin15 = C.sizeof_struct_rt_metrics - - sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage - sizeofSockaddrInet = C.sizeof_struct_sockaddr_in - sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 ) diff --git a/route/defs_dragonfly.go b/route/defs_dragonfly.go deleted file mode 100644 index 9bf202dda4..0000000000 --- a/route/defs_dragonfly.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build ignore - -package route - -/* -#include -#include - -#include -#include -#include - -#include - -struct ifa_msghdr_dfly4 { - u_short ifam_msglen; - u_char ifam_version; - u_char ifam_type; - int ifam_addrs; - int ifam_flags; - u_short ifam_index; - int ifam_metric; -}; - -struct ifa_msghdr_dfly58 { - u_short ifam_msglen; - u_char ifam_version; - u_char ifam_type; - u_short ifam_index; - int ifam_flags; - int ifam_addrs; - int ifam_addrflags; - int ifam_metric; -}; -*/ -import "C" - -const ( - sizeofIfMsghdrDragonFlyBSD4 = C.sizeof_struct_if_msghdr - sizeofIfaMsghdrDragonFlyBSD4 = C.sizeof_struct_ifa_msghdr_dfly4 - sizeofIfmaMsghdrDragonFlyBSD4 = C.sizeof_struct_ifma_msghdr - sizeofIfAnnouncemsghdrDragonFlyBSD4 = C.sizeof_struct_if_announcemsghdr - - sizeofIfaMsghdrDragonFlyBSD58 = C.sizeof_struct_ifa_msghdr_dfly58 - - sizeofRtMsghdrDragonFlyBSD4 = C.sizeof_struct_rt_msghdr - sizeofRtMetricsDragonFlyBSD4 = C.sizeof_struct_rt_metrics - - sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage - sizeofSockaddrInet = C.sizeof_struct_sockaddr_in - sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 -) diff --git a/route/defs_freebsd.go b/route/defs_freebsd.go index abb2dc0957..a1318949a3 100644 --- a/route/defs_freebsd.go +++ b/route/defs_freebsd.go @@ -218,12 +218,6 @@ struct if_msghdr_freebsd11 { import "C" const ( - sizeofIfMsghdrlFreeBSD10 = C.sizeof_struct_if_msghdrl - sizeofIfaMsghdrFreeBSD10 = C.sizeof_struct_ifa_msghdr - sizeofIfaMsghdrlFreeBSD10 = C.sizeof_struct_ifa_msghdrl - sizeofIfmaMsghdrFreeBSD10 = C.sizeof_struct_ifma_msghdr - sizeofIfAnnouncemsghdrFreeBSD10 = C.sizeof_struct_if_announcemsghdr - sizeofRtMsghdrFreeBSD10 = C.sizeof_struct_rt_msghdr sizeofRtMetricsFreeBSD10 = C.sizeof_struct_rt_metrics @@ -239,12 +233,6 @@ const ( sizeofIfDataFreeBSD10 = C.sizeof_struct_if_data_freebsd10 sizeofIfDataFreeBSD11 = C.sizeof_struct_if_data_freebsd11 - sizeofIfMsghdrlFreeBSD10Emu = C.sizeof_struct_if_msghdrl - sizeofIfaMsghdrFreeBSD10Emu = C.sizeof_struct_ifa_msghdr - sizeofIfaMsghdrlFreeBSD10Emu = C.sizeof_struct_ifa_msghdrl - sizeofIfmaMsghdrFreeBSD10Emu = C.sizeof_struct_ifma_msghdr - sizeofIfAnnouncemsghdrFreeBSD10Emu = C.sizeof_struct_if_announcemsghdr - sizeofRtMsghdrFreeBSD10Emu = C.sizeof_struct_rt_msghdr sizeofRtMetricsFreeBSD10Emu = C.sizeof_struct_rt_metrics diff --git a/route/defs_netbsd.go b/route/defs_netbsd.go deleted file mode 100644 index 8e89934c5a..0000000000 --- a/route/defs_netbsd.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build ignore - -package route - -/* -#include -#include - -#include -#include -#include - -#include -*/ -import "C" - -const ( - sizeofIfMsghdrNetBSD7 = C.sizeof_struct_if_msghdr - sizeofIfaMsghdrNetBSD7 = C.sizeof_struct_ifa_msghdr - sizeofIfAnnouncemsghdrNetBSD7 = C.sizeof_struct_if_announcemsghdr - - sizeofRtMsghdrNetBSD7 = C.sizeof_struct_rt_msghdr - sizeofRtMetricsNetBSD7 = C.sizeof_struct_rt_metrics - - sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage - sizeofSockaddrInet = C.sizeof_struct_sockaddr_in - sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 -) diff --git a/route/defs_openbsd.go b/route/defs_openbsd.go deleted file mode 100644 index 8f3218bc63..0000000000 --- a/route/defs_openbsd.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build ignore - -package route - -/* -#include -#include - -#include -#include -#include - -#include -*/ -import "C" - -const ( - sizeofRtMsghdr = C.sizeof_struct_rt_msghdr - - sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage - sizeofSockaddrInet = C.sizeof_struct_sockaddr_in - sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 -) diff --git a/route/interface_classic.go b/route/interface_classic.go index be1bf2652e..e1dc4eba58 100644 --- a/route/interface_classic.go +++ b/route/interface_classic.go @@ -8,7 +8,8 @@ package route import ( "runtime" - "syscall" + + "golang.org/x/sys/unix" ) func (w *wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) { @@ -20,13 +21,13 @@ func (w *wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) return nil, errInvalidMessage } attrs := uint(nativeEndian.Uint32(b[4:8])) - if attrs&syscall.RTA_IFP == 0 { + if attrs&unix.RTA_IFP == 0 { return nil, nil } m := &InterfaceMessage{ Version: int(b[2]), Type: int(b[3]), - Addrs: make([]Addr, syscall.RTAX_MAX), + Addrs: make([]Addr, unix.RTAX_MAX), Flags: int(nativeEndian.Uint32(b[8:12])), Index: int(nativeEndian.Uint16(b[12:14])), extOff: w.extOff, @@ -36,7 +37,7 @@ func (w *wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) if err != nil { return nil, err } - m.Addrs[syscall.RTAX_IFP] = a + m.Addrs[unix.RTAX_IFP] = a m.Name = a.(*LinkAddr).Name return m, nil } diff --git a/route/interface_freebsd.go b/route/interface_freebsd.go index 14d251c94f..7e90b17d33 100644 --- a/route/interface_freebsd.go +++ b/route/interface_freebsd.go @@ -4,11 +4,11 @@ package route -import "syscall" +import "golang.org/x/sys/unix" func (w *wireFormat) parseInterfaceMessage(typ RIBType, b []byte) (Message, error) { var extOff, bodyOff int - if typ == syscall.NET_RT_IFLISTL { + if typ == unix.NET_RT_IFLISTL { if len(b) < 20 { return nil, errMessageTooShort } @@ -26,7 +26,7 @@ func (w *wireFormat) parseInterfaceMessage(typ RIBType, b []byte) (Message, erro return nil, errInvalidMessage } attrs := uint(nativeEndian.Uint32(b[4:8])) - if attrs&syscall.RTA_IFP == 0 { + if attrs&unix.RTA_IFP == 0 { return nil, nil } m := &InterfaceMessage{ @@ -34,7 +34,7 @@ func (w *wireFormat) parseInterfaceMessage(typ RIBType, b []byte) (Message, erro Type: int(b[3]), Flags: int(nativeEndian.Uint32(b[8:12])), Index: int(nativeEndian.Uint16(b[12:14])), - Addrs: make([]Addr, syscall.RTAX_MAX), + Addrs: make([]Addr, unix.RTAX_MAX), extOff: extOff, raw: b[:l], } @@ -42,14 +42,14 @@ func (w *wireFormat) parseInterfaceMessage(typ RIBType, b []byte) (Message, erro if err != nil { return nil, err } - m.Addrs[syscall.RTAX_IFP] = a + m.Addrs[unix.RTAX_IFP] = a m.Name = a.(*LinkAddr).Name return m, nil } func (w *wireFormat) parseInterfaceAddrMessage(typ RIBType, b []byte) (Message, error) { var bodyOff int - if typ == syscall.NET_RT_IFLISTL { + if typ == unix.NET_RT_IFLISTL { if len(b) < 24 { return nil, errMessageTooShort } diff --git a/route/interface_openbsd.go b/route/interface_openbsd.go index d369409a72..fe003e39de 100644 --- a/route/interface_openbsd.go +++ b/route/interface_openbsd.go @@ -4,7 +4,7 @@ package route -import "syscall" +import "golang.org/x/sys/unix" func (*wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) { if len(b) < 32 { @@ -15,7 +15,7 @@ func (*wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) { return nil, errInvalidMessage } attrs := uint(nativeEndian.Uint32(b[12:16])) - if attrs&syscall.RTA_IFP == 0 { + if attrs&unix.RTA_IFP == 0 { return nil, nil } m := &InterfaceMessage{ @@ -23,7 +23,7 @@ func (*wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) { Type: int(b[3]), Flags: int(nativeEndian.Uint32(b[16:20])), Index: int(nativeEndian.Uint16(b[6:8])), - Addrs: make([]Addr, syscall.RTAX_MAX), + Addrs: make([]Addr, unix.RTAX_MAX), raw: b[:l], } ll := int(nativeEndian.Uint16(b[4:6])) @@ -34,7 +34,7 @@ func (*wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) { if err != nil { return nil, err } - m.Addrs[syscall.RTAX_IFP] = a + m.Addrs[unix.RTAX_IFP] = a m.Name = a.(*LinkAddr).Name return m, nil } diff --git a/route/message_darwin_test.go b/route/message_darwin_test.go index 7d6a3c75e8..debe2e6b42 100644 --- a/route/message_darwin_test.go +++ b/route/message_darwin_test.go @@ -5,15 +5,16 @@ package route import ( - "syscall" "testing" + + "golang.org/x/sys/unix" ) func TestFetchAndParseRIBOnDarwin(t *testing.T) { - for _, typ := range []RIBType{syscall.NET_RT_FLAGS, syscall.NET_RT_DUMP2, syscall.NET_RT_IFLIST2} { + for _, typ := range []RIBType{unix.NET_RT_FLAGS, unix.NET_RT_DUMP2, unix.NET_RT_IFLIST2} { var lastErr error var ms []Message - for _, af := range []int{syscall.AF_UNSPEC, syscall.AF_INET, syscall.AF_INET6} { + for _, af := range []int{unix.AF_UNSPEC, unix.AF_INET, unix.AF_INET6} { rs, err := fetchAndParseRIB(af, typ) if err != nil { lastErr = err diff --git a/route/message_freebsd_test.go b/route/message_freebsd_test.go index 62677c1e30..9f899c6991 100644 --- a/route/message_freebsd_test.go +++ b/route/message_freebsd_test.go @@ -5,15 +5,16 @@ package route import ( - "syscall" "testing" + + "golang.org/x/sys/unix" ) func TestFetchAndParseRIBOnFreeBSD(t *testing.T) { - for _, typ := range []RIBType{syscall.NET_RT_IFMALIST} { + for _, typ := range []RIBType{unix.NET_RT_IFMALIST} { var lastErr error var ms []Message - for _, af := range []int{syscall.AF_UNSPEC, syscall.AF_INET, syscall.AF_INET6} { + for _, af := range []int{unix.AF_UNSPEC, unix.AF_INET, unix.AF_INET6} { rs, err := fetchAndParseRIB(af, typ) if err != nil { lastErr = err @@ -37,7 +38,7 @@ func TestFetchAndParseRIBOnFreeBSD(t *testing.T) { } func TestFetchAndParseRIBOnFreeBSD10AndAbove(t *testing.T) { - if _, err := FetchRIB(syscall.AF_UNSPEC, syscall.NET_RT_IFLISTL, 0); err != nil { + if _, err := FetchRIB(unix.AF_UNSPEC, unix.NET_RT_IFLISTL, 0); err != nil { t.Skip("NET_RT_IFLISTL not supported") } if compatFreeBSD32 { @@ -50,12 +51,12 @@ func TestFetchAndParseRIBOnFreeBSD10AndAbove(t *testing.T) { msgs []Message ss []string }{ - {typ: syscall.NET_RT_IFLIST}, - {typ: syscall.NET_RT_IFLISTL}, + {typ: unix.NET_RT_IFLIST}, + {typ: unix.NET_RT_IFLISTL}, } for i := range tests { var lastErr error - for _, af := range []int{syscall.AF_UNSPEC, syscall.AF_INET, syscall.AF_INET6} { + for _, af := range []int{unix.AF_UNSPEC, unix.AF_INET, unix.AF_INET6} { rs, err := fetchAndParseRIB(af, tests[i].typ) if err != nil { lastErr = err diff --git a/route/message_test.go b/route/message_test.go index 9381f1b2df..74e8c0ade7 100644 --- a/route/message_test.go +++ b/route/message_test.go @@ -8,16 +8,17 @@ package route import ( "os" - "syscall" "testing" "time" + + "golang.org/x/sys/unix" ) func TestFetchAndParseRIB(t *testing.T) { - for _, typ := range []RIBType{syscall.NET_RT_DUMP, syscall.NET_RT_IFLIST} { + for _, typ := range []RIBType{unix.NET_RT_DUMP, unix.NET_RT_IFLIST} { var lastErr error var ms []Message - for _, af := range []int{syscall.AF_UNSPEC, syscall.AF_INET, syscall.AF_INET6} { + for _, af := range []int{unix.AF_UNSPEC, unix.AF_INET, unix.AF_INET6} { rs, err := fetchAndParseRIB(af, typ) if err != nil { lastErr = err @@ -48,7 +49,7 @@ var ( func init() { // We need to keep rtmonSock alive to avoid treading on // recycled socket descriptors. - rtmonSock, rtmonErr = syscall.Socket(syscall.AF_ROUTE, syscall.SOCK_RAW, syscall.AF_UNSPEC) + rtmonSock, rtmonErr = unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC) } // TestMonitorAndParseRIB leaks a worker goroutine and a socket @@ -84,7 +85,7 @@ func TestMonitorAndParseRIB(t *testing.T) { // use the net package of standard library due // to the lack of support for routing socket // and circular dependency. - n, err := syscall.Read(rtmonSock, b) + n, err := unix.Read(rtmonSock, b) if err != nil { return } @@ -144,60 +145,60 @@ func TestParseRIBWithFuzz(t *testing.T) { } func TestRouteMessage(t *testing.T) { - s, err := syscall.Socket(syscall.AF_ROUTE, syscall.SOCK_RAW, syscall.AF_UNSPEC) + s, err := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC) if err != nil { t.Fatal(err) } - defer syscall.Close(s) + defer unix.Close(s) var ms []RouteMessage - for _, af := range []int{syscall.AF_INET, syscall.AF_INET6} { - if _, err := fetchAndParseRIB(af, syscall.NET_RT_DUMP); err != nil { + for _, af := range []int{unix.AF_INET, unix.AF_INET6} { + if _, err := fetchAndParseRIB(af, unix.NET_RT_DUMP); err != nil { t.Log(err) continue } switch af { - case syscall.AF_INET: + case unix.AF_INET: ms = append(ms, []RouteMessage{ { - Type: syscall.RTM_GET, + Type: unix.RTM_GET, Addrs: []Addr{ - syscall.RTAX_DST: &Inet4Addr{IP: [4]byte{127, 0, 0, 1}}, - syscall.RTAX_GATEWAY: nil, - syscall.RTAX_NETMASK: nil, - syscall.RTAX_GENMASK: nil, - syscall.RTAX_IFP: &LinkAddr{}, - syscall.RTAX_IFA: &Inet4Addr{}, - syscall.RTAX_AUTHOR: nil, - syscall.RTAX_BRD: &Inet4Addr{}, + unix.RTAX_DST: &Inet4Addr{IP: [4]byte{127, 0, 0, 1}}, + unix.RTAX_GATEWAY: nil, + unix.RTAX_NETMASK: nil, + unix.RTAX_GENMASK: nil, + unix.RTAX_IFP: &LinkAddr{}, + unix.RTAX_IFA: &Inet4Addr{}, + unix.RTAX_AUTHOR: nil, + unix.RTAX_BRD: &Inet4Addr{}, }, }, { - Type: syscall.RTM_GET, + Type: unix.RTM_GET, Addrs: []Addr{ - syscall.RTAX_DST: &Inet4Addr{IP: [4]byte{127, 0, 0, 1}}, + unix.RTAX_DST: &Inet4Addr{IP: [4]byte{127, 0, 0, 1}}, }, }, }...) - case syscall.AF_INET6: + case unix.AF_INET6: ms = append(ms, []RouteMessage{ { - Type: syscall.RTM_GET, + Type: unix.RTM_GET, Addrs: []Addr{ - syscall.RTAX_DST: &Inet6Addr{IP: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}, - syscall.RTAX_GATEWAY: nil, - syscall.RTAX_NETMASK: nil, - syscall.RTAX_GENMASK: nil, - syscall.RTAX_IFP: &LinkAddr{}, - syscall.RTAX_IFA: &Inet6Addr{}, - syscall.RTAX_AUTHOR: nil, - syscall.RTAX_BRD: &Inet6Addr{}, + unix.RTAX_DST: &Inet6Addr{IP: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}, + unix.RTAX_GATEWAY: nil, + unix.RTAX_NETMASK: nil, + unix.RTAX_GENMASK: nil, + unix.RTAX_IFP: &LinkAddr{}, + unix.RTAX_IFA: &Inet6Addr{}, + unix.RTAX_AUTHOR: nil, + unix.RTAX_BRD: &Inet6Addr{}, }, }, { - Type: syscall.RTM_GET, + Type: unix.RTM_GET, Addrs: []Addr{ - syscall.RTAX_DST: &Inet6Addr{IP: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}, + unix.RTAX_DST: &Inet6Addr{IP: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}, }, }, }...) @@ -210,11 +211,11 @@ func TestRouteMessage(t *testing.T) { if err != nil { t.Fatalf("%v: %v", m, err) } - if _, err := syscall.Write(s, wb); err != nil { + if _, err := unix.Write(s, wb); err != nil { t.Fatalf("%v: %v", m, err) } rb := make([]byte, os.Getpagesize()) - n, err := syscall.Read(s, rb) + n, err := unix.Read(s, rb) if err != nil { t.Fatalf("%v: %v", m, err) } diff --git a/route/route.go b/route/route.go index ca2ce2b887..0a20f507cd 100644 --- a/route/route.go +++ b/route/route.go @@ -15,7 +15,8 @@ package route import ( "errors" "os" - "syscall" + + "golang.org/x/sys/unix" ) var ( @@ -92,8 +93,8 @@ func (m *RouteMessage) Marshal() ([]byte, error) { type RIBType int const ( - RIBTypeRoute RIBType = syscall.NET_RT_DUMP - RIBTypeInterface RIBType = syscall.NET_RT_IFLIST + RIBTypeRoute RIBType = unix.NET_RT_DUMP + RIBTypeInterface RIBType = unix.NET_RT_IFLIST ) // FetchRIB fetches a routing information base from the operating @@ -110,7 +111,7 @@ func FetchRIB(af int, typ RIBType, arg int) ([]byte, error) { try := 0 for { try++ - mib := [6]int32{syscall.CTL_NET, syscall.AF_ROUTE, 0, int32(af), int32(typ), int32(arg)} + mib := [6]int32{unix.CTL_NET, unix.AF_ROUTE, 0, int32(af), int32(typ), int32(arg)} n := uintptr(0) if err := sysctl(mib[:], nil, &n, nil, 0); err != nil { return nil, os.NewSyscallError("sysctl", err) @@ -124,7 +125,7 @@ func FetchRIB(af int, typ RIBType, arg int) ([]byte, error) { // between the two sysctl calls, try a few times // before failing. (golang.org/issue/45736). const maxTries = 3 - if err == syscall.ENOMEM && try < maxTries { + if err == unix.ENOMEM && try < maxTries { continue } return nil, os.NewSyscallError("sysctl", err) diff --git a/route/route_classic.go b/route/route_classic.go index e273fe39ab..6501378609 100644 --- a/route/route_classic.go +++ b/route/route_classic.go @@ -8,7 +8,8 @@ package route import ( "runtime" - "syscall" + + "golang.org/x/sys/unix" ) func (m *RouteMessage) marshal() ([]byte, error) { @@ -62,7 +63,7 @@ func (w *wireFormat) parseRouteMessage(typ RIBType, b []byte) (Message, error) { extOff: w.extOff, raw: b[:l], } - errno := syscall.Errno(nativeEndian.Uint32(b[28:32])) + errno := unix.Errno(nativeEndian.Uint32(b[28:32])) if errno != 0 { m.Err = errno } diff --git a/route/route_openbsd.go b/route/route_openbsd.go index f848fb1f24..c592bd8eee 100644 --- a/route/route_openbsd.go +++ b/route/route_openbsd.go @@ -5,25 +5,25 @@ package route import ( - "syscall" + "golang.org/x/sys/unix" ) func (m *RouteMessage) marshal() ([]byte, error) { - l := sizeofRtMsghdr + addrsSpace(m.Addrs) + l := unix.SizeofRtMsghdr + addrsSpace(m.Addrs) b := make([]byte, l) nativeEndian.PutUint16(b[:2], uint16(l)) if m.Version == 0 { - b[2] = syscall.RTM_VERSION + b[2] = unix.RTM_VERSION } else { b[2] = byte(m.Version) } b[3] = byte(m.Type) - nativeEndian.PutUint16(b[4:6], uint16(sizeofRtMsghdr)) + nativeEndian.PutUint16(b[4:6], uint16(unix.SizeofRtMsghdr)) nativeEndian.PutUint32(b[16:20], uint32(m.Flags)) nativeEndian.PutUint16(b[6:8], uint16(m.Index)) nativeEndian.PutUint32(b[24:28], uint32(m.ID)) nativeEndian.PutUint32(b[28:32], uint32(m.Seq)) - attrs, err := marshalAddrs(b[sizeofRtMsghdr:], m.Addrs) + attrs, err := marshalAddrs(b[unix.SizeofRtMsghdr:], m.Addrs) if err != nil { return nil, err } @@ -34,7 +34,7 @@ func (m *RouteMessage) marshal() ([]byte, error) { } func (*wireFormat) parseRouteMessage(_ RIBType, b []byte) (Message, error) { - if len(b) < sizeofRtMsghdr { + if len(b) < unix.SizeofRtMsghdr { return nil, errMessageTooShort } l := int(nativeEndian.Uint16(b[:2])) @@ -54,7 +54,7 @@ func (*wireFormat) parseRouteMessage(_ RIBType, b []byte) (Message, error) { if len(b) < ll { return nil, errInvalidMessage } - errno := syscall.Errno(nativeEndian.Uint32(b[32:36])) + errno := unix.Errno(nativeEndian.Uint32(b[32:36])) if errno != 0 { m.Err = errno } diff --git a/route/route_test.go b/route/route_test.go index ba57702178..9f00a498cd 100644 --- a/route/route_test.go +++ b/route/route_test.go @@ -10,7 +10,8 @@ import ( "fmt" "os/exec" "runtime" - "syscall" + + "golang.org/x/sys/unix" ) func (m *RouteMessage) String() string { @@ -176,13 +177,13 @@ type addrFamily int func (af addrFamily) String() string { switch af { - case syscall.AF_UNSPEC: + case unix.AF_UNSPEC: return "unspec" - case syscall.AF_LINK: + case unix.AF_LINK: return "link" - case syscall.AF_INET: + case unix.AF_INET: return "inet4" - case syscall.AF_INET6: + case unix.AF_INET6: return "inet6" default: return fmt.Sprintf("%d", af) @@ -281,24 +282,24 @@ func (as addrs) String() string { func (as addrs) match(attrs addrAttrs) error { var ts addrAttrs - af := syscall.AF_UNSPEC + af := unix.AF_UNSPEC for i := range as { if as[i] != nil { ts |= 1 << uint(i) } switch as[i].(type) { case *Inet4Addr: - if af == syscall.AF_UNSPEC { - af = syscall.AF_INET + if af == unix.AF_UNSPEC { + af = unix.AF_INET } - if af != syscall.AF_INET { + if af != unix.AF_INET { return fmt.Errorf("got %v; want %v", addrs(as), addrFamily(af)) } case *Inet6Addr: - if af == syscall.AF_UNSPEC { - af = syscall.AF_INET6 + if af == unix.AF_UNSPEC { + af = unix.AF_INET6 } - if af != syscall.AF_INET6 { + if af != unix.AF_INET6 { return fmt.Errorf("got %v; want %v", addrs(as), addrFamily(af)) } } diff --git a/route/sys.go b/route/sys.go index fcebee58ec..497819e41d 100644 --- a/route/sys.go +++ b/route/sys.go @@ -7,8 +7,9 @@ package route import ( - "syscall" "unsafe" + + "golang.org/x/sys/unix" ) var ( @@ -27,7 +28,7 @@ func init() { nativeEndian = bigEndian } // might get overridden in probeRoutingStack - rtmVersion = syscall.RTM_VERSION + rtmVersion = unix.RTM_VERSION kernelAlign, wireFormats = probeRoutingStack() } diff --git a/route/sys_darwin.go b/route/sys_darwin.go index c8c4eecb8e..6444a3dcd5 100644 --- a/route/sys_darwin.go +++ b/route/sys_darwin.go @@ -4,11 +4,11 @@ package route -import "syscall" +import "golang.org/x/sys/unix" func (typ RIBType) parseable() bool { switch typ { - case syscall.NET_RT_STAT, syscall.NET_RT_TRASH: + case unix.NET_RT_STAT, unix.NET_RT_TRASH: return false default: return true @@ -52,38 +52,38 @@ func (m *InterfaceMessage) Sys() []Sys { } func probeRoutingStack() (int, map[int]*wireFormat) { - rtm := &wireFormat{extOff: 36, bodyOff: sizeofRtMsghdrDarwin15} + rtm := &wireFormat{extOff: 36, bodyOff: unix.SizeofRtMsghdr} rtm.parse = rtm.parseRouteMessage rtm2 := &wireFormat{extOff: 36, bodyOff: sizeofRtMsghdr2Darwin15} rtm2.parse = rtm2.parseRouteMessage - ifm := &wireFormat{extOff: 16, bodyOff: sizeofIfMsghdrDarwin15} + ifm := &wireFormat{extOff: 16, bodyOff: unix.SizeofIfMsghdr} ifm.parse = ifm.parseInterfaceMessage ifm2 := &wireFormat{extOff: 32, bodyOff: sizeofIfMsghdr2Darwin15} ifm2.parse = ifm2.parseInterfaceMessage - ifam := &wireFormat{extOff: sizeofIfaMsghdrDarwin15, bodyOff: sizeofIfaMsghdrDarwin15} + ifam := &wireFormat{extOff: unix.SizeofIfaMsghdr, bodyOff: unix.SizeofIfaMsghdr} ifam.parse = ifam.parseInterfaceAddrMessage - ifmam := &wireFormat{extOff: sizeofIfmaMsghdrDarwin15, bodyOff: sizeofIfmaMsghdrDarwin15} + ifmam := &wireFormat{extOff: unix.SizeofIfmaMsghdr, bodyOff: unix.SizeofIfmaMsghdr} ifmam.parse = ifmam.parseInterfaceMulticastAddrMessage - ifmam2 := &wireFormat{extOff: sizeofIfmaMsghdr2Darwin15, bodyOff: sizeofIfmaMsghdr2Darwin15} + ifmam2 := &wireFormat{extOff: unix.SizeofIfmaMsghdr2, bodyOff: unix.SizeofIfmaMsghdr2} ifmam2.parse = ifmam2.parseInterfaceMulticastAddrMessage // Darwin kernels require 32-bit aligned access to routing facilities. return 4, map[int]*wireFormat{ - syscall.RTM_ADD: rtm, - syscall.RTM_DELETE: rtm, - syscall.RTM_CHANGE: rtm, - syscall.RTM_GET: rtm, - syscall.RTM_LOSING: rtm, - syscall.RTM_REDIRECT: rtm, - syscall.RTM_MISS: rtm, - syscall.RTM_LOCK: rtm, - syscall.RTM_RESOLVE: rtm, - syscall.RTM_NEWADDR: ifam, - syscall.RTM_DELADDR: ifam, - syscall.RTM_IFINFO: ifm, - syscall.RTM_NEWMADDR: ifmam, - syscall.RTM_DELMADDR: ifmam, - syscall.RTM_IFINFO2: ifm2, - syscall.RTM_NEWMADDR2: ifmam2, - syscall.RTM_GET2: rtm2, + unix.RTM_ADD: rtm, + unix.RTM_DELETE: rtm, + unix.RTM_CHANGE: rtm, + unix.RTM_GET: rtm, + unix.RTM_LOSING: rtm, + unix.RTM_REDIRECT: rtm, + unix.RTM_MISS: rtm, + unix.RTM_LOCK: rtm, + unix.RTM_RESOLVE: rtm, + unix.RTM_NEWADDR: ifam, + unix.RTM_DELADDR: ifam, + unix.RTM_IFINFO: ifm, + unix.RTM_NEWMADDR: ifmam, + unix.RTM_DELMADDR: ifmam, + unix.RTM_IFINFO2: ifm2, + unix.RTM_NEWMADDR2: ifmam2, + unix.RTM_GET2: rtm2, } } diff --git a/route/sys_dragonfly.go b/route/sys_dragonfly.go index 577fb16eb4..4fb118cd74 100644 --- a/route/sys_dragonfly.go +++ b/route/sys_dragonfly.go @@ -5,8 +5,9 @@ package route import ( - "syscall" "unsafe" + + "golang.org/x/sys/unix" ) func (typ RIBType) parseable() bool { return true } @@ -49,40 +50,42 @@ func (m *InterfaceMessage) Sys() []Sys { func probeRoutingStack() (int, map[int]*wireFormat) { var p uintptr - rtm := &wireFormat{extOff: 40, bodyOff: sizeofRtMsghdrDragonFlyBSD4} + rtm := &wireFormat{extOff: 40, bodyOff: unix.SizeofRtMsghdr} rtm.parse = rtm.parseRouteMessage - ifm := &wireFormat{extOff: 16, bodyOff: sizeofIfMsghdrDragonFlyBSD4} + ifm := &wireFormat{extOff: 16, bodyOff: unix.SizeofIfMsghdr} ifm.parse = ifm.parseInterfaceMessage - ifam := &wireFormat{extOff: sizeofIfaMsghdrDragonFlyBSD4, bodyOff: sizeofIfaMsghdrDragonFlyBSD4} + ifam := &wireFormat{extOff: unix.SizeofIfmaMsghdr, bodyOff: unix.SizeofIfaMsghdr} ifam.parse = ifam.parseInterfaceAddrMessage - ifmam := &wireFormat{extOff: sizeofIfmaMsghdrDragonFlyBSD4, bodyOff: sizeofIfmaMsghdrDragonFlyBSD4} + ifmam := &wireFormat{extOff: unix.SizeofIfmaMsghdr, bodyOff: unix.SizeofIfmaMsghdr} ifmam.parse = ifmam.parseInterfaceMulticastAddrMessage - ifanm := &wireFormat{extOff: sizeofIfAnnouncemsghdrDragonFlyBSD4, bodyOff: sizeofIfAnnouncemsghdrDragonFlyBSD4} + ifanm := &wireFormat{extOff: unix.SizeofIfAnnounceMsghdr, bodyOff: unix.SizeofIfAnnounceMsghdr} ifanm.parse = ifanm.parseInterfaceAnnounceMessage - rel, _ := syscall.SysctlUint32("kern.osreldate") - if rel >= 500705 { + rel, _ := unix.SysctlUint32("kern.osreldate") + if rel < 500705 { // https://github.com/DragonFlyBSD/DragonFlyBSD/commit/43a373152df2d405c9940983e584e6a25e76632d - // but only the size of struct ifa_msghdr actually changed + // but only the size of struct ifa_msghdr actually changed. + // The type is not in current header files, + // so we just use constants here. rtmVersion = 7 - ifam.bodyOff = sizeofIfaMsghdrDragonFlyBSD58 + ifam.bodyOff = 0x14 } return int(unsafe.Sizeof(p)), map[int]*wireFormat{ - syscall.RTM_ADD: rtm, - syscall.RTM_DELETE: rtm, - syscall.RTM_CHANGE: rtm, - syscall.RTM_GET: rtm, - syscall.RTM_LOSING: rtm, - syscall.RTM_REDIRECT: rtm, - syscall.RTM_MISS: rtm, - syscall.RTM_LOCK: rtm, - syscall.RTM_RESOLVE: rtm, - syscall.RTM_NEWADDR: ifam, - syscall.RTM_DELADDR: ifam, - syscall.RTM_IFINFO: ifm, - syscall.RTM_NEWMADDR: ifmam, - syscall.RTM_DELMADDR: ifmam, - syscall.RTM_IFANNOUNCE: ifanm, + unix.RTM_ADD: rtm, + unix.RTM_DELETE: rtm, + unix.RTM_CHANGE: rtm, + unix.RTM_GET: rtm, + unix.RTM_LOSING: rtm, + unix.RTM_REDIRECT: rtm, + unix.RTM_MISS: rtm, + unix.RTM_LOCK: rtm, + unix.RTM_RESOLVE: rtm, + unix.RTM_NEWADDR: ifam, + unix.RTM_DELADDR: ifam, + unix.RTM_IFINFO: ifm, + unix.RTM_NEWMADDR: ifmam, + unix.RTM_DELMADDR: ifmam, + unix.RTM_IFANNOUNCE: ifanm, } } diff --git a/route/sys_freebsd.go b/route/sys_freebsd.go index 0a66dcedb3..608f1a9307 100644 --- a/route/sys_freebsd.go +++ b/route/sys_freebsd.go @@ -5,8 +5,9 @@ package route import ( - "syscall" "unsafe" + + "golang.org/x/sys/unix" ) func (typ RIBType) parseable() bool { return true } @@ -64,7 +65,7 @@ func probeRoutingStack() (int, map[int]*wireFormat) { // to know the underlying kernel's architecture because the // alignment for routing facilities are set at the build time // of the kernel. - conf, _ := syscall.Sysctl("kern.conftxt") + conf, _ := unix.Sysctl("kern.conftxt") for i, j := 0, 0; j < len(conf); j++ { if conf[j] != '\n' { continue @@ -88,21 +89,17 @@ func probeRoutingStack() (int, map[int]*wireFormat) { if align != wordSize { compatFreeBSD32 = true // 386 emulation on amd64 } - var rtm, ifm, ifam, ifmam, ifanm *wireFormat + var rtm *wireFormat + ifam := &wireFormat{extOff: unix.SizeofIfaMsghdr, bodyOff: unix.SizeofIfaMsghdr} + ifmam := &wireFormat{extOff: unix.SizeofIfmaMsghdr, bodyOff: unix.SizeofIfmaMsghdr} + ifanm := &wireFormat{extOff: unix.SizeofIfAnnounceMsghdr, bodyOff: unix.SizeofIfAnnounceMsghdr} + ifm := &wireFormat{extOff: 16} if compatFreeBSD32 { rtm = &wireFormat{extOff: sizeofRtMsghdrFreeBSD10Emu - sizeofRtMetricsFreeBSD10Emu, bodyOff: sizeofRtMsghdrFreeBSD10Emu} - ifm = &wireFormat{extOff: 16} - ifam = &wireFormat{extOff: sizeofIfaMsghdrFreeBSD10Emu, bodyOff: sizeofIfaMsghdrFreeBSD10Emu} - ifmam = &wireFormat{extOff: sizeofIfmaMsghdrFreeBSD10Emu, bodyOff: sizeofIfmaMsghdrFreeBSD10Emu} - ifanm = &wireFormat{extOff: sizeofIfAnnouncemsghdrFreeBSD10Emu, bodyOff: sizeofIfAnnouncemsghdrFreeBSD10Emu} } else { rtm = &wireFormat{extOff: sizeofRtMsghdrFreeBSD10 - sizeofRtMetricsFreeBSD10, bodyOff: sizeofRtMsghdrFreeBSD10} - ifm = &wireFormat{extOff: 16} - ifam = &wireFormat{extOff: sizeofIfaMsghdrFreeBSD10, bodyOff: sizeofIfaMsghdrFreeBSD10} - ifmam = &wireFormat{extOff: sizeofIfmaMsghdrFreeBSD10, bodyOff: sizeofIfmaMsghdrFreeBSD10} - ifanm = &wireFormat{extOff: sizeofIfAnnouncemsghdrFreeBSD10, bodyOff: sizeofIfAnnouncemsghdrFreeBSD10} } - rel, _ := syscall.SysctlUint32("kern.osreldate") + rel, _ := unix.SysctlUint32("kern.osreldate") switch { case rel < 800000: if compatFreeBSD32 { @@ -141,20 +138,20 @@ func probeRoutingStack() (int, map[int]*wireFormat) { ifmam.parse = ifmam.parseInterfaceMulticastAddrMessage ifanm.parse = ifanm.parseInterfaceAnnounceMessage return align, map[int]*wireFormat{ - syscall.RTM_ADD: rtm, - syscall.RTM_DELETE: rtm, - syscall.RTM_CHANGE: rtm, - syscall.RTM_GET: rtm, - syscall.RTM_LOSING: rtm, - syscall.RTM_REDIRECT: rtm, - syscall.RTM_MISS: rtm, - syscall.RTM_LOCK: rtm, - syscall.RTM_RESOLVE: rtm, - syscall.RTM_NEWADDR: ifam, - syscall.RTM_DELADDR: ifam, - syscall.RTM_IFINFO: ifm, - syscall.RTM_NEWMADDR: ifmam, - syscall.RTM_DELMADDR: ifmam, - syscall.RTM_IFANNOUNCE: ifanm, + unix.RTM_ADD: rtm, + unix.RTM_DELETE: rtm, + unix.RTM_CHANGE: rtm, + unix.RTM_GET: rtm, + unix.RTM_LOSING: rtm, + unix.RTM_REDIRECT: rtm, + unix.RTM_MISS: rtm, + unix.RTM_LOCK: rtm, + unix.RTM_RESOLVE: rtm, + unix.RTM_NEWADDR: ifam, + unix.RTM_DELADDR: ifam, + unix.RTM_IFINFO: ifm, + unix.RTM_NEWMADDR: ifmam, + unix.RTM_DELMADDR: ifmam, + unix.RTM_IFANNOUNCE: ifanm, } } diff --git a/route/sys_netbsd.go b/route/sys_netbsd.go index be4460e13f..441458180a 100644 --- a/route/sys_netbsd.go +++ b/route/sys_netbsd.go @@ -4,7 +4,7 @@ package route -import "syscall" +import "golang.org/x/sys/unix" func (typ RIBType) parseable() bool { return true } @@ -45,29 +45,29 @@ func (m *InterfaceMessage) Sys() []Sys { } func probeRoutingStack() (int, map[int]*wireFormat) { - rtm := &wireFormat{extOff: 40, bodyOff: sizeofRtMsghdrNetBSD7} + rtm := &wireFormat{extOff: 40, bodyOff: unix.SizeofRtMsghdr} rtm.parse = rtm.parseRouteMessage - ifm := &wireFormat{extOff: 16, bodyOff: sizeofIfMsghdrNetBSD7} + ifm := &wireFormat{extOff: 16, bodyOff: unix.SizeofIfMsghdr} ifm.parse = ifm.parseInterfaceMessage - ifam := &wireFormat{extOff: sizeofIfaMsghdrNetBSD7, bodyOff: sizeofIfaMsghdrNetBSD7} + ifam := &wireFormat{extOff: unix.SizeofIfaMsghdr, bodyOff: unix.SizeofIfaMsghdr} ifam.parse = ifam.parseInterfaceAddrMessage - ifanm := &wireFormat{extOff: sizeofIfAnnouncemsghdrNetBSD7, bodyOff: sizeofIfAnnouncemsghdrNetBSD7} + ifanm := &wireFormat{extOff: unix.SizeofIfAnnounceMsghdr, bodyOff: unix.SizeofIfAnnounceMsghdr} ifanm.parse = ifanm.parseInterfaceAnnounceMessage // NetBSD 6 and above kernels require 64-bit aligned access to // routing facilities. return 8, map[int]*wireFormat{ - syscall.RTM_ADD: rtm, - syscall.RTM_DELETE: rtm, - syscall.RTM_CHANGE: rtm, - syscall.RTM_GET: rtm, - syscall.RTM_LOSING: rtm, - syscall.RTM_REDIRECT: rtm, - syscall.RTM_MISS: rtm, - syscall.RTM_LOCK: rtm, - syscall.RTM_RESOLVE: rtm, - syscall.RTM_NEWADDR: ifam, - syscall.RTM_DELADDR: ifam, - syscall.RTM_IFANNOUNCE: ifanm, - syscall.RTM_IFINFO: ifm, + unix.RTM_ADD: rtm, + unix.RTM_DELETE: rtm, + unix.RTM_CHANGE: rtm, + unix.RTM_GET: rtm, + unix.RTM_LOSING: rtm, + unix.RTM_REDIRECT: rtm, + unix.RTM_MISS: rtm, + unix.RTM_LOCK: rtm, + unix.RTM_RESOLVE: rtm, + unix.RTM_NEWADDR: ifam, + unix.RTM_DELADDR: ifam, + unix.RTM_IFANNOUNCE: ifanm, + unix.RTM_IFINFO: ifm, } } diff --git a/route/sys_openbsd.go b/route/sys_openbsd.go index 7f4f93cbea..21f1d3d6e5 100644 --- a/route/sys_openbsd.go +++ b/route/sys_openbsd.go @@ -5,13 +5,14 @@ package route import ( - "syscall" "unsafe" + + "golang.org/x/sys/unix" ) func (typ RIBType) parseable() bool { switch typ { - case syscall.NET_RT_STATS, syscall.NET_RT_TABLE: + case unix.NET_RT_STATS, unix.NET_RT_TABLE: return false default: return true @@ -65,18 +66,18 @@ func probeRoutingStack() (int, map[int]*wireFormat) { ifanm := &wireFormat{extOff: -1, bodyOff: -1} ifanm.parse = ifanm.parseInterfaceAnnounceMessage return int(unsafe.Sizeof(p)), map[int]*wireFormat{ - syscall.RTM_ADD: rtm, - syscall.RTM_DELETE: rtm, - syscall.RTM_CHANGE: rtm, - syscall.RTM_GET: rtm, - syscall.RTM_LOSING: rtm, - syscall.RTM_REDIRECT: rtm, - syscall.RTM_MISS: rtm, - syscall.RTM_RESOLVE: rtm, - syscall.RTM_NEWADDR: ifam, - syscall.RTM_DELADDR: ifam, - syscall.RTM_IFINFO: ifm, - syscall.RTM_IFANNOUNCE: ifanm, - syscall.RTM_DESYNC: rtm, + unix.RTM_ADD: rtm, + unix.RTM_DELETE: rtm, + unix.RTM_CHANGE: rtm, + unix.RTM_GET: rtm, + unix.RTM_LOSING: rtm, + unix.RTM_REDIRECT: rtm, + unix.RTM_MISS: rtm, + unix.RTM_RESOLVE: rtm, + unix.RTM_NEWADDR: ifam, + unix.RTM_DELADDR: ifam, + unix.RTM_IFINFO: ifm, + unix.RTM_IFANNOUNCE: ifanm, + unix.RTM_DESYNC: rtm, } } diff --git a/route/zsys_darwin.go b/route/zsys_darwin.go index 56a0c66f44..521be9f19f 100644 --- a/route/zsys_darwin.go +++ b/route/zsys_darwin.go @@ -4,19 +4,8 @@ package route const ( - sizeofIfMsghdrDarwin15 = 0x70 - sizeofIfaMsghdrDarwin15 = 0x14 - sizeofIfmaMsghdrDarwin15 = 0x10 - sizeofIfMsghdr2Darwin15 = 0xa0 - sizeofIfmaMsghdr2Darwin15 = 0x14 - sizeofIfDataDarwin15 = 0x60 - sizeofIfData64Darwin15 = 0x80 + sizeofIfMsghdr2Darwin15 = 0xa0 + sizeofIfData64Darwin15 = 0x80 - sizeofRtMsghdrDarwin15 = 0x5c sizeofRtMsghdr2Darwin15 = 0x5c - sizeofRtMetricsDarwin15 = 0x38 - - sizeofSockaddrStorage = 0x80 - sizeofSockaddrInet = 0x10 - sizeofSockaddrInet6 = 0x1c ) diff --git a/route/zsys_dragonfly.go b/route/zsys_dragonfly.go deleted file mode 100644 index f7c7a60cd6..0000000000 --- a/route/zsys_dragonfly.go +++ /dev/null @@ -1,20 +0,0 @@ -// Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs defs_dragonfly.go - -package route - -const ( - sizeofIfMsghdrDragonFlyBSD4 = 0xb0 - sizeofIfaMsghdrDragonFlyBSD4 = 0x14 - sizeofIfmaMsghdrDragonFlyBSD4 = 0x10 - sizeofIfAnnouncemsghdrDragonFlyBSD4 = 0x18 - - sizeofIfaMsghdrDragonFlyBSD58 = 0x18 - - sizeofRtMsghdrDragonFlyBSD4 = 0x98 - sizeofRtMetricsDragonFlyBSD4 = 0x70 - - sizeofSockaddrStorage = 0x80 - sizeofSockaddrInet = 0x10 - sizeofSockaddrInet6 = 0x1c -) diff --git a/route/zsys_freebsd_386.go b/route/zsys_freebsd_386.go index 3f985c7ee9..37b5c7b3e3 100644 --- a/route/zsys_freebsd_386.go +++ b/route/zsys_freebsd_386.go @@ -4,12 +4,6 @@ package route const ( - sizeofIfMsghdrlFreeBSD10 = 0x68 - sizeofIfaMsghdrFreeBSD10 = 0x14 - sizeofIfaMsghdrlFreeBSD10 = 0x6c - sizeofIfmaMsghdrFreeBSD10 = 0x10 - sizeofIfAnnouncemsghdrFreeBSD10 = 0x18 - sizeofRtMsghdrFreeBSD10 = 0x5c sizeofRtMetricsFreeBSD10 = 0x38 @@ -28,12 +22,6 @@ const ( // MODIFIED BY HAND FOR 386 EMULATION ON AMD64 // 386 EMULATION USES THE UNDERLYING RAW DATA LAYOUT - sizeofIfMsghdrlFreeBSD10Emu = 0xb0 - sizeofIfaMsghdrFreeBSD10Emu = 0x14 - sizeofIfaMsghdrlFreeBSD10Emu = 0xb0 - sizeofIfmaMsghdrFreeBSD10Emu = 0x10 - sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18 - sizeofRtMsghdrFreeBSD10Emu = 0x98 sizeofRtMetricsFreeBSD10Emu = 0x70 diff --git a/route/zsys_freebsd_amd64.go b/route/zsys_freebsd_amd64.go index 9293393698..2f6cf35ff0 100644 --- a/route/zsys_freebsd_amd64.go +++ b/route/zsys_freebsd_amd64.go @@ -4,12 +4,6 @@ package route const ( - sizeofIfMsghdrlFreeBSD10 = 0xb0 - sizeofIfaMsghdrFreeBSD10 = 0x14 - sizeofIfaMsghdrlFreeBSD10 = 0xb0 - sizeofIfmaMsghdrFreeBSD10 = 0x10 - sizeofIfAnnouncemsghdrFreeBSD10 = 0x18 - sizeofRtMsghdrFreeBSD10 = 0x98 sizeofRtMetricsFreeBSD10 = 0x70 @@ -25,12 +19,6 @@ const ( sizeofIfDataFreeBSD10 = 0x98 sizeofIfDataFreeBSD11 = 0x98 - sizeofIfMsghdrlFreeBSD10Emu = 0xb0 - sizeofIfaMsghdrFreeBSD10Emu = 0x14 - sizeofIfaMsghdrlFreeBSD10Emu = 0xb0 - sizeofIfmaMsghdrFreeBSD10Emu = 0x10 - sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18 - sizeofRtMsghdrFreeBSD10Emu = 0x98 sizeofRtMetricsFreeBSD10Emu = 0x70 diff --git a/route/zsys_freebsd_arm.go b/route/zsys_freebsd_arm.go index a2bdb4ad3b..b6b90d55cf 100644 --- a/route/zsys_freebsd_arm.go +++ b/route/zsys_freebsd_arm.go @@ -4,12 +4,6 @@ package route const ( - sizeofIfMsghdrlFreeBSD10 = 0x68 - sizeofIfaMsghdrFreeBSD10 = 0x14 - sizeofIfaMsghdrlFreeBSD10 = 0x6c - sizeofIfmaMsghdrFreeBSD10 = 0x10 - sizeofIfAnnouncemsghdrFreeBSD10 = 0x18 - sizeofRtMsghdrFreeBSD10 = 0x5c sizeofRtMetricsFreeBSD10 = 0x38 @@ -25,12 +19,6 @@ const ( sizeofIfDataFreeBSD10 = 0x60 sizeofIfDataFreeBSD11 = 0x98 - sizeofIfMsghdrlFreeBSD10Emu = 0x68 - sizeofIfaMsghdrFreeBSD10Emu = 0x14 - sizeofIfaMsghdrlFreeBSD10Emu = 0x6c - sizeofIfmaMsghdrFreeBSD10Emu = 0x10 - sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18 - sizeofRtMsghdrFreeBSD10Emu = 0x5c sizeofRtMetricsFreeBSD10Emu = 0x38 diff --git a/route/zsys_freebsd_arm64.go b/route/zsys_freebsd_arm64.go index 9293393698..2f6cf35ff0 100644 --- a/route/zsys_freebsd_arm64.go +++ b/route/zsys_freebsd_arm64.go @@ -4,12 +4,6 @@ package route const ( - sizeofIfMsghdrlFreeBSD10 = 0xb0 - sizeofIfaMsghdrFreeBSD10 = 0x14 - sizeofIfaMsghdrlFreeBSD10 = 0xb0 - sizeofIfmaMsghdrFreeBSD10 = 0x10 - sizeofIfAnnouncemsghdrFreeBSD10 = 0x18 - sizeofRtMsghdrFreeBSD10 = 0x98 sizeofRtMetricsFreeBSD10 = 0x70 @@ -25,12 +19,6 @@ const ( sizeofIfDataFreeBSD10 = 0x98 sizeofIfDataFreeBSD11 = 0x98 - sizeofIfMsghdrlFreeBSD10Emu = 0xb0 - sizeofIfaMsghdrFreeBSD10Emu = 0x14 - sizeofIfaMsghdrlFreeBSD10Emu = 0xb0 - sizeofIfmaMsghdrFreeBSD10Emu = 0x10 - sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18 - sizeofRtMsghdrFreeBSD10Emu = 0x98 sizeofRtMetricsFreeBSD10Emu = 0x70 diff --git a/route/zsys_freebsd_riscv64.go b/route/zsys_freebsd_riscv64.go index 9293393698..2f6cf35ff0 100644 --- a/route/zsys_freebsd_riscv64.go +++ b/route/zsys_freebsd_riscv64.go @@ -4,12 +4,6 @@ package route const ( - sizeofIfMsghdrlFreeBSD10 = 0xb0 - sizeofIfaMsghdrFreeBSD10 = 0x14 - sizeofIfaMsghdrlFreeBSD10 = 0xb0 - sizeofIfmaMsghdrFreeBSD10 = 0x10 - sizeofIfAnnouncemsghdrFreeBSD10 = 0x18 - sizeofRtMsghdrFreeBSD10 = 0x98 sizeofRtMetricsFreeBSD10 = 0x70 @@ -25,12 +19,6 @@ const ( sizeofIfDataFreeBSD10 = 0x98 sizeofIfDataFreeBSD11 = 0x98 - sizeofIfMsghdrlFreeBSD10Emu = 0xb0 - sizeofIfaMsghdrFreeBSD10Emu = 0x14 - sizeofIfaMsghdrlFreeBSD10Emu = 0xb0 - sizeofIfmaMsghdrFreeBSD10Emu = 0x10 - sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18 - sizeofRtMsghdrFreeBSD10Emu = 0x98 sizeofRtMetricsFreeBSD10Emu = 0x70 diff --git a/route/zsys_netbsd.go b/route/zsys_netbsd.go deleted file mode 100644 index eaffe8c408..0000000000 --- a/route/zsys_netbsd.go +++ /dev/null @@ -1,17 +0,0 @@ -// Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs defs_netbsd.go - -package route - -const ( - sizeofIfMsghdrNetBSD7 = 0x98 - sizeofIfaMsghdrNetBSD7 = 0x18 - sizeofIfAnnouncemsghdrNetBSD7 = 0x18 - - sizeofRtMsghdrNetBSD7 = 0x78 - sizeofRtMetricsNetBSD7 = 0x50 - - sizeofSockaddrStorage = 0x80 - sizeofSockaddrInet = 0x10 - sizeofSockaddrInet6 = 0x1c -) diff --git a/route/zsys_openbsd.go b/route/zsys_openbsd.go deleted file mode 100644 index b11b812680..0000000000 --- a/route/zsys_openbsd.go +++ /dev/null @@ -1,12 +0,0 @@ -// Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs defs_openbsd.go - -package route - -const ( - sizeofRtMsghdr = 0x60 - - sizeofSockaddrStorage = 0x100 - sizeofSockaddrInet = 0x10 - sizeofSockaddrInet6 = 0x1c -) From 6e414109c26d44bf2c146302818fc3bcc49b97b2 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 2 Dec 2024 13:01:47 -0800 Subject: [PATCH 5/7] http2: fix benchmarks using common frame read/write functions CL 586249 unified frame read/write functions used by client and server tests, but inadvertently broke some benchmarks. Fix those benchmarks. This mostly restores the previous behavior of the affected benchmarks (for example, testing only to see that a DATA frame contains an END_STREAM marker, ignoring the number of bytes in the frame). Fixes golang/go#70647 Change-Id: I2b0099c3513ac8754d11c4e37b7d63277a0fb0b1 Reviewed-on: https://go-review.googlesource.com/c/net/+/633055 Auto-Submit: Damien Neil Reviewed-by: Jonathan Amsterdam LUCI-TryBot-Result: Go LUCI Reviewed-by: Antonio Ojea --- http2/server_test.go | 50 +++++++++++++------------------------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/http2/server_test.go b/http2/server_test.go index 77de1be209..201cf0d00e 100644 --- a/http2/server_test.go +++ b/http2/server_test.go @@ -333,7 +333,9 @@ func newServerTesterWithRealConn(t testing.TB, handler http.HandlerFunc, opts .. // sync waits for all goroutines to idle. func (st *serverTester) sync() { - st.group.Wait() + if st.group != nil { + st.group.Wait() + } } // advance advances synthetic time by a duration. @@ -2896,15 +2898,10 @@ func BenchmarkServerGets(b *testing.B) { EndStream: true, EndHeaders: true, }) - st.wantHeaders(wantHeader{ - streamID: 1, - endStream: true, - }) - st.wantData(wantData{ - streamID: 1, - endStream: true, - size: 0, - }) + st.wantFrameType(FrameHeaders) + if df := readFrame[*DataFrame](b, st); !df.StreamEnded() { + b.Fatalf("DATA didn't have END_STREAM; got %v", df) + } } } @@ -2939,15 +2936,10 @@ func BenchmarkServerPosts(b *testing.B) { EndHeaders: true, }) st.writeData(id, true, nil) - st.wantHeaders(wantHeader{ - streamID: 1, - endStream: false, - }) - st.wantData(wantData{ - streamID: 1, - endStream: true, - size: 0, - }) + st.wantFrameType(FrameHeaders) + if df := readFrame[*DataFrame](b, st); !df.StreamEnded() { + b.Fatalf("DATA didn't have END_STREAM; got %v", df) + } } } @@ -3289,14 +3281,8 @@ func BenchmarkServer_GetRequest(b *testing.B) { EndStream: true, EndHeaders: true, }) - st.wantHeaders(wantHeader{ - streamID: streamID, - endStream: false, - }) - st.wantData(wantData{ - streamID: streamID, - endStream: true, - }) + st.wantFrameType(FrameHeaders) + st.wantFrameType(FrameData) } } @@ -3327,14 +3313,8 @@ func BenchmarkServer_PostRequest(b *testing.B) { EndHeaders: true, }) st.writeData(streamID, true, nil) - st.wantHeaders(wantHeader{ - streamID: streamID, - endStream: false, - }) - st.wantData(wantData{ - streamID: streamID, - endStream: true, - }) + st.wantFrameType(FrameHeaders) + st.wantFrameType(FrameData) } } From d0a1049b7e05d3d6f62570a8381a22301a97ae73 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 3 Dec 2024 13:23:01 +0100 Subject: [PATCH 6/7] route: remove unused sizeof* consts on freebsd The sizeofSockaddr* consts were replaced by the respective x/sys/unix consts by CL 632816. The sizeofIfDataFreeBSD* consts were never used since they were added. Cq-Include-Trybots: luci.golang.try:x_net-gotip-freebsd-amd64 Change-Id: Ieb0e01353199e08659d45cdc3293e817b679fed5 Reviewed-on: https://go-review.googlesource.com/c/net/+/633155 Reviewed-by: Ian Lance Taylor Auto-Submit: Tobias Klauser LUCI-TryBot-Result: Go LUCI Auto-Submit: Damien Neil Reviewed-by: Damien Neil --- route/defs_freebsd.go | 16 ---------------- route/zsys_freebsd_386.go | 16 ---------------- route/zsys_freebsd_amd64.go | 16 ---------------- route/zsys_freebsd_arm.go | 16 ---------------- route/zsys_freebsd_arm64.go | 16 ---------------- route/zsys_freebsd_riscv64.go | 16 ---------------- 6 files changed, 96 deletions(-) diff --git a/route/defs_freebsd.go b/route/defs_freebsd.go index a1318949a3..863e4ea245 100644 --- a/route/defs_freebsd.go +++ b/route/defs_freebsd.go @@ -227,12 +227,6 @@ const ( sizeofIfMsghdrFreeBSD10 = C.sizeof_struct_if_msghdr_freebsd10 sizeofIfMsghdrFreeBSD11 = C.sizeof_struct_if_msghdr_freebsd11 - sizeofIfDataFreeBSD7 = C.sizeof_struct_if_data_freebsd7 - sizeofIfDataFreeBSD8 = C.sizeof_struct_if_data_freebsd8 - sizeofIfDataFreeBSD9 = C.sizeof_struct_if_data_freebsd9 - sizeofIfDataFreeBSD10 = C.sizeof_struct_if_data_freebsd10 - sizeofIfDataFreeBSD11 = C.sizeof_struct_if_data_freebsd11 - sizeofRtMsghdrFreeBSD10Emu = C.sizeof_struct_rt_msghdr sizeofRtMetricsFreeBSD10Emu = C.sizeof_struct_rt_metrics @@ -241,14 +235,4 @@ const ( sizeofIfMsghdrFreeBSD9Emu = C.sizeof_struct_if_msghdr_freebsd9 sizeofIfMsghdrFreeBSD10Emu = C.sizeof_struct_if_msghdr_freebsd10 sizeofIfMsghdrFreeBSD11Emu = C.sizeof_struct_if_msghdr_freebsd11 - - sizeofIfDataFreeBSD7Emu = C.sizeof_struct_if_data_freebsd7 - sizeofIfDataFreeBSD8Emu = C.sizeof_struct_if_data_freebsd8 - sizeofIfDataFreeBSD9Emu = C.sizeof_struct_if_data_freebsd9 - sizeofIfDataFreeBSD10Emu = C.sizeof_struct_if_data_freebsd10 - sizeofIfDataFreeBSD11Emu = C.sizeof_struct_if_data_freebsd11 - - sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage - sizeofSockaddrInet = C.sizeof_struct_sockaddr_in - sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 ) diff --git a/route/zsys_freebsd_386.go b/route/zsys_freebsd_386.go index 37b5c7b3e3..a4a6d290e9 100644 --- a/route/zsys_freebsd_386.go +++ b/route/zsys_freebsd_386.go @@ -13,12 +13,6 @@ const ( sizeofIfMsghdrFreeBSD10 = 0x64 sizeofIfMsghdrFreeBSD11 = 0xa8 - sizeofIfDataFreeBSD7 = 0x50 - sizeofIfDataFreeBSD8 = 0x50 - sizeofIfDataFreeBSD9 = 0x50 - sizeofIfDataFreeBSD10 = 0x54 - sizeofIfDataFreeBSD11 = 0x98 - // MODIFIED BY HAND FOR 386 EMULATION ON AMD64 // 386 EMULATION USES THE UNDERLYING RAW DATA LAYOUT @@ -30,14 +24,4 @@ const ( sizeofIfMsghdrFreeBSD9Emu = 0xa8 sizeofIfMsghdrFreeBSD10Emu = 0xa8 sizeofIfMsghdrFreeBSD11Emu = 0xa8 - - sizeofIfDataFreeBSD7Emu = 0x98 - sizeofIfDataFreeBSD8Emu = 0x98 - sizeofIfDataFreeBSD9Emu = 0x98 - sizeofIfDataFreeBSD10Emu = 0x98 - sizeofIfDataFreeBSD11Emu = 0x98 - - sizeofSockaddrStorage = 0x80 - sizeofSockaddrInet = 0x10 - sizeofSockaddrInet6 = 0x1c ) diff --git a/route/zsys_freebsd_amd64.go b/route/zsys_freebsd_amd64.go index 2f6cf35ff0..d563b86ac4 100644 --- a/route/zsys_freebsd_amd64.go +++ b/route/zsys_freebsd_amd64.go @@ -13,12 +13,6 @@ const ( sizeofIfMsghdrFreeBSD10 = 0xa8 sizeofIfMsghdrFreeBSD11 = 0xa8 - sizeofIfDataFreeBSD7 = 0x98 - sizeofIfDataFreeBSD8 = 0x98 - sizeofIfDataFreeBSD9 = 0x98 - sizeofIfDataFreeBSD10 = 0x98 - sizeofIfDataFreeBSD11 = 0x98 - sizeofRtMsghdrFreeBSD10Emu = 0x98 sizeofRtMetricsFreeBSD10Emu = 0x70 @@ -27,14 +21,4 @@ const ( sizeofIfMsghdrFreeBSD9Emu = 0xa8 sizeofIfMsghdrFreeBSD10Emu = 0xa8 sizeofIfMsghdrFreeBSD11Emu = 0xa8 - - sizeofIfDataFreeBSD7Emu = 0x98 - sizeofIfDataFreeBSD8Emu = 0x98 - sizeofIfDataFreeBSD9Emu = 0x98 - sizeofIfDataFreeBSD10Emu = 0x98 - sizeofIfDataFreeBSD11Emu = 0x98 - - sizeofSockaddrStorage = 0x80 - sizeofSockaddrInet = 0x10 - sizeofSockaddrInet6 = 0x1c ) diff --git a/route/zsys_freebsd_arm.go b/route/zsys_freebsd_arm.go index b6b90d55cf..c7f9bbb214 100644 --- a/route/zsys_freebsd_arm.go +++ b/route/zsys_freebsd_arm.go @@ -13,12 +13,6 @@ const ( sizeofIfMsghdrFreeBSD10 = 0x70 sizeofIfMsghdrFreeBSD11 = 0xa8 - sizeofIfDataFreeBSD7 = 0x60 - sizeofIfDataFreeBSD8 = 0x60 - sizeofIfDataFreeBSD9 = 0x60 - sizeofIfDataFreeBSD10 = 0x60 - sizeofIfDataFreeBSD11 = 0x98 - sizeofRtMsghdrFreeBSD10Emu = 0x5c sizeofRtMetricsFreeBSD10Emu = 0x38 @@ -27,14 +21,4 @@ const ( sizeofIfMsghdrFreeBSD9Emu = 0x70 sizeofIfMsghdrFreeBSD10Emu = 0x70 sizeofIfMsghdrFreeBSD11Emu = 0xa8 - - sizeofIfDataFreeBSD7Emu = 0x60 - sizeofIfDataFreeBSD8Emu = 0x60 - sizeofIfDataFreeBSD9Emu = 0x60 - sizeofIfDataFreeBSD10Emu = 0x60 - sizeofIfDataFreeBSD11Emu = 0x98 - - sizeofSockaddrStorage = 0x80 - sizeofSockaddrInet = 0x10 - sizeofSockaddrInet6 = 0x1c ) diff --git a/route/zsys_freebsd_arm64.go b/route/zsys_freebsd_arm64.go index 2f6cf35ff0..d563b86ac4 100644 --- a/route/zsys_freebsd_arm64.go +++ b/route/zsys_freebsd_arm64.go @@ -13,12 +13,6 @@ const ( sizeofIfMsghdrFreeBSD10 = 0xa8 sizeofIfMsghdrFreeBSD11 = 0xa8 - sizeofIfDataFreeBSD7 = 0x98 - sizeofIfDataFreeBSD8 = 0x98 - sizeofIfDataFreeBSD9 = 0x98 - sizeofIfDataFreeBSD10 = 0x98 - sizeofIfDataFreeBSD11 = 0x98 - sizeofRtMsghdrFreeBSD10Emu = 0x98 sizeofRtMetricsFreeBSD10Emu = 0x70 @@ -27,14 +21,4 @@ const ( sizeofIfMsghdrFreeBSD9Emu = 0xa8 sizeofIfMsghdrFreeBSD10Emu = 0xa8 sizeofIfMsghdrFreeBSD11Emu = 0xa8 - - sizeofIfDataFreeBSD7Emu = 0x98 - sizeofIfDataFreeBSD8Emu = 0x98 - sizeofIfDataFreeBSD9Emu = 0x98 - sizeofIfDataFreeBSD10Emu = 0x98 - sizeofIfDataFreeBSD11Emu = 0x98 - - sizeofSockaddrStorage = 0x80 - sizeofSockaddrInet = 0x10 - sizeofSockaddrInet6 = 0x1c ) diff --git a/route/zsys_freebsd_riscv64.go b/route/zsys_freebsd_riscv64.go index 2f6cf35ff0..d563b86ac4 100644 --- a/route/zsys_freebsd_riscv64.go +++ b/route/zsys_freebsd_riscv64.go @@ -13,12 +13,6 @@ const ( sizeofIfMsghdrFreeBSD10 = 0xa8 sizeofIfMsghdrFreeBSD11 = 0xa8 - sizeofIfDataFreeBSD7 = 0x98 - sizeofIfDataFreeBSD8 = 0x98 - sizeofIfDataFreeBSD9 = 0x98 - sizeofIfDataFreeBSD10 = 0x98 - sizeofIfDataFreeBSD11 = 0x98 - sizeofRtMsghdrFreeBSD10Emu = 0x98 sizeofRtMetricsFreeBSD10Emu = 0x70 @@ -27,14 +21,4 @@ const ( sizeofIfMsghdrFreeBSD9Emu = 0xa8 sizeofIfMsghdrFreeBSD10Emu = 0xa8 sizeofIfMsghdrFreeBSD11Emu = 0xa8 - - sizeofIfDataFreeBSD7Emu = 0x98 - sizeofIfDataFreeBSD8Emu = 0x98 - sizeofIfDataFreeBSD9Emu = 0x98 - sizeofIfDataFreeBSD10Emu = 0x98 - sizeofIfDataFreeBSD11Emu = 0x98 - - sizeofSockaddrStorage = 0x80 - sizeofSockaddrInet = 0x10 - sizeofSockaddrInet6 = 0x1c ) From 285e1cf6650f407805ea8af9255624961b768479 Mon Sep 17 00:00:00 2001 From: Gopher Robot Date: Wed, 4 Dec 2024 20:26:06 +0000 Subject: [PATCH 7/7] go.mod: update golang.org/x dependencies Update golang.org/x dependencies to their latest tagged versions. Change-Id: I5db578f0e340dbf37012f580b307155806d55993 Reviewed-on: https://go-review.googlesource.com/c/net/+/633584 Reviewed-by: Dmitri Shuralyov Auto-Submit: Gopher Robot LUCI-TryBot-Result: Go LUCI Reviewed-by: David Chase --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 2721bac68d..59ca52bc48 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module golang.org/x/net go 1.18 require ( - golang.org/x/crypto v0.29.0 - golang.org/x/sys v0.27.0 - golang.org/x/term v0.26.0 - golang.org/x/text v0.20.0 + golang.org/x/crypto v0.30.0 + golang.org/x/sys v0.28.0 + golang.org/x/term v0.27.0 + golang.org/x/text v0.21.0 ) diff --git a/go.sum b/go.sum index 6868ecce4c..b723d4ccb1 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=