inet.af/netstack@v0.0.0-20220214151720-7585b01ddccf/tcpip/network/arp/arp.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 arp implements the ARP network protocol. It is used to resolve
    16  // IPv4 addresses into link-local MAC addresses, and advertises IPv4
    17  // addresses of its stack with the local network.
    18  package arp
    19  
    20  import (
    21  	"fmt"
    22  	"reflect"
    23  	"sync/atomic"
    24  
    25  	"inet.af/netstack/sync"
    26  	"inet.af/netstack/tcpip"
    27  	"inet.af/netstack/tcpip/buffer"
    28  	"inet.af/netstack/tcpip/header"
    29  	"inet.af/netstack/tcpip/header/parse"
    30  	"inet.af/netstack/tcpip/network/internal/ip"
    31  	"inet.af/netstack/tcpip/stack"
    32  )
    33  
    34  const (
    35  	// ProtocolNumber is the ARP protocol number.
    36  	ProtocolNumber = header.ARPProtocolNumber
    37  )
    38  
    39  var _ stack.DuplicateAddressDetector = (*endpoint)(nil)
    40  var _ stack.LinkAddressResolver = (*endpoint)(nil)
    41  var _ ip.DADProtocol = (*endpoint)(nil)
    42  
    43  // ARP endpoints need to implement stack.NetworkEndpoint because the stack
    44  // considers the layer above the link-layer a network layer; the only
    45  // facility provided by the stack to deliver packets to a layer above
    46  // the link-layer is via stack.NetworkEndpoint.HandlePacket.
    47  var _ stack.NetworkEndpoint = (*endpoint)(nil)
    48  
    49  type endpoint struct {
    50  	protocol *protocol
    51  
    52  	// enabled is set to 1 when the NIC is enabled and 0 when it is disabled.
    53  	//
    54  	// Must be accessed using atomic operations.
    55  	enabled uint32
    56  
    57  	nic   stack.NetworkInterface
    58  	stats sharedStats
    59  
    60  	mu struct {
    61  		sync.Mutex
    62  
    63  		dad ip.DAD
    64  	}
    65  }
    66  
    67  // CheckDuplicateAddress implements stack.DuplicateAddressDetector.
    68  func (e *endpoint) CheckDuplicateAddress(addr tcpip.Address, h stack.DADCompletionHandler) stack.DADCheckAddressDisposition {
    69  	e.mu.Lock()
    70  	defer e.mu.Unlock()
    71  	return e.mu.dad.CheckDuplicateAddressLocked(addr, h)
    72  }
    73  
    74  // SetDADConfigurations implements stack.DuplicateAddressDetector.
    75  func (e *endpoint) SetDADConfigurations(c stack.DADConfigurations) {
    76  	e.mu.Lock()
    77  	defer e.mu.Unlock()
    78  	e.mu.dad.SetConfigsLocked(c)
    79  }
    80  
    81  // DuplicateAddressProtocol implements stack.DuplicateAddressDetector.
    82  func (*endpoint) DuplicateAddressProtocol() tcpip.NetworkProtocolNumber {
    83  	return header.IPv4ProtocolNumber
    84  }
    85  
    86  // SendDADMessage implements ip.DADProtocol.
    87  func (e *endpoint) SendDADMessage(addr tcpip.Address, _ []byte) tcpip.Error {
    88  	return e.sendARPRequest(header.IPv4Any, addr, header.EthernetBroadcastAddress)
    89  }
    90  
    91  func (e *endpoint) Enable() tcpip.Error {
    92  	if !e.nic.Enabled() {
    93  		return &tcpip.ErrNotPermitted{}
    94  	}
    95  
    96  	e.setEnabled(true)
    97  	return nil
    98  }
    99  
   100  func (e *endpoint) Enabled() bool {
   101  	return e.nic.Enabled() && e.isEnabled()
   102  }
   103  
   104  // isEnabled returns true if the endpoint is enabled, regardless of the
   105  // enabled status of the NIC.
   106  func (e *endpoint) isEnabled() bool {
   107  	return atomic.LoadUint32(&e.enabled) == 1
   108  }
   109  
   110  // setEnabled sets the enabled status for the endpoint.
   111  func (e *endpoint) setEnabled(v bool) {
   112  	if v {
   113  		atomic.StoreUint32(&e.enabled, 1)
   114  	} else {
   115  		atomic.StoreUint32(&e.enabled, 0)
   116  	}
   117  }
   118  
   119  func (e *endpoint) Disable() {
   120  	e.setEnabled(false)
   121  }
   122  
   123  // DefaultTTL is unused for ARP. It implements stack.NetworkEndpoint.
   124  func (*endpoint) DefaultTTL() uint8 {
   125  	return 0
   126  }
   127  
   128  func (e *endpoint) MTU() uint32 {
   129  	lmtu := e.nic.MTU()
   130  	return lmtu - uint32(e.MaxHeaderLength())
   131  }
   132  
   133  func (e *endpoint) MaxHeaderLength() uint16 {
   134  	return e.nic.MaxHeaderLength() + header.ARPSize
   135  }
   136  
   137  func (*endpoint) Close() {}
   138  
   139  func (*endpoint) WritePacket(*stack.Route, stack.NetworkHeaderParams, *stack.PacketBuffer) tcpip.Error {
   140  	return &tcpip.ErrNotSupported{}
   141  }
   142  
   143  // NetworkProtocolNumber implements stack.NetworkEndpoint.NetworkProtocolNumber.
   144  func (*endpoint) NetworkProtocolNumber() tcpip.NetworkProtocolNumber {
   145  	return ProtocolNumber
   146  }
   147  
   148  // WritePackets implements stack.NetworkEndpoint.WritePackets.
   149  func (*endpoint) WritePackets(*stack.Route, stack.PacketBufferList, stack.NetworkHeaderParams) (int, tcpip.Error) {
   150  	return 0, &tcpip.ErrNotSupported{}
   151  }
   152  
   153  func (*endpoint) WriteHeaderIncludedPacket(*stack.Route, *stack.PacketBuffer) tcpip.Error {
   154  	return &tcpip.ErrNotSupported{}
   155  }
   156  
   157  func (e *endpoint) HandlePacket(pkt *stack.PacketBuffer) {
   158  	stats := e.stats.arp
   159  	stats.packetsReceived.Increment()
   160  
   161  	if !e.isEnabled() {
   162  		stats.disabledPacketsReceived.Increment()
   163  		return
   164  	}
   165  
   166  	if _, _, ok := e.protocol.Parse(pkt); !ok {
   167  		stats.malformedPacketsReceived.Increment()
   168  		return
   169  	}
   170  
   171  	h := header.ARP(pkt.NetworkHeader().View())
   172  	if !h.IsValid() {
   173  		stats.malformedPacketsReceived.Increment()
   174  		return
   175  	}
   176  
   177  	switch h.Op() {
   178  	case header.ARPRequest:
   179  		stats.requestsReceived.Increment()
   180  		localAddr := tcpip.Address(h.ProtocolAddressTarget())
   181  
   182  		if !e.nic.CheckLocalAddress(header.IPv4ProtocolNumber, localAddr) {
   183  			stats.requestsReceivedUnknownTargetAddress.Increment()
   184  			return // we have no useful answer, ignore the request
   185  		}
   186  
   187  		remoteAddr := tcpip.Address(h.ProtocolAddressSender())
   188  		remoteLinkAddr := tcpip.LinkAddress(h.HardwareAddressSender())
   189  
   190  		switch err := e.nic.HandleNeighborProbe(header.IPv4ProtocolNumber, remoteAddr, remoteLinkAddr); err.(type) {
   191  		case nil:
   192  		case *tcpip.ErrNotSupported:
   193  			// The stack may support ARP but the NIC may not need link resolution.
   194  		default:
   195  			panic(fmt.Sprintf("unexpected error when informing NIC of neighbor probe message: %s", err))
   196  		}
   197  
   198  		respPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   199  			ReserveHeaderBytes: int(e.nic.MaxHeaderLength()) + header.ARPSize,
   200  		})
   201  		defer respPkt.DecRef()
   202  		packet := header.ARP(respPkt.NetworkHeader().Push(header.ARPSize))
   203  		respPkt.NetworkProtocolNumber = ProtocolNumber
   204  		packet.SetIPv4OverEthernet()
   205  		packet.SetOp(header.ARPReply)
   206  		// TODO(gvisor.dev/issue/4582): check copied length once TAP devices have a
   207  		// link address.
   208  		_ = copy(packet.HardwareAddressSender(), e.nic.LinkAddress())
   209  		if n := copy(packet.ProtocolAddressSender(), h.ProtocolAddressTarget()); n != header.IPv4AddressSize {
   210  			panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, header.IPv4AddressSize))
   211  		}
   212  		origSender := h.HardwareAddressSender()
   213  		if n := copy(packet.HardwareAddressTarget(), origSender); n != header.EthernetAddressSize {
   214  			panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, header.EthernetAddressSize))
   215  		}
   216  		if n := copy(packet.ProtocolAddressTarget(), h.ProtocolAddressSender()); n != header.IPv4AddressSize {
   217  			panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, header.IPv4AddressSize))
   218  		}
   219  
   220  		// As per RFC 826, under Packet Reception:
   221  		//   Swap hardware and protocol fields, putting the local hardware and
   222  		//   protocol addresses in the sender fields.
   223  		//
   224  		//   Send the packet to the (new) target hardware address on the same
   225  		//   hardware on which the request was received.
   226  		if err := e.nic.WritePacketToRemote(tcpip.LinkAddress(origSender), ProtocolNumber, respPkt); err != nil {
   227  			stats.outgoingRepliesDropped.Increment()
   228  		} else {
   229  			stats.outgoingRepliesSent.Increment()
   230  		}
   231  
   232  	case header.ARPReply:
   233  		stats.repliesReceived.Increment()
   234  		addr := tcpip.Address(h.ProtocolAddressSender())
   235  		linkAddr := tcpip.LinkAddress(h.HardwareAddressSender())
   236  
   237  		e.mu.Lock()
   238  		e.mu.dad.StopLocked(addr, &stack.DADDupAddrDetected{HolderLinkAddress: linkAddr})
   239  		e.mu.Unlock()
   240  
   241  		// The solicited, override, and isRouter flags are not available for ARP;
   242  		// they are only available for IPv6 Neighbor Advertisements.
   243  		switch err := e.nic.HandleNeighborConfirmation(header.IPv4ProtocolNumber, addr, linkAddr, stack.ReachabilityConfirmationFlags{
   244  			// Solicited and unsolicited (also referred to as gratuitous) ARP Replies
   245  			// are handled equivalently to a solicited Neighbor Advertisement.
   246  			Solicited: true,
   247  			// If a different link address is received than the one cached, the entry
   248  			// should always go to Stale.
   249  			Override: false,
   250  			// ARP does not distinguish between router and non-router hosts.
   251  			IsRouter: false,
   252  		}); err.(type) {
   253  		case nil:
   254  		case *tcpip.ErrNotSupported:
   255  		// The stack may support ARP but the NIC may not need link resolution.
   256  		default:
   257  			panic(fmt.Sprintf("unexpected error when informing NIC of neighbor confirmation message: %s", err))
   258  		}
   259  	}
   260  }
   261  
   262  // Stats implements stack.NetworkEndpoint.
   263  func (e *endpoint) Stats() stack.NetworkEndpointStats {
   264  	return &e.stats.localStats
   265  }
   266  
   267  var _ stack.NetworkProtocol = (*protocol)(nil)
   268  
   269  type protocol struct {
   270  	stack   *stack.Stack
   271  	options Options
   272  }
   273  
   274  func (p *protocol) Number() tcpip.NetworkProtocolNumber { return ProtocolNumber }
   275  func (p *protocol) MinimumPacketSize() int              { return header.ARPSize }
   276  
   277  func (*protocol) ParseAddresses(buffer.View) (src, dst tcpip.Address) {
   278  	return "", ""
   279  }
   280  
   281  func (p *protocol) NewEndpoint(nic stack.NetworkInterface, _ stack.TransportDispatcher) stack.NetworkEndpoint {
   282  	e := &endpoint{
   283  		protocol: p,
   284  		nic:      nic,
   285  	}
   286  
   287  	e.mu.Lock()
   288  	e.mu.dad.Init(&e.mu, p.options.DADConfigs, ip.DADOptions{
   289  		Clock:     p.stack.Clock(),
   290  		SecureRNG: p.stack.SecureRNG(),
   291  		// ARP does not support sending nonce values.
   292  		NonceSize: 0,
   293  		Protocol:  e,
   294  		NICID:     nic.ID(),
   295  	})
   296  	e.mu.Unlock()
   297  
   298  	tcpip.InitStatCounters(reflect.ValueOf(&e.stats.localStats).Elem())
   299  
   300  	stackStats := p.stack.Stats()
   301  	e.stats.arp.init(&e.stats.localStats.ARP, &stackStats.ARP)
   302  
   303  	return e
   304  }
   305  
   306  // LinkAddressProtocol implements stack.LinkAddressResolver.LinkAddressProtocol.
   307  func (*endpoint) LinkAddressProtocol() tcpip.NetworkProtocolNumber {
   308  	return header.IPv4ProtocolNumber
   309  }
   310  
   311  // LinkAddressRequest implements stack.LinkAddressResolver.LinkAddressRequest.
   312  func (e *endpoint) LinkAddressRequest(targetAddr, localAddr tcpip.Address, remoteLinkAddr tcpip.LinkAddress) tcpip.Error {
   313  	stats := e.stats.arp
   314  
   315  	if len(remoteLinkAddr) == 0 {
   316  		remoteLinkAddr = header.EthernetBroadcastAddress
   317  	}
   318  
   319  	if len(localAddr) == 0 {
   320  		addr, err := e.nic.PrimaryAddress(header.IPv4ProtocolNumber)
   321  		if err != nil {
   322  			return err
   323  		}
   324  
   325  		if len(addr.Address) == 0 {
   326  			stats.outgoingRequestInterfaceHasNoLocalAddressErrors.Increment()
   327  			return &tcpip.ErrNetworkUnreachable{}
   328  		}
   329  
   330  		localAddr = addr.Address
   331  	} else if !e.nic.CheckLocalAddress(header.IPv4ProtocolNumber, localAddr) {
   332  		stats.outgoingRequestBadLocalAddressErrors.Increment()
   333  		return &tcpip.ErrBadLocalAddress{}
   334  	}
   335  
   336  	return e.sendARPRequest(localAddr, targetAddr, remoteLinkAddr)
   337  }
   338  
   339  func (e *endpoint) sendARPRequest(localAddr, targetAddr tcpip.Address, remoteLinkAddr tcpip.LinkAddress) tcpip.Error {
   340  	pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   341  		ReserveHeaderBytes: int(e.MaxHeaderLength()),
   342  	})
   343  	defer pkt.DecRef()
   344  	h := header.ARP(pkt.NetworkHeader().Push(header.ARPSize))
   345  	pkt.NetworkProtocolNumber = ProtocolNumber
   346  	h.SetIPv4OverEthernet()
   347  	h.SetOp(header.ARPRequest)
   348  	// TODO(gvisor.dev/issue/4582): check copied length once TAP devices have a
   349  	// link address.
   350  	_ = copy(h.HardwareAddressSender(), e.nic.LinkAddress())
   351  	if n := copy(h.ProtocolAddressSender(), localAddr); n != header.IPv4AddressSize {
   352  		panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, header.IPv4AddressSize))
   353  	}
   354  	if n := copy(h.ProtocolAddressTarget(), targetAddr); n != header.IPv4AddressSize {
   355  		panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, header.IPv4AddressSize))
   356  	}
   357  
   358  	stats := e.stats.arp
   359  	if err := e.nic.WritePacketToRemote(remoteLinkAddr, ProtocolNumber, pkt); err != nil {
   360  		stats.outgoingRequestsDropped.Increment()
   361  		return err
   362  	}
   363  	stats.outgoingRequestsSent.Increment()
   364  	return nil
   365  }
   366  
   367  // ResolveStaticAddress implements stack.LinkAddressResolver.ResolveStaticAddress.
   368  func (*endpoint) ResolveStaticAddress(addr tcpip.Address) (tcpip.LinkAddress, bool) {
   369  	if addr == header.IPv4Broadcast {
   370  		return header.EthernetBroadcastAddress, true
   371  	}
   372  	if header.IsV4MulticastAddress(addr) {
   373  		return header.EthernetAddressFromMulticastIPv4Address(addr), true
   374  	}
   375  	return tcpip.LinkAddress([]byte(nil)), false
   376  }
   377  
   378  // SetOption implements stack.NetworkProtocol.SetOption.
   379  func (*protocol) SetOption(tcpip.SettableNetworkProtocolOption) tcpip.Error {
   380  	return &tcpip.ErrUnknownProtocolOption{}
   381  }
   382  
   383  // Option implements stack.NetworkProtocol.Option.
   384  func (*protocol) Option(tcpip.GettableNetworkProtocolOption) tcpip.Error {
   385  	return &tcpip.ErrUnknownProtocolOption{}
   386  }
   387  
   388  // Close implements stack.TransportProtocol.Close.
   389  func (*protocol) Close() {}
   390  
   391  // Wait implements stack.TransportProtocol.Wait.
   392  func (*protocol) Wait() {}
   393  
   394  // Parse implements stack.NetworkProtocol.Parse.
   395  func (*protocol) Parse(pkt *stack.PacketBuffer) (proto tcpip.TransportProtocolNumber, hasTransportHdr bool, ok bool) {
   396  	return 0, false, parse.ARP(pkt)
   397  }
   398  
   399  // Options holds options to configure a protocol.
   400  type Options struct {
   401  	// DADConfigs is the default DAD configurations used by ARP endpoints.
   402  	DADConfigs stack.DADConfigurations
   403  }
   404  
   405  // NewProtocolWithOptions returns an ARP network protocol factory that
   406  // will return an ARP network protocol with the provided options.
   407  func NewProtocolWithOptions(opts Options) stack.NetworkProtocolFactory {
   408  	return func(s *stack.Stack) stack.NetworkProtocol {
   409  		return &protocol{
   410  			stack:   s,
   411  			options: opts,
   412  		}
   413  	}
   414  }
   415  
   416  // NewProtocol returns an ARP network protocol.
   417  func NewProtocol(s *stack.Stack) stack.NetworkProtocol {
   418  	return NewProtocolWithOptions(Options{})(s)
   419  }