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