github.com/google/netstack@v0.0.0-20191123085552-55fcc16cd0eb/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/google/netstack/tcpip" 30 "github.com/google/netstack/tcpip/buffer" 31 "github.com/google/netstack/tcpip/header" 32 "github.com/google/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 }