mld.go raw

   1  // Copyright 2020 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 header
  16  
  17  import (
  18  	"encoding/binary"
  19  	"fmt"
  20  	"time"
  21  
  22  	"gvisor.dev/gvisor/pkg/tcpip"
  23  )
  24  
  25  const (
  26  	// MLDMinimumSize is the minimum size for an MLD message.
  27  	MLDMinimumSize = 20
  28  
  29  	// MLDHopLimit is the Hop Limit for all IPv6 packets with an MLD message, as
  30  	// per RFC 2710 section 3.
  31  	MLDHopLimit = 1
  32  
  33  	// mldMaximumResponseDelayOffset is the offset to the Maximum Response Delay
  34  	// field within MLD.
  35  	mldMaximumResponseDelayOffset = 0
  36  
  37  	// mldMulticastAddressOffset is the offset to the Multicast Address field
  38  	// within MLD.
  39  	mldMulticastAddressOffset = 4
  40  )
  41  
  42  // MLD is a Multicast Listener Discovery message in an ICMPv6 packet.
  43  //
  44  // MLD will only contain the body of an ICMPv6 packet.
  45  //
  46  // As per RFC 2710 section 3, MLD messages have the following format (MLD only
  47  // holds the bytes after the first four bytes in the diagram below):
  48  //
  49  //	 0                   1                   2                   3
  50  //	 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  51  //	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  52  //	|     Type      |     Code      |          Checksum             |
  53  //	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  54  //	|     Maximum Response Delay    |          Reserved             |
  55  //	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  56  //	|                                                               |
  57  //	+                                                               +
  58  //	|                                                               |
  59  //	+                       Multicast Address                       +
  60  //	|                                                               |
  61  //	+                                                               +
  62  //	|                                                               |
  63  //	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  64  type MLD []byte
  65  
  66  // MaximumResponseDelay returns the Maximum Response Delay.
  67  func (m MLD) MaximumResponseDelay() time.Duration {
  68  	// As per RFC 2710 section 3.4:
  69  	//
  70  	//   The Maximum Response Delay field is meaningful only in Query
  71  	//   messages, and specifies the maximum allowed delay before sending a
  72  	//   responding Report, in units of milliseconds. In all other messages,
  73  	//   it is set to zero by the sender and ignored by receivers.
  74  	return time.Duration(binary.BigEndian.Uint16(m[mldMaximumResponseDelayOffset:])) * time.Millisecond
  75  }
  76  
  77  // SetMaximumResponseDelay sets the Maximum Response Delay field.
  78  //
  79  // maxRespDelayMS is the value in milliseconds.
  80  func (m MLD) SetMaximumResponseDelay(maxRespDelayMS uint16) {
  81  	binary.BigEndian.PutUint16(m[mldMaximumResponseDelayOffset:], maxRespDelayMS)
  82  }
  83  
  84  // MulticastAddress returns the Multicast Address.
  85  func (m MLD) MulticastAddress() tcpip.Address {
  86  	// As per RFC 2710 section 3.5:
  87  	//
  88  	//   In a Query message, the Multicast Address field is set to zero when
  89  	//   sending a General Query, and set to a specific IPv6 multicast address
  90  	//   when sending a Multicast-Address-Specific Query.
  91  	//
  92  	//   In a Report or Done message, the Multicast Address field holds a
  93  	//   specific IPv6 multicast address to which the message sender is
  94  	//   listening or is ceasing to listen, respectively.
  95  	return tcpip.AddrFrom16([16]byte(m[mldMulticastAddressOffset:][:IPv6AddressSize]))
  96  }
  97  
  98  // SetMulticastAddress sets the Multicast Address field.
  99  func (m MLD) SetMulticastAddress(multicastAddress tcpip.Address) {
 100  	if n := copy(m[mldMulticastAddressOffset:], multicastAddress.AsSlice()); n != IPv6AddressSize {
 101  		panic(fmt.Sprintf("copied %d bytes, expected to copy %d bytes", n, IPv6AddressSize))
 102  	}
 103  }
 104