github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/link/ethernet/ethernet.go (about) 1 // Copyright 2020 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 ethernet provides an implementation of an ethernet link endpoint that 16 // wraps an inner link endpoint. 17 package ethernet 18 19 import ( 20 "github.com/SagerNet/gvisor/pkg/tcpip" 21 "github.com/SagerNet/gvisor/pkg/tcpip/header" 22 "github.com/SagerNet/gvisor/pkg/tcpip/link/nested" 23 "github.com/SagerNet/gvisor/pkg/tcpip/stack" 24 ) 25 26 var _ stack.NetworkDispatcher = (*Endpoint)(nil) 27 var _ stack.LinkEndpoint = (*Endpoint)(nil) 28 29 // New returns an ethernet link endpoint that wraps an inner link endpoint. 30 func New(ep stack.LinkEndpoint) *Endpoint { 31 var e Endpoint 32 e.Endpoint.Init(ep, &e) 33 return &e 34 } 35 36 // Endpoint is an ethernet endpoint. 37 // 38 // It adds an ethernet header to packets before sending them out through its 39 // inner link endpoint and consumes an ethernet header before sending the 40 // packet to the stack. 41 type Endpoint struct { 42 nested.Endpoint 43 } 44 45 // DeliverNetworkPacket implements stack.NetworkDispatcher. 46 func (e *Endpoint) DeliverNetworkPacket(_, _ tcpip.LinkAddress, _ tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) { 47 hdr, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize) 48 if !ok { 49 return 50 } 51 52 // Note, there is no need to check the destination link address here since 53 // the ethernet hardware filters frames based on their destination addresses. 54 eth := header.Ethernet(hdr) 55 e.Endpoint.DeliverNetworkPacket(eth.SourceAddress() /* remote */, eth.DestinationAddress() /* local */, eth.Type() /* protocol */, pkt) 56 } 57 58 // Capabilities implements stack.LinkEndpoint. 59 func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities { 60 return stack.CapabilityResolutionRequired | e.Endpoint.Capabilities() 61 } 62 63 // WritePacket implements stack.LinkEndpoint. 64 func (e *Endpoint) WritePacket(r stack.RouteInfo, proto tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) tcpip.Error { 65 e.AddHeader(e.Endpoint.LinkAddress(), r.RemoteLinkAddress, proto, pkt) 66 return e.Endpoint.WritePacket(r, proto, pkt) 67 } 68 69 // WritePackets implements stack.LinkEndpoint. 70 func (e *Endpoint) WritePackets(r stack.RouteInfo, pkts stack.PacketBufferList, proto tcpip.NetworkProtocolNumber) (int, tcpip.Error) { 71 linkAddr := e.Endpoint.LinkAddress() 72 73 for pkt := pkts.Front(); pkt != nil; pkt = pkt.Next() { 74 e.AddHeader(linkAddr, r.RemoteLinkAddress, proto, pkt) 75 } 76 77 return e.Endpoint.WritePackets(r, pkts, proto) 78 } 79 80 // MaxHeaderLength implements stack.LinkEndpoint. 81 func (e *Endpoint) MaxHeaderLength() uint16 { 82 return header.EthernetMinimumSize + e.Endpoint.MaxHeaderLength() 83 } 84 85 // ARPHardwareType implements stack.LinkEndpoint. 86 func (*Endpoint) ARPHardwareType() header.ARPHardwareType { 87 return header.ARPHardwareEther 88 } 89 90 // AddHeader implements stack.LinkEndpoint. 91 func (*Endpoint) AddHeader(local, remote tcpip.LinkAddress, proto tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) { 92 eth := header.Ethernet(pkt.LinkHeader().Push(header.EthernetMinimumSize)) 93 fields := header.EthernetFields{ 94 SrcAddr: local, 95 DstAddr: remote, 96 Type: proto, 97 } 98 eth.Encode(&fields) 99 }