github.com/vpnishe/netstack@v1.10.6/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  //
    19  // To use it in the networking stack, pass arp.NewProtocol() as one of the
    20  // network protocols when calling stack.New. Then add an "arp" address to every
    21  // NIC on the stack that should respond to ARP requests. That is:
    22  //
    23  //	if err := s.AddAddress(1, arp.ProtocolNumber, "arp"); err != nil {
    24  //		// handle err
    25  //	}
    26  package arp
    27  
    28  import (
    29  	"github.com/vpnishe/netstack/tcpip"
    30  	"github.com/vpnishe/netstack/tcpip/buffer"
    31  	"github.com/vpnishe/netstack/tcpip/header"
    32  	"github.com/vpnishe/netstack/tcpip/stack"
    33  )
    34  
    35  const (
    36  	// ProtocolNumber is the ARP protocol number.
    37  	ProtocolNumber = header.ARPProtocolNumber
    38  
    39  	// ProtocolAddress is the address expected by the ARP endpoint.
    40  	ProtocolAddress = tcpip.Address("arp")
    41  )
    42  
    43  // endpoint implements stack.NetworkEndpoint.
    44  type endpoint struct {
    45  	nicID         tcpip.NICID
    46  	linkEP        stack.LinkEndpoint
    47  	linkAddrCache stack.LinkAddressCache
    48  }
    49  
    50  // DefaultTTL is unused for ARP. It implements stack.NetworkEndpoint.
    51  func (e *endpoint) DefaultTTL() uint8 {
    52  	return 0
    53  }
    54  
    55  func (e *endpoint) MTU() uint32 {
    56  	lmtu := e.linkEP.MTU()
    57  	return lmtu - uint32(e.MaxHeaderLength())
    58  }
    59  
    60  func (e *endpoint) NICID() tcpip.NICID {
    61  	return e.nicID
    62  }
    63  
    64  func (e *endpoint) Capabilities() stack.LinkEndpointCapabilities {
    65  	return e.linkEP.Capabilities()
    66  }
    67  
    68  func (e *endpoint) ID() *stack.NetworkEndpointID {
    69  	return &stack.NetworkEndpointID{ProtocolAddress}
    70  }
    71  
    72  func (e *endpoint) PrefixLen() int {
    73  	return 0
    74  }
    75  
    76  func (e *endpoint) MaxHeaderLength() uint16 {
    77  	return e.linkEP.MaxHeaderLength() + header.ARPSize
    78  }
    79  
    80  func (e *endpoint) Close() {}
    81  
    82  func (e *endpoint) WritePacket(*stack.Route, *stack.GSO, stack.NetworkHeaderParams, stack.PacketLooping, tcpip.PacketBuffer) *tcpip.Error {
    83  	return tcpip.ErrNotSupported
    84  }
    85  
    86  // WritePackets implements stack.NetworkEndpoint.WritePackets.
    87  func (e *endpoint) WritePackets(*stack.Route, *stack.GSO, []stack.PacketDescriptor, buffer.VectorisedView, stack.NetworkHeaderParams, stack.PacketLooping) (int, *tcpip.Error) {
    88  	return 0, tcpip.ErrNotSupported
    89  }
    90  
    91  func (e *endpoint) WriteHeaderIncludedPacket(r *stack.Route, loop stack.PacketLooping, pkt tcpip.PacketBuffer) *tcpip.Error {
    92  	return tcpip.ErrNotSupported
    93  }
    94  
    95  func (e *endpoint) HandlePacket(r *stack.Route, pkt tcpip.PacketBuffer) {
    96  	v := pkt.Data.First()
    97  	h := header.ARP(v)
    98  	if !h.IsValid() {
    99  		return
   100  	}
   101  
   102  	switch h.Op() {
   103  	case header.ARPRequest:
   104  		localAddr := tcpip.Address(h.ProtocolAddressTarget())
   105  		if e.linkAddrCache.CheckLocalAddress(e.nicID, header.IPv4ProtocolNumber, localAddr) == 0 {
   106  			return // we have no useful answer, ignore the request
   107  		}
   108  		hdr := buffer.NewPrependable(int(e.linkEP.MaxHeaderLength()) + header.ARPSize)
   109  		packet := header.ARP(hdr.Prepend(header.ARPSize))
   110  		packet.SetIPv4OverEthernet()
   111  		packet.SetOp(header.ARPReply)
   112  		copy(packet.HardwareAddressSender(), r.LocalLinkAddress[:])
   113  		copy(packet.ProtocolAddressSender(), h.ProtocolAddressTarget())
   114  		copy(packet.HardwareAddressTarget(), h.HardwareAddressSender())
   115  		copy(packet.ProtocolAddressTarget(), h.ProtocolAddressSender())
   116  		e.linkEP.WritePacket(r, nil /* gso */, ProtocolNumber, tcpip.PacketBuffer{
   117  			Header: hdr,
   118  		})
   119  		fallthrough // also fill the cache from requests
   120  	case header.ARPReply:
   121  		addr := tcpip.Address(h.ProtocolAddressSender())
   122  		linkAddr := tcpip.LinkAddress(h.HardwareAddressSender())
   123  		e.linkAddrCache.AddLinkAddress(e.nicID, addr, linkAddr)
   124  	}
   125  }
   126  
   127  // protocol implements stack.NetworkProtocol and stack.LinkAddressResolver.
   128  type protocol struct {
   129  }
   130  
   131  func (p *protocol) Number() tcpip.NetworkProtocolNumber { return ProtocolNumber }
   132  func (p *protocol) MinimumPacketSize() int              { return header.ARPSize }
   133  func (p *protocol) DefaultPrefixLen() int               { return 0 }
   134  
   135  func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) {
   136  	h := header.ARP(v)
   137  	return tcpip.Address(h.ProtocolAddressSender()), ProtocolAddress
   138  }
   139  
   140  func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, sender stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
   141  	if addrWithPrefix.Address != ProtocolAddress {
   142  		return nil, tcpip.ErrBadLocalAddress
   143  	}
   144  	return &endpoint{
   145  		nicID:         nicID,
   146  		linkEP:        sender,
   147  		linkAddrCache: linkAddrCache,
   148  	}, nil
   149  }
   150  
   151  // LinkAddressProtocol implements stack.LinkAddressResolver.
   152  func (*protocol) LinkAddressProtocol() tcpip.NetworkProtocolNumber {
   153  	return header.IPv4ProtocolNumber
   154  }
   155  
   156  // LinkAddressRequest implements stack.LinkAddressResolver.
   157  func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, linkEP stack.LinkEndpoint) *tcpip.Error {
   158  	r := &stack.Route{
   159  		RemoteLinkAddress: broadcastMAC,
   160  	}
   161  
   162  	hdr := buffer.NewPrependable(int(linkEP.MaxHeaderLength()) + header.ARPSize)
   163  	h := header.ARP(hdr.Prepend(header.ARPSize))
   164  	h.SetIPv4OverEthernet()
   165  	h.SetOp(header.ARPRequest)
   166  	copy(h.HardwareAddressSender(), linkEP.LinkAddress())
   167  	copy(h.ProtocolAddressSender(), localAddr)
   168  	copy(h.ProtocolAddressTarget(), addr)
   169  
   170  	return linkEP.WritePacket(r, nil /* gso */, ProtocolNumber, tcpip.PacketBuffer{
   171  		Header: hdr,
   172  	})
   173  }
   174  
   175  // ResolveStaticAddress implements stack.LinkAddressResolver.
   176  func (*protocol) ResolveStaticAddress(addr tcpip.Address) (tcpip.LinkAddress, bool) {
   177  	if addr == header.IPv4Broadcast {
   178  		return broadcastMAC, true
   179  	}
   180  	if header.IsV4MulticastAddress(addr) {
   181  		// RFC 1112 Host Extensions for IP Multicasting
   182  		//
   183  		// 6.4. Extensions to an Ethernet Local Network Module:
   184  		//
   185  		// An IP host group address is mapped to an Ethernet multicast
   186  		// address by placing the low-order 23-bits of the IP address
   187  		// into the low-order 23 bits of the Ethernet multicast address
   188  		// 01-00-5E-00-00-00 (hex).
   189  		return tcpip.LinkAddress([]byte{
   190  			0x01,
   191  			0x00,
   192  			0x5e,
   193  			addr[header.IPv4AddressSize-3] & 0x7f,
   194  			addr[header.IPv4AddressSize-2],
   195  			addr[header.IPv4AddressSize-1],
   196  		}), true
   197  	}
   198  	return "", false
   199  }
   200  
   201  // SetOption implements NetworkProtocol.
   202  func (p *protocol) SetOption(option interface{}) *tcpip.Error {
   203  	return tcpip.ErrUnknownProtocolOption
   204  }
   205  
   206  // Option implements NetworkProtocol.
   207  func (p *protocol) Option(option interface{}) *tcpip.Error {
   208  	return tcpip.ErrUnknownProtocolOption
   209  }
   210  
   211  var broadcastMAC = tcpip.LinkAddress([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff})
   212  
   213  // NewProtocol returns an ARP network protocol.
   214  func NewProtocol() stack.NetworkProtocol {
   215  	return &protocol{}
   216  }