github.com/google/netstack@v0.0.0-20191123085552-55fcc16cd0eb/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. To use it in the networking stack, this package 17 // must be added to the project, and activated on the stack by passing 18 // icmp.NewProtocol4() and/or icmp.NewProtocol6() as one of the transport 19 // protocols when calling stack.New(). Then endpoints can be created by passing 20 // icmp.ProtocolNumber or icmp.ProtocolNumber6 as the transport protocol number 21 // when calling Stack.NewEndpoint(). 22 package icmp 23 24 import ( 25 "fmt" 26 27 "github.com/google/netstack/tcpip" 28 "github.com/google/netstack/tcpip/buffer" 29 "github.com/google/netstack/tcpip/header" 30 "github.com/google/netstack/tcpip/stack" 31 "github.com/google/netstack/tcpip/transport/raw" 32 "github.com/google/netstack/waiter" 33 ) 34 35 const ( 36 // ProtocolNumber4 is the ICMP protocol number. 37 ProtocolNumber4 = header.ICMPv4ProtocolNumber 38 39 // ProtocolNumber6 is the IPv6-ICMP protocol number. 40 ProtocolNumber6 = header.ICMPv6ProtocolNumber 41 ) 42 43 // protocol implements stack.TransportProtocol. 44 type protocol struct { 45 number tcpip.TransportProtocolNumber 46 } 47 48 // Number returns the ICMP protocol number. 49 func (p *protocol) Number() tcpip.TransportProtocolNumber { 50 return p.number 51 } 52 53 func (p *protocol) netProto() tcpip.NetworkProtocolNumber { 54 switch p.number { 55 case ProtocolNumber4: 56 return header.IPv4ProtocolNumber 57 case ProtocolNumber6: 58 return header.IPv6ProtocolNumber 59 } 60 panic(fmt.Sprint("unknown protocol number: ", p.number)) 61 } 62 63 // NewEndpoint creates a new icmp endpoint. It implements 64 // stack.TransportProtocol.NewEndpoint. 65 func (p *protocol) NewEndpoint(stack *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) { 66 if netProto != p.netProto() { 67 return nil, tcpip.ErrUnknownProtocol 68 } 69 return newEndpoint(stack, netProto, p.number, waiterQueue) 70 } 71 72 // NewRawEndpoint creates a new raw icmp endpoint. It implements 73 // stack.TransportProtocol.NewRawEndpoint. 74 func (p *protocol) NewRawEndpoint(stack *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) { 75 if netProto != p.netProto() { 76 return nil, tcpip.ErrUnknownProtocol 77 } 78 return raw.NewEndpoint(stack, netProto, p.number, waiterQueue) 79 } 80 81 // MinimumPacketSize returns the minimum valid icmp packet size. 82 func (p *protocol) MinimumPacketSize() int { 83 switch p.number { 84 case ProtocolNumber4: 85 return header.ICMPv4MinimumSize 86 case ProtocolNumber6: 87 return header.ICMPv6MinimumSize 88 } 89 panic(fmt.Sprint("unknown protocol number: ", p.number)) 90 } 91 92 // ParsePorts in case of ICMP sets src to 0, dst to ICMP ID, and err to nil. 93 func (p *protocol) ParsePorts(v buffer.View) (src, dst uint16, err *tcpip.Error) { 94 switch p.number { 95 case ProtocolNumber4: 96 hdr := header.ICMPv4(v) 97 return 0, hdr.Ident(), nil 98 case ProtocolNumber6: 99 hdr := header.ICMPv6(v) 100 return 0, hdr.Ident(), nil 101 } 102 panic(fmt.Sprint("unknown protocol number: ", p.number)) 103 } 104 105 // HandleUnknownDestinationPacket handles packets targeted at this protocol but 106 // that don't match any existing endpoint. 107 func (p *protocol) HandleUnknownDestinationPacket(*stack.Route, stack.TransportEndpointID, tcpip.PacketBuffer) bool { 108 return true 109 } 110 111 // SetOption implements TransportProtocol.SetOption. 112 func (p *protocol) SetOption(option interface{}) *tcpip.Error { 113 return tcpip.ErrUnknownProtocolOption 114 } 115 116 // Option implements TransportProtocol.Option. 117 func (p *protocol) Option(option interface{}) *tcpip.Error { 118 return tcpip.ErrUnknownProtocolOption 119 } 120 121 // NewProtocol4 returns an ICMPv4 transport protocol. 122 func NewProtocol4() stack.TransportProtocol { 123 return &protocol{ProtocolNumber4} 124 } 125 126 // NewProtocol6 returns an ICMPv6 transport protocol. 127 func NewProtocol6() stack.TransportProtocol { 128 return &protocol{ProtocolNumber6} 129 }