github.com/lightlus/netstack@v1.2.0/tcpip/transport/icmp/endpoint.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package icmp
    16  
    17  import (
    18  	"sync"
    19  
    20  	"github.com/lightlus/netstack/tcpip"
    21  	"github.com/lightlus/netstack/tcpip/buffer"
    22  	"github.com/lightlus/netstack/tcpip/header"
    23  	"github.com/lightlus/netstack/tcpip/iptables"
    24  	"github.com/lightlus/netstack/tcpip/stack"
    25  	"github.com/lightlus/netstack/waiter"
    26  )
    27  
    28  // +stateify savable
    29  type icmpPacket struct {
    30  	icmpPacketEntry
    31  	senderAddress tcpip.FullAddress
    32  	data          buffer.VectorisedView
    33  	timestamp     int64
    34  }
    35  
    36  type endpointState int
    37  
    38  const (
    39  	stateInitial endpointState = iota
    40  	stateBound
    41  	stateConnected
    42  	stateClosed
    43  )
    44  
    45  // endpoint represents an ICMP endpoint. This struct serves as the interface
    46  // between users of the endpoint and the protocol implementation; it is legal to
    47  // have concurrent goroutines make calls into the endpoint, they are properly
    48  // synchronized.
    49  //
    50  // +stateify savable
    51  type endpoint struct {
    52  	stack.TransportEndpointInfo
    53  
    54  	// The following fields are initialized at creation time and are
    55  	// immutable.
    56  	stack       *stack.Stack
    57  	waiterQueue *waiter.Queue
    58  	uniqueID    uint64
    59  
    60  	// The following fields are used to manage the receive queue, and are
    61  	// protected by rcvMu.
    62  	rcvMu         sync.Mutex
    63  	rcvReady      bool
    64  	rcvList       icmpPacketList
    65  	rcvBufSizeMax int
    66  	rcvBufSize    int
    67  	rcvClosed     bool
    68  
    69  	// The following fields are protected by the mu mutex.
    70  	mu         sync.RWMutex
    71  	sndBufSize int
    72  	// shutdownFlags represent the current shutdown state of the endpoint.
    73  	shutdownFlags tcpip.ShutdownFlags
    74  	state         endpointState
    75  	route         stack.Route
    76  	ttl           uint8
    77  	stats         tcpip.TransportEndpointStats
    78  }
    79  
    80  func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, transProto tcpip.TransportProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) {
    81  	return &endpoint{
    82  		stack: s,
    83  		TransportEndpointInfo: stack.TransportEndpointInfo{
    84  			NetProto:   netProto,
    85  			TransProto: transProto,
    86  		},
    87  		waiterQueue:   waiterQueue,
    88  		rcvBufSizeMax: 32 * 1024,
    89  		sndBufSize:    32 * 1024,
    90  		state:         stateInitial,
    91  		uniqueID:      s.UniqueID(),
    92  	}, nil
    93  }
    94  
    95  // UniqueID implements stack.TransportEndpoint.UniqueID.
    96  func (e *endpoint) UniqueID() uint64 {
    97  	return e.uniqueID
    98  }
    99  
   100  // Close puts the endpoint in a closed state and frees all resources
   101  // associated with it.
   102  func (e *endpoint) Close() {
   103  	e.mu.Lock()
   104  	e.shutdownFlags = tcpip.ShutdownRead | tcpip.ShutdownWrite
   105  	switch e.state {
   106  	case stateBound, stateConnected:
   107  		e.stack.UnregisterTransportEndpoint(e.RegisterNICID, []tcpip.NetworkProtocolNumber{e.NetProto}, e.TransProto, e.ID, e, 0 /* bindToDevice */)
   108  	}
   109  
   110  	// Close the receive list and drain it.
   111  	e.rcvMu.Lock()
   112  	e.rcvClosed = true
   113  	e.rcvBufSize = 0
   114  	for !e.rcvList.Empty() {
   115  		p := e.rcvList.Front()
   116  		e.rcvList.Remove(p)
   117  	}
   118  	e.rcvMu.Unlock()
   119  
   120  	e.route.Release()
   121  
   122  	// Update the state.
   123  	e.state = stateClosed
   124  
   125  	e.mu.Unlock()
   126  
   127  	e.waiterQueue.Notify(waiter.EventHUp | waiter.EventErr | waiter.EventIn | waiter.EventOut)
   128  }
   129  
   130  // ModerateRecvBuf implements tcpip.Endpoint.ModerateRecvBuf.
   131  func (e *endpoint) ModerateRecvBuf(copied int) {}
   132  
   133  // IPTables implements tcpip.Endpoint.IPTables.
   134  func (e *endpoint) IPTables() (iptables.IPTables, error) {
   135  	return e.stack.IPTables(), nil
   136  }
   137  
   138  // Read reads data from the endpoint. This method does not block if
   139  // there is no data pending.
   140  func (e *endpoint) Read(addr *tcpip.FullAddress) (buffer.View, tcpip.ControlMessages, *tcpip.Error) {
   141  	e.rcvMu.Lock()
   142  
   143  	if e.rcvList.Empty() {
   144  		err := tcpip.ErrWouldBlock
   145  		if e.rcvClosed {
   146  			e.stats.ReadErrors.ReadClosed.Increment()
   147  			err = tcpip.ErrClosedForReceive
   148  		}
   149  		e.rcvMu.Unlock()
   150  		return buffer.View{}, tcpip.ControlMessages{}, err
   151  	}
   152  
   153  	p := e.rcvList.Front()
   154  	e.rcvList.Remove(p)
   155  	e.rcvBufSize -= p.data.Size()
   156  
   157  	e.rcvMu.Unlock()
   158  
   159  	if addr != nil {
   160  		*addr = p.senderAddress
   161  	}
   162  
   163  	return p.data.ToView(), tcpip.ControlMessages{HasTimestamp: true, Timestamp: p.timestamp}, nil
   164  }
   165  
   166  // prepareForWrite prepares the endpoint for sending data. In particular, it
   167  // binds it if it's still in the initial state. To do so, it must first
   168  // reacquire the mutex in exclusive mode.
   169  //
   170  // Returns true for retry if preparation should be retried.
   171  func (e *endpoint) prepareForWrite(to *tcpip.FullAddress) (retry bool, err *tcpip.Error) {
   172  	switch e.state {
   173  	case stateInitial:
   174  	case stateConnected:
   175  		return false, nil
   176  
   177  	case stateBound:
   178  		if to == nil {
   179  			return false, tcpip.ErrDestinationRequired
   180  		}
   181  		return false, nil
   182  	default:
   183  		return false, tcpip.ErrInvalidEndpointState
   184  	}
   185  
   186  	e.mu.RUnlock()
   187  	defer e.mu.RLock()
   188  
   189  	e.mu.Lock()
   190  	defer e.mu.Unlock()
   191  
   192  	// The state changed when we released the shared locked and re-acquired
   193  	// it in exclusive mode. Try again.
   194  	if e.state != stateInitial {
   195  		return true, nil
   196  	}
   197  
   198  	// The state is still 'initial', so try to bind the endpoint.
   199  	if err := e.bindLocked(tcpip.FullAddress{}); err != nil {
   200  		return false, err
   201  	}
   202  
   203  	return true, nil
   204  }
   205  
   206  // Write writes data to the endpoint's peer. This method does not block
   207  // if the data cannot be written.
   208  func (e *endpoint) Write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, <-chan struct{}, *tcpip.Error) {
   209  	n, ch, err := e.write(p, opts)
   210  	switch err {
   211  	case nil:
   212  		e.stats.PacketsSent.Increment()
   213  	case tcpip.ErrMessageTooLong, tcpip.ErrInvalidOptionValue:
   214  		e.stats.WriteErrors.InvalidArgs.Increment()
   215  	case tcpip.ErrClosedForSend:
   216  		e.stats.WriteErrors.WriteClosed.Increment()
   217  	case tcpip.ErrInvalidEndpointState:
   218  		e.stats.WriteErrors.InvalidEndpointState.Increment()
   219  	case tcpip.ErrNoLinkAddress:
   220  		e.stats.SendErrors.NoLinkAddr.Increment()
   221  	case tcpip.ErrNoRoute, tcpip.ErrBroadcastDisabled, tcpip.ErrNetworkUnreachable:
   222  		// Errors indicating any problem with IP routing of the packet.
   223  		e.stats.SendErrors.NoRoute.Increment()
   224  	default:
   225  		// For all other errors when writing to the network layer.
   226  		e.stats.SendErrors.SendToNetworkFailed.Increment()
   227  	}
   228  	return n, ch, err
   229  }
   230  
   231  func (e *endpoint) write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, <-chan struct{}, *tcpip.Error) {
   232  	// MSG_MORE is unimplemented. (This also means that MSG_EOR is a no-op.)
   233  	if opts.More {
   234  		return 0, nil, tcpip.ErrInvalidOptionValue
   235  	}
   236  
   237  	to := opts.To
   238  
   239  	e.mu.RLock()
   240  	defer e.mu.RUnlock()
   241  
   242  	// If we've shutdown with SHUT_WR we are in an invalid state for sending.
   243  	if e.shutdownFlags&tcpip.ShutdownWrite != 0 {
   244  		return 0, nil, tcpip.ErrClosedForSend
   245  	}
   246  
   247  	// Prepare for write.
   248  	for {
   249  		retry, err := e.prepareForWrite(to)
   250  		if err != nil {
   251  			return 0, nil, err
   252  		}
   253  
   254  		if !retry {
   255  			break
   256  		}
   257  	}
   258  
   259  	var route *stack.Route
   260  	if to == nil {
   261  		route = &e.route
   262  
   263  		if route.IsResolutionRequired() {
   264  			// Promote lock to exclusive if using a shared route,
   265  			// given that it may need to change in Route.Resolve()
   266  			// call below.
   267  			e.mu.RUnlock()
   268  			defer e.mu.RLock()
   269  
   270  			e.mu.Lock()
   271  			defer e.mu.Unlock()
   272  
   273  			// Recheck state after lock was re-acquired.
   274  			if e.state != stateConnected {
   275  				return 0, nil, tcpip.ErrInvalidEndpointState
   276  			}
   277  		}
   278  	} else {
   279  		// Reject destination address if it goes through a different
   280  		// NIC than the endpoint was bound to.
   281  		nicID := to.NIC
   282  		if e.BindNICID != 0 {
   283  			if nicID != 0 && nicID != e.BindNICID {
   284  				return 0, nil, tcpip.ErrNoRoute
   285  			}
   286  
   287  			nicID = e.BindNICID
   288  		}
   289  
   290  		toCopy := *to
   291  		to = &toCopy
   292  		netProto, err := e.checkV4Mapped(to, true)
   293  		if err != nil {
   294  			return 0, nil, err
   295  		}
   296  
   297  		// Find the enpoint.
   298  		r, err := e.stack.FindRoute(nicID, e.BindAddr, to.Addr, netProto, false /* multicastLoop */)
   299  		if err != nil {
   300  			return 0, nil, err
   301  		}
   302  		defer r.Release()
   303  
   304  		route = &r
   305  	}
   306  
   307  	if route.IsResolutionRequired() {
   308  		if ch, err := route.Resolve(nil); err != nil {
   309  			if err == tcpip.ErrWouldBlock {
   310  				return 0, ch, tcpip.ErrNoLinkAddress
   311  			}
   312  			return 0, nil, err
   313  		}
   314  	}
   315  
   316  	v, err := p.FullPayload()
   317  	if err != nil {
   318  		return 0, nil, err
   319  	}
   320  
   321  	switch e.NetProto {
   322  	case header.IPv4ProtocolNumber:
   323  		err = send4(route, e.ID.LocalPort, v, e.ttl)
   324  
   325  	case header.IPv6ProtocolNumber:
   326  		err = send6(route, e.ID.LocalPort, v, e.ttl)
   327  	}
   328  
   329  	if err != nil {
   330  		return 0, nil, err
   331  	}
   332  
   333  	return int64(len(v)), nil, nil
   334  }
   335  
   336  // Peek only returns data from a single datagram, so do nothing here.
   337  func (e *endpoint) Peek([][]byte) (int64, tcpip.ControlMessages, *tcpip.Error) {
   338  	return 0, tcpip.ControlMessages{}, nil
   339  }
   340  
   341  // SetSockOpt sets a socket option.
   342  func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
   343  	switch o := opt.(type) {
   344  	case tcpip.TTLOption:
   345  		e.mu.Lock()
   346  		e.ttl = uint8(o)
   347  		e.mu.Unlock()
   348  	}
   349  
   350  	return nil
   351  }
   352  
   353  // SetSockOptInt sets a socket option. Currently not supported.
   354  func (e *endpoint) SetSockOptInt(opt tcpip.SockOpt, v int) *tcpip.Error {
   355  	return nil
   356  }
   357  
   358  // GetSockOptInt implements tcpip.Endpoint.GetSockOptInt.
   359  func (e *endpoint) GetSockOptInt(opt tcpip.SockOpt) (int, *tcpip.Error) {
   360  	switch opt {
   361  	case tcpip.ReceiveQueueSizeOption:
   362  		v := 0
   363  		e.rcvMu.Lock()
   364  		if !e.rcvList.Empty() {
   365  			p := e.rcvList.Front()
   366  			v = p.data.Size()
   367  		}
   368  		e.rcvMu.Unlock()
   369  		return v, nil
   370  	case tcpip.SendBufferSizeOption:
   371  		e.mu.Lock()
   372  		v := e.sndBufSize
   373  		e.mu.Unlock()
   374  		return v, nil
   375  
   376  	case tcpip.ReceiveBufferSizeOption:
   377  		e.rcvMu.Lock()
   378  		v := e.rcvBufSizeMax
   379  		e.rcvMu.Unlock()
   380  		return v, nil
   381  
   382  	}
   383  	return -1, tcpip.ErrUnknownProtocolOption
   384  }
   385  
   386  // GetSockOpt implements tcpip.Endpoint.GetSockOpt.
   387  func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error {
   388  	switch o := opt.(type) {
   389  	case tcpip.ErrorOption:
   390  		return nil
   391  
   392  	case *tcpip.KeepaliveEnabledOption:
   393  		*o = 0
   394  		return nil
   395  
   396  	case *tcpip.TTLOption:
   397  		e.rcvMu.Lock()
   398  		*o = tcpip.TTLOption(e.ttl)
   399  		e.rcvMu.Unlock()
   400  		return nil
   401  
   402  	default:
   403  		return tcpip.ErrUnknownProtocolOption
   404  	}
   405  }
   406  
   407  func send4(r *stack.Route, ident uint16, data buffer.View, ttl uint8) *tcpip.Error {
   408  	if len(data) < header.ICMPv4MinimumSize {
   409  		return tcpip.ErrInvalidEndpointState
   410  	}
   411  
   412  	hdr := buffer.NewPrependable(header.ICMPv4MinimumSize + int(r.MaxHeaderLength()))
   413  
   414  	icmpv4 := header.ICMPv4(hdr.Prepend(header.ICMPv4MinimumSize))
   415  	copy(icmpv4, data)
   416  	// Set the ident to the user-specified port. Sequence number should
   417  	// already be set by the user.
   418  	icmpv4.SetIdent(ident)
   419  	data = data[header.ICMPv4MinimumSize:]
   420  
   421  	// Linux performs these basic checks.
   422  	if icmpv4.Type() != header.ICMPv4Echo || icmpv4.Code() != 0 {
   423  		return tcpip.ErrInvalidEndpointState
   424  	}
   425  
   426  	icmpv4.SetChecksum(0)
   427  	icmpv4.SetChecksum(^header.Checksum(icmpv4, header.Checksum(data, 0)))
   428  
   429  	if ttl == 0 {
   430  		ttl = r.DefaultTTL()
   431  	}
   432  	return r.WritePacket(nil /* gso */, stack.NetworkHeaderParams{Protocol: header.ICMPv4ProtocolNumber, TTL: ttl, TOS: stack.DefaultTOS}, tcpip.PacketBuffer{
   433  		Header:          hdr,
   434  		Data:            data.ToVectorisedView(),
   435  		TransportHeader: buffer.View(icmpv4),
   436  	})
   437  }
   438  
   439  func send6(r *stack.Route, ident uint16, data buffer.View, ttl uint8) *tcpip.Error {
   440  	if len(data) < header.ICMPv6EchoMinimumSize {
   441  		return tcpip.ErrInvalidEndpointState
   442  	}
   443  
   444  	hdr := buffer.NewPrependable(header.ICMPv6MinimumSize + int(r.MaxHeaderLength()))
   445  
   446  	icmpv6 := header.ICMPv6(hdr.Prepend(header.ICMPv6MinimumSize))
   447  	copy(icmpv6, data)
   448  	// Set the ident. Sequence number is provided by the user.
   449  	icmpv6.SetIdent(ident)
   450  	data = data[header.ICMPv6MinimumSize:]
   451  
   452  	if icmpv6.Type() != header.ICMPv6EchoRequest || icmpv6.Code() != 0 {
   453  		return tcpip.ErrInvalidEndpointState
   454  	}
   455  
   456  	dataVV := data.ToVectorisedView()
   457  	icmpv6.SetChecksum(header.ICMPv6Checksum(icmpv6, r.LocalAddress, r.RemoteAddress, dataVV))
   458  
   459  	if ttl == 0 {
   460  		ttl = r.DefaultTTL()
   461  	}
   462  	return r.WritePacket(nil /* gso */, stack.NetworkHeaderParams{Protocol: header.ICMPv6ProtocolNumber, TTL: ttl, TOS: stack.DefaultTOS}, tcpip.PacketBuffer{
   463  		Header:          hdr,
   464  		Data:            dataVV,
   465  		TransportHeader: buffer.View(icmpv6),
   466  	})
   467  }
   468  
   469  func (e *endpoint) checkV4Mapped(addr *tcpip.FullAddress, allowMismatch bool) (tcpip.NetworkProtocolNumber, *tcpip.Error) {
   470  	netProto := e.NetProto
   471  	if header.IsV4MappedAddress(addr.Addr) {
   472  		return 0, tcpip.ErrNoRoute
   473  	}
   474  
   475  	// Fail if we're bound to an address length different from the one we're
   476  	// checking.
   477  	if l := len(e.ID.LocalAddress); !allowMismatch && l != 0 && l != len(addr.Addr) {
   478  		return 0, tcpip.ErrInvalidEndpointState
   479  	}
   480  
   481  	return netProto, nil
   482  }
   483  
   484  // Disconnect implements tcpip.Endpoint.Disconnect.
   485  func (*endpoint) Disconnect() *tcpip.Error {
   486  	return tcpip.ErrNotSupported
   487  }
   488  
   489  // Connect connects the endpoint to its peer. Specifying a NIC is optional.
   490  func (e *endpoint) Connect(addr tcpip.FullAddress) *tcpip.Error {
   491  	e.mu.Lock()
   492  	defer e.mu.Unlock()
   493  
   494  	nicID := addr.NIC
   495  	localPort := uint16(0)
   496  	switch e.state {
   497  	case stateBound, stateConnected:
   498  		localPort = e.ID.LocalPort
   499  		if e.BindNICID == 0 {
   500  			break
   501  		}
   502  
   503  		if nicID != 0 && nicID != e.BindNICID {
   504  			return tcpip.ErrInvalidEndpointState
   505  		}
   506  
   507  		nicID = e.BindNICID
   508  	default:
   509  		return tcpip.ErrInvalidEndpointState
   510  	}
   511  
   512  	netProto, err := e.checkV4Mapped(&addr, false)
   513  	if err != nil {
   514  		return err
   515  	}
   516  
   517  	// Find a route to the desired destination.
   518  	r, err := e.stack.FindRoute(nicID, e.BindAddr, addr.Addr, netProto, false /* multicastLoop */)
   519  	if err != nil {
   520  		return err
   521  	}
   522  	defer r.Release()
   523  
   524  	id := stack.TransportEndpointID{
   525  		LocalAddress:  r.LocalAddress,
   526  		LocalPort:     localPort,
   527  		RemoteAddress: r.RemoteAddress,
   528  	}
   529  
   530  	// Even if we're connected, this endpoint can still be used to send
   531  	// packets on a different network protocol, so we register both even if
   532  	// v6only is set to false and this is an ipv6 endpoint.
   533  	netProtos := []tcpip.NetworkProtocolNumber{netProto}
   534  
   535  	id, err = e.registerWithStack(nicID, netProtos, id)
   536  	if err != nil {
   537  		return err
   538  	}
   539  
   540  	e.ID = id
   541  	e.route = r.Clone()
   542  	e.RegisterNICID = nicID
   543  
   544  	e.state = stateConnected
   545  
   546  	e.rcvMu.Lock()
   547  	e.rcvReady = true
   548  	e.rcvMu.Unlock()
   549  
   550  	return nil
   551  }
   552  
   553  // ConnectEndpoint is not supported.
   554  func (*endpoint) ConnectEndpoint(tcpip.Endpoint) *tcpip.Error {
   555  	return tcpip.ErrInvalidEndpointState
   556  }
   557  
   558  // Shutdown closes the read and/or write end of the endpoint connection
   559  // to its peer.
   560  func (e *endpoint) Shutdown(flags tcpip.ShutdownFlags) *tcpip.Error {
   561  	e.mu.Lock()
   562  	defer e.mu.Unlock()
   563  	e.shutdownFlags |= flags
   564  
   565  	if e.state != stateConnected {
   566  		return tcpip.ErrNotConnected
   567  	}
   568  
   569  	if flags&tcpip.ShutdownRead != 0 {
   570  		e.rcvMu.Lock()
   571  		wasClosed := e.rcvClosed
   572  		e.rcvClosed = true
   573  		e.rcvMu.Unlock()
   574  
   575  		if !wasClosed {
   576  			e.waiterQueue.Notify(waiter.EventIn)
   577  		}
   578  	}
   579  
   580  	return nil
   581  }
   582  
   583  // Listen is not supported by UDP, it just fails.
   584  func (*endpoint) Listen(int) *tcpip.Error {
   585  	return tcpip.ErrNotSupported
   586  }
   587  
   588  // Accept is not supported by UDP, it just fails.
   589  func (*endpoint) Accept() (tcpip.Endpoint, *waiter.Queue, *tcpip.Error) {
   590  	return nil, nil, tcpip.ErrNotSupported
   591  }
   592  
   593  func (e *endpoint) registerWithStack(nicID tcpip.NICID, netProtos []tcpip.NetworkProtocolNumber, id stack.TransportEndpointID) (stack.TransportEndpointID, *tcpip.Error) {
   594  	if id.LocalPort != 0 {
   595  		// The endpoint already has a local port, just attempt to
   596  		// register it.
   597  		err := e.stack.RegisterTransportEndpoint(nicID, netProtos, e.TransProto, id, e, false /* reuse */, 0 /* bindToDevice */)
   598  		return id, err
   599  	}
   600  
   601  	// We need to find a port for the endpoint.
   602  	_, err := e.stack.PickEphemeralPort(func(p uint16) (bool, *tcpip.Error) {
   603  		id.LocalPort = p
   604  		err := e.stack.RegisterTransportEndpoint(nicID, netProtos, e.TransProto, id, e, false /* reuse */, 0 /* bindtodevice */)
   605  		switch err {
   606  		case nil:
   607  			return true, nil
   608  		case tcpip.ErrPortInUse:
   609  			return false, nil
   610  		default:
   611  			return false, err
   612  		}
   613  	})
   614  
   615  	return id, err
   616  }
   617  
   618  func (e *endpoint) bindLocked(addr tcpip.FullAddress) *tcpip.Error {
   619  	// Don't allow binding once endpoint is not in the initial state
   620  	// anymore.
   621  	if e.state != stateInitial {
   622  		return tcpip.ErrInvalidEndpointState
   623  	}
   624  
   625  	netProto, err := e.checkV4Mapped(&addr, false)
   626  	if err != nil {
   627  		return err
   628  	}
   629  
   630  	// Expand netProtos to include v4 and v6 if the caller is binding to a
   631  	// wildcard (empty) address, and this is an IPv6 endpoint with v6only
   632  	// set to false.
   633  	netProtos := []tcpip.NetworkProtocolNumber{netProto}
   634  
   635  	if len(addr.Addr) != 0 {
   636  		// A local address was specified, verify that it's valid.
   637  		if e.stack.CheckLocalAddress(addr.NIC, netProto, addr.Addr) == 0 {
   638  			return tcpip.ErrBadLocalAddress
   639  		}
   640  	}
   641  
   642  	id := stack.TransportEndpointID{
   643  		LocalPort:    addr.Port,
   644  		LocalAddress: addr.Addr,
   645  	}
   646  	id, err = e.registerWithStack(addr.NIC, netProtos, id)
   647  	if err != nil {
   648  		return err
   649  	}
   650  
   651  	e.ID = id
   652  	e.RegisterNICID = addr.NIC
   653  
   654  	// Mark endpoint as bound.
   655  	e.state = stateBound
   656  
   657  	e.rcvMu.Lock()
   658  	e.rcvReady = true
   659  	e.rcvMu.Unlock()
   660  
   661  	return nil
   662  }
   663  
   664  // Bind binds the endpoint to a specific local address and port.
   665  // Specifying a NIC is optional.
   666  func (e *endpoint) Bind(addr tcpip.FullAddress) *tcpip.Error {
   667  	e.mu.Lock()
   668  	defer e.mu.Unlock()
   669  
   670  	err := e.bindLocked(addr)
   671  	if err != nil {
   672  		return err
   673  	}
   674  
   675  	e.BindNICID = addr.NIC
   676  	e.BindAddr = addr.Addr
   677  
   678  	return nil
   679  }
   680  
   681  // GetLocalAddress returns the address to which the endpoint is bound.
   682  func (e *endpoint) GetLocalAddress() (tcpip.FullAddress, *tcpip.Error) {
   683  	e.mu.RLock()
   684  	defer e.mu.RUnlock()
   685  
   686  	return tcpip.FullAddress{
   687  		NIC:  e.RegisterNICID,
   688  		Addr: e.ID.LocalAddress,
   689  		Port: e.ID.LocalPort,
   690  	}, nil
   691  }
   692  
   693  // GetRemoteAddress returns the address to which the endpoint is connected.
   694  func (e *endpoint) GetRemoteAddress() (tcpip.FullAddress, *tcpip.Error) {
   695  	e.mu.RLock()
   696  	defer e.mu.RUnlock()
   697  
   698  	if e.state != stateConnected {
   699  		return tcpip.FullAddress{}, tcpip.ErrNotConnected
   700  	}
   701  
   702  	return tcpip.FullAddress{
   703  		NIC:  e.RegisterNICID,
   704  		Addr: e.ID.RemoteAddress,
   705  		Port: e.ID.RemotePort,
   706  	}, nil
   707  }
   708  
   709  // Readiness returns the current readiness of the endpoint. For example, if
   710  // waiter.EventIn is set, the endpoint is immediately readable.
   711  func (e *endpoint) Readiness(mask waiter.EventMask) waiter.EventMask {
   712  	// The endpoint is always writable.
   713  	result := waiter.EventOut & mask
   714  
   715  	// Determine if the endpoint is readable if requested.
   716  	if (mask & waiter.EventIn) != 0 {
   717  		e.rcvMu.Lock()
   718  		if !e.rcvList.Empty() || e.rcvClosed {
   719  			result |= waiter.EventIn
   720  		}
   721  		e.rcvMu.Unlock()
   722  	}
   723  
   724  	return result
   725  }
   726  
   727  // HandlePacket is called by the stack when new packets arrive to this transport
   728  // endpoint.
   729  func (e *endpoint) HandlePacket(r *stack.Route, id stack.TransportEndpointID, pkt tcpip.PacketBuffer) {
   730  	// Only accept echo replies.
   731  	switch e.NetProto {
   732  	case header.IPv4ProtocolNumber:
   733  		h := header.ICMPv4(pkt.Data.First())
   734  		if h.Type() != header.ICMPv4EchoReply {
   735  			e.stack.Stats().DroppedPackets.Increment()
   736  			e.stats.ReceiveErrors.MalformedPacketsReceived.Increment()
   737  			return
   738  		}
   739  	case header.IPv6ProtocolNumber:
   740  		h := header.ICMPv6(pkt.Data.First())
   741  		if h.Type() != header.ICMPv6EchoReply {
   742  			e.stack.Stats().DroppedPackets.Increment()
   743  			e.stats.ReceiveErrors.MalformedPacketsReceived.Increment()
   744  			return
   745  		}
   746  	}
   747  
   748  	e.rcvMu.Lock()
   749  
   750  	// Drop the packet if our buffer is currently full.
   751  	if !e.rcvReady || e.rcvClosed {
   752  		e.rcvMu.Unlock()
   753  		e.stack.Stats().DroppedPackets.Increment()
   754  		e.stats.ReceiveErrors.ClosedReceiver.Increment()
   755  		return
   756  	}
   757  
   758  	if e.rcvBufSize >= e.rcvBufSizeMax {
   759  		e.rcvMu.Unlock()
   760  		e.stack.Stats().DroppedPackets.Increment()
   761  		e.stats.ReceiveErrors.ReceiveBufferOverflow.Increment()
   762  		return
   763  	}
   764  
   765  	wasEmpty := e.rcvBufSize == 0
   766  
   767  	// Push new packet into receive list and increment the buffer size.
   768  	packet := &icmpPacket{
   769  		senderAddress: tcpip.FullAddress{
   770  			NIC:  r.NICID(),
   771  			Addr: id.RemoteAddress,
   772  		},
   773  	}
   774  
   775  	packet.data = pkt.Data
   776  
   777  	e.rcvList.PushBack(packet)
   778  	e.rcvBufSize += packet.data.Size()
   779  
   780  	packet.timestamp = e.stack.NowNanoseconds()
   781  
   782  	e.rcvMu.Unlock()
   783  	e.stats.PacketsReceived.Increment()
   784  	// Notify any waiters that there's data to be read now.
   785  	if wasEmpty {
   786  		e.waiterQueue.Notify(waiter.EventIn)
   787  	}
   788  }
   789  
   790  // HandleControlPacket implements stack.TransportEndpoint.HandleControlPacket.
   791  func (e *endpoint) HandleControlPacket(id stack.TransportEndpointID, typ stack.ControlType, extra uint32, pkt tcpip.PacketBuffer) {
   792  }
   793  
   794  // State implements tcpip.Endpoint.State. The ICMP endpoint currently doesn't
   795  // expose internal socket state.
   796  func (e *endpoint) State() uint32 {
   797  	return 0
   798  }
   799  
   800  // Info returns a copy of the endpoint info.
   801  func (e *endpoint) Info() tcpip.EndpointInfo {
   802  	e.mu.RLock()
   803  	// Make a copy of the endpoint info.
   804  	ret := e.TransportEndpointInfo
   805  	e.mu.RUnlock()
   806  	return &ret
   807  }
   808  
   809  // Stats returns a pointer to the endpoint stats.
   810  func (e *endpoint) Stats() tcpip.EndpointStats {
   811  	return &e.stats
   812  }
   813  
   814  // Wait implements stack.TransportEndpoint.Wait.
   815  func (*endpoint) Wait() {}