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 }