github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/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/FlowerWrong/netstack/tcpip"
    30  	"github.com/FlowerWrong/netstack/tcpip/buffer"
    31  	"github.com/FlowerWrong/netstack/tcpip/header"
    32  	"github.com/FlowerWrong/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, buffer.Prependable, buffer.VectorisedView, tcpip.TransportProtocolNumber, uint8, stack.PacketLooping) *tcpip.Error {
    83  	return tcpip.ErrNotSupported
    84  }
    85  
    86  func (e *endpoint) WriteHeaderIncludedPacket(r *stack.Route, payload buffer.VectorisedView, loop stack.PacketLooping) *tcpip.Error {
    87  	return tcpip.ErrNotSupported
    88  }
    89  
    90  func (e *endpoint) HandlePacket(r *stack.Route, vv buffer.VectorisedView) {
    91  	v := vv.First()
    92  	h := header.ARP(v)
    93  	if !h.IsValid() {
    94  		return
    95  	}
    96  
    97  	switch h.Op() {
    98  	case header.ARPRequest:
    99  		localAddr := tcpip.Address(h.ProtocolAddressTarget())
   100  		if e.linkAddrCache.CheckLocalAddress(e.nicid, header.IPv4ProtocolNumber, localAddr) == 0 {
   101  			return // we have no useful answer, ignore the request
   102  		}
   103  		hdr := buffer.NewPrependable(int(e.linkEP.MaxHeaderLength()) + header.ARPSize)
   104  		pkt := header.ARP(hdr.Prepend(header.ARPSize))
   105  		pkt.SetIPv4OverEthernet()
   106  		pkt.SetOp(header.ARPReply)
   107  		copy(pkt.HardwareAddressSender(), r.LocalLinkAddress[:])
   108  		copy(pkt.ProtocolAddressSender(), h.ProtocolAddressTarget())
   109  		copy(pkt.HardwareAddressTarget(), h.HardwareAddressSender())
   110  		copy(pkt.ProtocolAddressTarget(), h.ProtocolAddressSender())
   111  		e.linkEP.WritePacket(r, nil /* gso */, hdr, buffer.VectorisedView{}, ProtocolNumber)
   112  	case header.ARPReply:
   113  	}
   114  }
   115  
   116  // protocol implements stack.NetworkProtocol and stack.LinkAddressResolver.
   117  type protocol struct {
   118  }
   119  
   120  func (p *protocol) Number() tcpip.NetworkProtocolNumber { return ProtocolNumber }
   121  func (p *protocol) MinimumPacketSize() int              { return header.ARPSize }
   122  func (p *protocol) DefaultPrefixLen() int               { return 0 }
   123  
   124  func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) {
   125  	h := header.ARP(v)
   126  	return tcpip.Address(h.ProtocolAddressSender()), ProtocolAddress
   127  }
   128  
   129  func (p *protocol) NewEndpoint(nicid tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, sender stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
   130  	if addrWithPrefix.Address != ProtocolAddress {
   131  		return nil, tcpip.ErrBadLocalAddress
   132  	}
   133  	return &endpoint{
   134  		nicid:         nicid,
   135  		linkEP:        sender,
   136  		linkAddrCache: linkAddrCache,
   137  	}, nil
   138  }
   139  
   140  // LinkAddressProtocol implements stack.LinkAddressResolver.
   141  func (*protocol) LinkAddressProtocol() tcpip.NetworkProtocolNumber {
   142  	return header.IPv4ProtocolNumber
   143  }
   144  
   145  // LinkAddressRequest implements stack.LinkAddressResolver.
   146  func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, linkEP stack.LinkEndpoint) *tcpip.Error {
   147  	r := &stack.Route{
   148  		RemoteLinkAddress: broadcastMAC,
   149  	}
   150  
   151  	hdr := buffer.NewPrependable(int(linkEP.MaxHeaderLength()) + header.ARPSize)
   152  	h := header.ARP(hdr.Prepend(header.ARPSize))
   153  	h.SetIPv4OverEthernet()
   154  	h.SetOp(header.ARPRequest)
   155  	copy(h.HardwareAddressSender(), linkEP.LinkAddress())
   156  	copy(h.ProtocolAddressSender(), localAddr)
   157  	copy(h.ProtocolAddressTarget(), addr)
   158  
   159  	return linkEP.WritePacket(r, nil /* gso */, hdr, buffer.VectorisedView{}, ProtocolNumber)
   160  }
   161  
   162  // ResolveStaticAddress implements stack.LinkAddressResolver.
   163  func (*protocol) ResolveStaticAddress(addr tcpip.Address) (tcpip.LinkAddress, bool) {
   164  	if addr == header.IPv4Broadcast {
   165  		return broadcastMAC, true
   166  	}
   167  	if header.IsV4MulticastAddress(addr) {
   168  		// RFC 1112 Host Extensions for IP Multicasting
   169  		//
   170  		// 6.4. Extensions to an Ethernet Local Network Module:
   171  		//
   172  		// An IP host group address is mapped to an Ethernet multicast
   173  		// address by placing the low-order 23-bits of the IP address
   174  		// into the low-order 23 bits of the Ethernet multicast address
   175  		// 01-00-5E-00-00-00 (hex).
   176  		return tcpip.LinkAddress([]byte{
   177  			0x01,
   178  			0x00,
   179  			0x5e,
   180  			addr[header.IPv4AddressSize-3] & 0x7f,
   181  			addr[header.IPv4AddressSize-2],
   182  			addr[header.IPv4AddressSize-1],
   183  		}), true
   184  	}
   185  	return "", false
   186  }
   187  
   188  // SetOption implements NetworkProtocol.
   189  func (p *protocol) SetOption(option interface{}) *tcpip.Error {
   190  	return tcpip.ErrUnknownProtocolOption
   191  }
   192  
   193  // Option implements NetworkProtocol.
   194  func (p *protocol) Option(option interface{}) *tcpip.Error {
   195  	return tcpip.ErrUnknownProtocolOption
   196  }
   197  
   198  var broadcastMAC = tcpip.LinkAddress([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff})
   199  
   200  // NewProtocol returns an ARP network protocol.
   201  func NewProtocol() stack.NetworkProtocol {
   202  	return &protocol{}
   203  }