github.com/vpnishe/netstack@v1.10.6/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/vpnishe/netstack/tcpip" 25 "github.com/vpnishe/netstack/tcpip/buffer" 26 "github.com/vpnishe/netstack/tcpip/header" 27 "github.com/vpnishe/netstack/tcpip/stack" 28 "github.com/vpnishe/netstack/tcpip/transport/raw" 29 "github.com/vpnishe/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, pkt tcpip.PacketBuffer) bool { 70 // Get the header then trim it from the view. 71 hdr := header.UDP(pkt.Data.First()) 72 if int(hdr.Length()) > pkt.Data.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(pkt.NetworkHeader) + pkt.Data.Size() 120 if payloadLen > available { 121 payloadLen = available 122 } 123 124 // The buffers used by pkt may be used elsewhere in the system. 125 // For example, a raw or packet socket may use what UDP 126 // considers an unreachable destination. Thus we deep copy pkt 127 // to prevent multiple ownership and SR errors. 128 newNetHeader := append(buffer.View(nil), pkt.NetworkHeader...) 129 payload := newNetHeader.ToVectorisedView() 130 payload.Append(pkt.Data.ToView().ToVectorisedView()) 131 payload.CapLength(payloadLen) 132 133 hdr := buffer.NewPrependable(headerLen) 134 pkt := header.ICMPv4(hdr.Prepend(header.ICMPv4MinimumSize)) 135 pkt.SetType(header.ICMPv4DstUnreachable) 136 pkt.SetCode(header.ICMPv4PortUnreachable) 137 pkt.SetChecksum(header.ICMPv4Checksum(pkt, payload)) 138 r.WritePacket(nil /* gso */, stack.NetworkHeaderParams{Protocol: header.ICMPv4ProtocolNumber, TTL: r.DefaultTTL(), TOS: stack.DefaultTOS}, tcpip.PacketBuffer{ 139 Header: hdr, 140 Data: payload, 141 }) 142 143 case header.IPv6AddressSize: 144 if !r.Stack().AllowICMPMessage() { 145 r.Stack().Stats().ICMP.V6PacketsSent.RateLimited.Increment() 146 return true 147 } 148 149 // As per RFC 4443 section 2.4 150 // 151 // (c) Every ICMPv6 error message (type < 128) MUST include 152 // as much of the IPv6 offending (invoking) packet (the 153 // packet that caused the error) as possible without making 154 // the error message packet exceed the minimum IPv6 MTU 155 // [IPv6]. 156 mtu := int(r.MTU()) 157 if mtu > header.IPv6MinimumMTU { 158 mtu = header.IPv6MinimumMTU 159 } 160 headerLen := int(r.MaxHeaderLength()) + header.ICMPv6DstUnreachableMinimumSize 161 available := int(mtu) - headerLen 162 payloadLen := len(pkt.NetworkHeader) + pkt.Data.Size() 163 if payloadLen > available { 164 payloadLen = available 165 } 166 payload := buffer.NewVectorisedView(len(pkt.NetworkHeader), []buffer.View{pkt.NetworkHeader}) 167 payload.Append(pkt.Data) 168 payload.CapLength(payloadLen) 169 170 hdr := buffer.NewPrependable(headerLen) 171 pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6DstUnreachableMinimumSize)) 172 pkt.SetType(header.ICMPv6DstUnreachable) 173 pkt.SetCode(header.ICMPv6PortUnreachable) 174 pkt.SetChecksum(header.ICMPv6Checksum(pkt, r.LocalAddress, r.RemoteAddress, payload)) 175 r.WritePacket(nil /* gso */, stack.NetworkHeaderParams{Protocol: header.ICMPv6ProtocolNumber, TTL: r.DefaultTTL(), TOS: stack.DefaultTOS}, tcpip.PacketBuffer{ 176 Header: hdr, 177 Data: payload, 178 }) 179 } 180 return true 181 } 182 183 // SetOption implements TransportProtocol.SetOption. 184 func (p *protocol) SetOption(option interface{}) *tcpip.Error { 185 return tcpip.ErrUnknownProtocolOption 186 } 187 188 // Option implements TransportProtocol.Option. 189 func (p *protocol) Option(option interface{}) *tcpip.Error { 190 return tcpip.ErrUnknownProtocolOption 191 } 192 193 // NewProtocol returns a UDP transport protocol. 194 func NewProtocol() stack.TransportProtocol { 195 return &protocol{} 196 }