github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/tcpip/header/mld.go (about)

     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  	"github.com/nicocha30/gvisor-ligolo/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  }