github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/transport/icmp/protocol.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 icmp contains the implementation of the ICMP and IPv6-ICMP transport 16 // protocols for use in ping. 17 package icmp 18 19 import ( 20 "fmt" 21 22 "github.com/SagerNet/gvisor/pkg/tcpip" 23 "github.com/SagerNet/gvisor/pkg/tcpip/buffer" 24 "github.com/SagerNet/gvisor/pkg/tcpip/header" 25 "github.com/SagerNet/gvisor/pkg/tcpip/stack" 26 "github.com/SagerNet/gvisor/pkg/tcpip/transport/raw" 27 "github.com/SagerNet/gvisor/pkg/waiter" 28 ) 29 30 const ( 31 // ProtocolNumber4 is the ICMP protocol number. 32 ProtocolNumber4 = header.ICMPv4ProtocolNumber 33 34 // ProtocolNumber6 is the IPv6-ICMP protocol number. 35 ProtocolNumber6 = header.ICMPv6ProtocolNumber 36 ) 37 38 // protocol implements stack.TransportProtocol. 39 type protocol struct { 40 stack *stack.Stack 41 42 number tcpip.TransportProtocolNumber 43 } 44 45 // Number returns the ICMP protocol number. 46 func (p *protocol) Number() tcpip.TransportProtocolNumber { 47 return p.number 48 } 49 50 func (p *protocol) netProto() tcpip.NetworkProtocolNumber { 51 switch p.number { 52 case ProtocolNumber4: 53 return header.IPv4ProtocolNumber 54 case ProtocolNumber6: 55 return header.IPv6ProtocolNumber 56 } 57 panic(fmt.Sprint("unknown protocol number: ", p.number)) 58 } 59 60 // NewEndpoint creates a new icmp endpoint. It implements 61 // stack.TransportProtocol.NewEndpoint. 62 func (p *protocol) NewEndpoint(netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, tcpip.Error) { 63 if netProto != p.netProto() { 64 return nil, &tcpip.ErrUnknownProtocol{} 65 } 66 return newEndpoint(p.stack, netProto, p.number, waiterQueue) 67 } 68 69 // NewRawEndpoint creates a new raw icmp endpoint. It implements 70 // stack.TransportProtocol.NewRawEndpoint. 71 func (p *protocol) NewRawEndpoint(netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, tcpip.Error) { 72 if netProto != p.netProto() { 73 return nil, &tcpip.ErrUnknownProtocol{} 74 } 75 return raw.NewEndpoint(p.stack, netProto, p.number, waiterQueue) 76 } 77 78 // MinimumPacketSize returns the minimum valid icmp packet size. 79 func (p *protocol) MinimumPacketSize() int { 80 switch p.number { 81 case ProtocolNumber4: 82 return header.ICMPv4MinimumSize 83 case ProtocolNumber6: 84 return header.ICMPv6MinimumSize 85 } 86 panic(fmt.Sprint("unknown protocol number: ", p.number)) 87 } 88 89 // ParsePorts in case of ICMP sets src to 0, dst to ICMP ID, and err to nil. 90 func (p *protocol) ParsePorts(v buffer.View) (src, dst uint16, err tcpip.Error) { 91 switch p.number { 92 case ProtocolNumber4: 93 hdr := header.ICMPv4(v) 94 return 0, hdr.Ident(), nil 95 case ProtocolNumber6: 96 hdr := header.ICMPv6(v) 97 return 0, hdr.Ident(), nil 98 } 99 panic(fmt.Sprint("unknown protocol number: ", p.number)) 100 } 101 102 // HandleUnknownDestinationPacket handles packets targeted at this protocol but 103 // that don't match any existing endpoint. 104 func (*protocol) HandleUnknownDestinationPacket(stack.TransportEndpointID, *stack.PacketBuffer) stack.UnknownDestinationPacketDisposition { 105 return stack.UnknownDestinationPacketHandled 106 } 107 108 // SetOption implements stack.TransportProtocol.SetOption. 109 func (*protocol) SetOption(tcpip.SettableTransportProtocolOption) tcpip.Error { 110 return &tcpip.ErrUnknownProtocolOption{} 111 } 112 113 // Option implements stack.TransportProtocol.Option. 114 func (*protocol) Option(tcpip.GettableTransportProtocolOption) tcpip.Error { 115 return &tcpip.ErrUnknownProtocolOption{} 116 } 117 118 // Close implements stack.TransportProtocol.Close. 119 func (*protocol) Close() {} 120 121 // Wait implements stack.TransportProtocol.Wait. 122 func (*protocol) Wait() {} 123 124 // Parse implements stack.TransportProtocol.Parse. 125 func (*protocol) Parse(pkt *stack.PacketBuffer) bool { 126 // Right now, the Parse() method is tied to enabled protocols passed into 127 // stack.New. This works for UDP and TCP, but we handle ICMP traffic even 128 // when netstack users don't pass ICMP as a supported protocol. 129 return false 130 } 131 132 // NewProtocol4 returns an ICMPv4 transport protocol. 133 func NewProtocol4(s *stack.Stack) stack.TransportProtocol { 134 return &protocol{stack: s, number: ProtocolNumber4} 135 } 136 137 // NewProtocol6 returns an ICMPv6 transport protocol. 138 func NewProtocol6(s *stack.Stack) stack.TransportProtocol { 139 return &protocol{stack: s, number: ProtocolNumber6} 140 }