github.com/FlowerWrong/netstack@v0.0.0-20191009141956-e5848263af28/tcpip/transport/udp/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 udp contains the implementation of the UDP transport protocol. To use 16 // it in the networking stack, this package must be added to the project, and 17 // activated on the stack by passing udp.NewProtocol() as one of the 18 // transport protocols when calling stack.New(). Then endpoints can be created 19 // by passing udp.ProtocolNumber as the transport protocol number when calling 20 // Stack.NewEndpoint(). 21 package udp 22 23 import ( 24 "github.com/FlowerWrong/netstack/tcpip" 25 "github.com/FlowerWrong/netstack/tcpip/buffer" 26 "github.com/FlowerWrong/netstack/tcpip/header" 27 "github.com/FlowerWrong/netstack/tcpip/stack" 28 "github.com/FlowerWrong/netstack/tcpip/transport/raw" 29 "github.com/FlowerWrong/netstack/waiter" 30 ) 31 32 const ( 33 // ProtocolNumber is the udp protocol number. 34 ProtocolNumber = header.UDPProtocolNumber 35 ) 36 37 type protocol struct{} 38 39 // Number returns the udp protocol number. 40 func (*protocol) Number() tcpip.TransportProtocolNumber { 41 return ProtocolNumber 42 } 43 44 // NewEndpoint creates a new udp endpoint. 45 func (*protocol) NewEndpoint(stack *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) { 46 return newEndpoint(stack, netProto, waiterQueue), nil 47 } 48 49 // NewRawEndpoint creates a new raw UDP endpoint. It implements 50 // stack.TransportProtocol.NewRawEndpoint. 51 func (p *protocol) NewRawEndpoint(stack *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) { 52 return raw.NewEndpoint(stack, netProto, header.UDPProtocolNumber, waiterQueue) 53 } 54 55 // MinimumPacketSize returns the minimum valid udp packet size. 56 func (*protocol) MinimumPacketSize() int { 57 return header.UDPMinimumSize 58 } 59 60 // ParsePorts returns the source and destination ports stored in the given udp 61 // packet. 62 func (*protocol) ParsePorts(v buffer.View) (src, dst uint16, err *tcpip.Error) { 63 h := header.UDP(v) 64 return h.SourcePort(), h.DestinationPort(), nil 65 } 66 67 // HandleUnknownDestinationPacket handles packets targeted at this protocol but 68 // that don't match any existing endpoint. 69 func (p *protocol) HandleUnknownDestinationPacket(r *stack.Route, id stack.TransportEndpointID, netHeader buffer.View, vv buffer.VectorisedView) bool { 70 // Get the header then trim it from the view. 71 hdr := header.UDP(vv.First()) 72 if int(hdr.Length()) > vv.Size() { 73 // Malformed packet. 74 r.Stack().Stats().UDP.MalformedPacketsReceived.Increment() 75 return true 76 } 77 // TODO(b/129426613): only send an ICMP message if UDP checksum is valid. 78 79 // Only send ICMP error if the address is not a multicast/broadcast 80 // v4/v6 address or the source is not the unspecified address. 81 // 82 // See: point e) in https://tools.ietf.org/html/rfc4443#section-2.4 83 if id.LocalAddress == header.IPv4Broadcast || header.IsV4MulticastAddress(id.LocalAddress) || header.IsV6MulticastAddress(id.LocalAddress) || id.RemoteAddress == header.IPv6Any || id.RemoteAddress == header.IPv4Any { 84 return true 85 } 86 87 // As per RFC: 1122 Section 3.2.2.1 A host SHOULD generate Destination 88 // Unreachable messages with code: 89 // 90 // 2 (Protocol Unreachable), when the designated transport protocol 91 // is not supported; or 92 // 93 // 3 (Port Unreachable), when the designated transport protocol 94 // (e.g., UDP) is unable to demultiplex the datagram but has no 95 // protocol mechanism to inform the sender. 96 switch len(id.LocalAddress) { 97 case header.IPv4AddressSize: 98 if !r.Stack().AllowICMPMessage() { 99 r.Stack().Stats().ICMP.V4PacketsSent.RateLimited.Increment() 100 return true 101 } 102 // As per RFC 1812 Section 4.3.2.3 103 // 104 // ICMP datagram SHOULD contain as much of the original 105 // datagram as possible without the length of the ICMP 106 // datagram exceeding 576 bytes 107 // 108 // NOTE: The above RFC referenced is different from the original 109 // recommendation in RFC 1122 where it mentioned that at least 8 110 // bytes of the payload must be included. Today linux and other 111 // systems implement the] RFC1812 definition and not the original 112 // RFC 1122 requirement. 113 mtu := int(r.MTU()) 114 if mtu > header.IPv4MinimumProcessableDatagramSize { 115 mtu = header.IPv4MinimumProcessableDatagramSize 116 } 117 headerLen := int(r.MaxHeaderLength()) + header.ICMPv4MinimumSize 118 available := int(mtu) - headerLen 119 payloadLen := len(netHeader) + vv.Size() 120 if payloadLen > available { 121 payloadLen = available 122 } 123 124 payload := buffer.NewVectorisedView(len(netHeader), []buffer.View{netHeader}) 125 payload.Append(vv) 126 payload.CapLength(payloadLen) 127 128 hdr := buffer.NewPrependable(headerLen) 129 pkt := header.ICMPv4(hdr.Prepend(header.ICMPv4MinimumSize)) 130 pkt.SetType(header.ICMPv4DstUnreachable) 131 pkt.SetCode(header.ICMPv4PortUnreachable) 132 pkt.SetChecksum(header.ICMPv4Checksum(pkt, payload)) 133 r.WritePacket(nil /* gso */, hdr, payload, header.ICMPv4ProtocolNumber, 0, true /* useDefaultTTL */) 134 135 case header.IPv6AddressSize: 136 if !r.Stack().AllowICMPMessage() { 137 r.Stack().Stats().ICMP.V6PacketsSent.RateLimited.Increment() 138 return true 139 } 140 141 // As per RFC 4443 section 2.4 142 // 143 // (c) Every ICMPv6 error message (type < 128) MUST include 144 // as much of the IPv6 offending (invoking) packet (the 145 // packet that caused the error) as possible without making 146 // the error message packet exceed the minimum IPv6 MTU 147 // [IPv6]. 148 mtu := int(r.MTU()) 149 if mtu > header.IPv6MinimumMTU { 150 mtu = header.IPv6MinimumMTU 151 } 152 headerLen := int(r.MaxHeaderLength()) + header.ICMPv6DstUnreachableMinimumSize 153 available := int(mtu) - headerLen 154 payloadLen := len(netHeader) + vv.Size() 155 if payloadLen > available { 156 payloadLen = available 157 } 158 payload := buffer.NewVectorisedView(len(netHeader), []buffer.View{netHeader}) 159 payload.Append(vv) 160 payload.CapLength(payloadLen) 161 162 hdr := buffer.NewPrependable(headerLen) 163 pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6DstUnreachableMinimumSize)) 164 pkt.SetType(header.ICMPv6DstUnreachable) 165 pkt.SetCode(header.ICMPv6PortUnreachable) 166 pkt.SetChecksum(header.ICMPv6Checksum(pkt, r.LocalAddress, r.RemoteAddress, payload)) 167 r.WritePacket(nil /* gso */, hdr, payload, header.ICMPv6ProtocolNumber, 0, true /* useDefaultTTL */) 168 } 169 return true 170 } 171 172 // SetOption implements TransportProtocol.SetOption. 173 func (p *protocol) SetOption(option interface{}) *tcpip.Error { 174 return tcpip.ErrUnknownProtocolOption 175 } 176 177 // Option implements TransportProtocol.Option. 178 func (p *protocol) Option(option interface{}) *tcpip.Error { 179 return tcpip.ErrUnknownProtocolOption 180 } 181 182 // NewProtocol returns a UDP transport protocol. 183 func NewProtocol() stack.TransportProtocol { 184 return &protocol{} 185 }