github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/link/muxed/injectable.go (about) 1 // Copyright 2019 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 muxed provides a muxed link endpoints. 16 package muxed 17 18 import ( 19 "github.com/SagerNet/gvisor/pkg/tcpip" 20 "github.com/SagerNet/gvisor/pkg/tcpip/header" 21 "github.com/SagerNet/gvisor/pkg/tcpip/stack" 22 ) 23 24 // InjectableEndpoint is an injectable multi endpoint. The endpoint has 25 // trivial routing rules that determine which InjectableEndpoint a given packet 26 // will be written to. Note that HandleLocal works differently for this 27 // endpoint (see WritePacket). 28 type InjectableEndpoint struct { 29 routes map[tcpip.Address]stack.InjectableLinkEndpoint 30 dispatcher stack.NetworkDispatcher 31 } 32 33 // MTU implements stack.LinkEndpoint. 34 func (m *InjectableEndpoint) MTU() uint32 { 35 minMTU := ^uint32(0) 36 for _, endpoint := range m.routes { 37 if endpointMTU := endpoint.MTU(); endpointMTU < minMTU { 38 minMTU = endpointMTU 39 } 40 } 41 return minMTU 42 } 43 44 // Capabilities implements stack.LinkEndpoint. 45 func (m *InjectableEndpoint) Capabilities() stack.LinkEndpointCapabilities { 46 minCapabilities := stack.LinkEndpointCapabilities(^uint(0)) 47 for _, endpoint := range m.routes { 48 minCapabilities &= endpoint.Capabilities() 49 } 50 return minCapabilities 51 } 52 53 // MaxHeaderLength implements stack.LinkEndpoint. 54 func (m *InjectableEndpoint) MaxHeaderLength() uint16 { 55 minHeaderLen := ^uint16(0) 56 for _, endpoint := range m.routes { 57 if headerLen := endpoint.MaxHeaderLength(); headerLen < minHeaderLen { 58 minHeaderLen = headerLen 59 } 60 } 61 return minHeaderLen 62 } 63 64 // LinkAddress implements stack.LinkEndpoint. 65 func (m *InjectableEndpoint) LinkAddress() tcpip.LinkAddress { 66 return "" 67 } 68 69 // Attach implements stack.LinkEndpoint. 70 func (m *InjectableEndpoint) Attach(dispatcher stack.NetworkDispatcher) { 71 for _, endpoint := range m.routes { 72 endpoint.Attach(dispatcher) 73 } 74 m.dispatcher = dispatcher 75 } 76 77 // IsAttached implements stack.LinkEndpoint. 78 func (m *InjectableEndpoint) IsAttached() bool { 79 return m.dispatcher != nil 80 } 81 82 // InjectInbound implements stack.InjectableLinkEndpoint. 83 func (m *InjectableEndpoint) InjectInbound(protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) { 84 m.dispatcher.DeliverNetworkPacket("" /* remote */, "" /* local */, protocol, pkt) 85 } 86 87 // WritePackets writes outbound packets to the appropriate 88 // LinkInjectableEndpoint based on the RemoteAddress. HandleLocal only works if 89 // r.RemoteAddress has a route registered in this endpoint. 90 func (m *InjectableEndpoint) WritePackets(r stack.RouteInfo, pkts stack.PacketBufferList, protocol tcpip.NetworkProtocolNumber) (int, tcpip.Error) { 91 endpoint, ok := m.routes[r.RemoteAddress] 92 if !ok { 93 return 0, &tcpip.ErrNoRoute{} 94 } 95 return endpoint.WritePackets(r, pkts, protocol) 96 } 97 98 // WritePacket writes outbound packets to the appropriate LinkInjectableEndpoint 99 // based on the RemoteAddress. HandleLocal only works if r.RemoteAddress has a 100 // route registered in this endpoint. 101 func (m *InjectableEndpoint) WritePacket(r stack.RouteInfo, protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) tcpip.Error { 102 if endpoint, ok := m.routes[r.RemoteAddress]; ok { 103 return endpoint.WritePacket(r, protocol, pkt) 104 } 105 return &tcpip.ErrNoRoute{} 106 } 107 108 // InjectOutbound writes outbound packets to the appropriate 109 // LinkInjectableEndpoint based on the dest address. 110 func (m *InjectableEndpoint) InjectOutbound(dest tcpip.Address, packet []byte) tcpip.Error { 111 endpoint, ok := m.routes[dest] 112 if !ok { 113 return &tcpip.ErrNoRoute{} 114 } 115 return endpoint.InjectOutbound(dest, packet) 116 } 117 118 // Wait implements stack.LinkEndpoint.Wait. 119 func (m *InjectableEndpoint) Wait() { 120 for _, ep := range m.routes { 121 ep.Wait() 122 } 123 } 124 125 // ARPHardwareType implements stack.LinkEndpoint.ARPHardwareType. 126 func (*InjectableEndpoint) ARPHardwareType() header.ARPHardwareType { 127 panic("unsupported operation") 128 } 129 130 // AddHeader implements stack.LinkEndpoint.AddHeader. 131 func (*InjectableEndpoint) AddHeader(local, remote tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) { 132 } 133 134 // NewInjectableEndpoint creates a new multi-endpoint injectable endpoint. 135 func NewInjectableEndpoint(routes map[tcpip.Address]stack.InjectableLinkEndpoint) *InjectableEndpoint { 136 return &InjectableEndpoint{ 137 routes: routes, 138 } 139 }