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  }