github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/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 "github.com/SagerNet/gvisor/pkg/sync" 26 "github.com/SagerNet/gvisor/pkg/tcpip" 27 "github.com/SagerNet/gvisor/pkg/tcpip/buffer" 28 "github.com/SagerNet/gvisor/pkg/tcpip/header" 29 "github.com/SagerNet/gvisor/pkg/tcpip/header/parse" 30 "github.com/SagerNet/gvisor/pkg/tcpip/network/internal/ip" 31 "github.com/SagerNet/gvisor/pkg/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 packet := header.ARP(respPkt.NetworkHeader().Push(header.ARPSize)) 202 respPkt.NetworkProtocolNumber = ProtocolNumber 203 packet.SetIPv4OverEthernet() 204 packet.SetOp(header.ARPReply) 205 // TODO(github.com/SagerNet/issue/4582): check copied length once TAP devices have a 206 // link address. 207 _ = copy(packet.HardwareAddressSender(), e.nic.LinkAddress()) 208 if n := copy(packet.ProtocolAddressSender(), h.ProtocolAddressTarget()); n != header.IPv4AddressSize { 209 panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, header.IPv4AddressSize)) 210 } 211 origSender := h.HardwareAddressSender() 212 if n := copy(packet.HardwareAddressTarget(), origSender); n != header.EthernetAddressSize { 213 panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, header.EthernetAddressSize)) 214 } 215 if n := copy(packet.ProtocolAddressTarget(), h.ProtocolAddressSender()); n != header.IPv4AddressSize { 216 panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, header.IPv4AddressSize)) 217 } 218 219 // As per RFC 826, under Packet Reception: 220 // Swap hardware and protocol fields, putting the local hardware and 221 // protocol addresses in the sender fields. 222 // 223 // Send the packet to the (new) target hardware address on the same 224 // hardware on which the request was received. 225 if err := e.nic.WritePacketToRemote(tcpip.LinkAddress(origSender), ProtocolNumber, respPkt); err != nil { 226 stats.outgoingRepliesDropped.Increment() 227 } else { 228 stats.outgoingRepliesSent.Increment() 229 } 230 231 case header.ARPReply: 232 stats.repliesReceived.Increment() 233 addr := tcpip.Address(h.ProtocolAddressSender()) 234 linkAddr := tcpip.LinkAddress(h.HardwareAddressSender()) 235 236 e.mu.Lock() 237 e.mu.dad.StopLocked(addr, &stack.DADDupAddrDetected{HolderLinkAddress: linkAddr}) 238 e.mu.Unlock() 239 240 // The solicited, override, and isRouter flags are not available for ARP; 241 // they are only available for IPv6 Neighbor Advertisements. 242 switch err := e.nic.HandleNeighborConfirmation(header.IPv4ProtocolNumber, addr, linkAddr, stack.ReachabilityConfirmationFlags{ 243 // Solicited and unsolicited (also referred to as gratuitous) ARP Replies 244 // are handled equivalently to a solicited Neighbor Advertisement. 245 Solicited: true, 246 // If a different link address is received than the one cached, the entry 247 // should always go to Stale. 248 Override: false, 249 // ARP does not distinguish between router and non-router hosts. 250 IsRouter: false, 251 }); err.(type) { 252 case nil: 253 case *tcpip.ErrNotSupported: 254 // The stack may support ARP but the NIC may not need link resolution. 255 default: 256 panic(fmt.Sprintf("unexpected error when informing NIC of neighbor confirmation message: %s", err)) 257 } 258 } 259 } 260 261 // Stats implements stack.NetworkEndpoint. 262 func (e *endpoint) Stats() stack.NetworkEndpointStats { 263 return &e.stats.localStats 264 } 265 266 var _ stack.NetworkProtocol = (*protocol)(nil) 267 268 type protocol struct { 269 stack *stack.Stack 270 options Options 271 } 272 273 func (p *protocol) Number() tcpip.NetworkProtocolNumber { return ProtocolNumber } 274 func (p *protocol) MinimumPacketSize() int { return header.ARPSize } 275 func (p *protocol) DefaultPrefixLen() int { return 0 } 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 h := header.ARP(pkt.NetworkHeader().Push(header.ARPSize)) 344 pkt.NetworkProtocolNumber = ProtocolNumber 345 h.SetIPv4OverEthernet() 346 h.SetOp(header.ARPRequest) 347 // TODO(github.com/SagerNet/issue/4582): check copied length once TAP devices have a 348 // link address. 349 _ = copy(h.HardwareAddressSender(), e.nic.LinkAddress()) 350 if n := copy(h.ProtocolAddressSender(), localAddr); n != header.IPv4AddressSize { 351 panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, header.IPv4AddressSize)) 352 } 353 if n := copy(h.ProtocolAddressTarget(), targetAddr); n != header.IPv4AddressSize { 354 panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, header.IPv4AddressSize)) 355 } 356 357 stats := e.stats.arp 358 if err := e.nic.WritePacketToRemote(remoteLinkAddr, ProtocolNumber, pkt); err != nil { 359 stats.outgoingRequestsDropped.Increment() 360 return err 361 } 362 stats.outgoingRequestsSent.Increment() 363 return nil 364 } 365 366 // ResolveStaticAddress implements stack.LinkAddressResolver.ResolveStaticAddress. 367 func (*endpoint) ResolveStaticAddress(addr tcpip.Address) (tcpip.LinkAddress, bool) { 368 if addr == header.IPv4Broadcast { 369 return header.EthernetBroadcastAddress, true 370 } 371 if header.IsV4MulticastAddress(addr) { 372 return header.EthernetAddressFromMulticastIPv4Address(addr), true 373 } 374 return tcpip.LinkAddress([]byte(nil)), false 375 } 376 377 // SetOption implements stack.NetworkProtocol.SetOption. 378 func (*protocol) SetOption(tcpip.SettableNetworkProtocolOption) tcpip.Error { 379 return &tcpip.ErrUnknownProtocolOption{} 380 } 381 382 // Option implements stack.NetworkProtocol.Option. 383 func (*protocol) Option(tcpip.GettableNetworkProtocolOption) tcpip.Error { 384 return &tcpip.ErrUnknownProtocolOption{} 385 } 386 387 // Close implements stack.TransportProtocol.Close. 388 func (*protocol) Close() {} 389 390 // Wait implements stack.TransportProtocol.Wait. 391 func (*protocol) Wait() {} 392 393 // Parse implements stack.NetworkProtocol.Parse. 394 func (*protocol) Parse(pkt *stack.PacketBuffer) (proto tcpip.TransportProtocolNumber, hasTransportHdr bool, ok bool) { 395 return 0, false, parse.ARP(pkt) 396 } 397 398 // Options holds options to configure a protocol. 399 type Options struct { 400 // DADConfigs is the default DAD configurations used by ARP endpoints. 401 DADConfigs stack.DADConfigurations 402 } 403 404 // NewProtocolWithOptions returns an ARP network protocol factory that 405 // will return an ARP network protocol with the provided options. 406 func NewProtocolWithOptions(opts Options) stack.NetworkProtocolFactory { 407 return func(s *stack.Stack) stack.NetworkProtocol { 408 return &protocol{ 409 stack: s, 410 options: opts, 411 } 412 } 413 } 414 415 // NewProtocol returns an ARP network protocol. 416 func NewProtocol(s *stack.Stack) stack.NetworkProtocol { 417 return NewProtocolWithOptions(Options{})(s) 418 }