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 }