blob: e1bb1dc00fe6673891dd5a594193d1d640a41136 [file] [log] [blame]
Takahiro Suzuki241c10e2020-12-17 20:17:57 +09001// Copyright 2018 GoPacket Authors. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style license
4// that can be found in the LICENSE file in the root of the source
5// tree.
6
7package layers
8
9import (
10 "encoding/binary"
11 "errors"
12 "fmt"
13 "math"
14 "net"
15 "time"
16
17 "github.com/google/gopacket"
18)
19
20// MLDv1Message represents the common structure of all MLDv1 messages
21type MLDv1Message struct {
22 BaseLayer
23 // 3.4. Maximum Response Delay
24 MaximumResponseDelay time.Duration
25 // 3.6. Multicast Address
26 // Zero in general query
27 // Specific IPv6 multicast address otherwise
28 MulticastAddress net.IP
29}
30
31// DecodeFromBytes decodes the given bytes into this layer.
32func (m *MLDv1Message) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
33 if len(data) < 20 {
34 df.SetTruncated()
35 return errors.New("ICMP layer less than 20 bytes for Multicast Listener Query Message V1")
36 }
37
38 m.MaximumResponseDelay = time.Duration(binary.BigEndian.Uint16(data[0:2])) * time.Millisecond
39 // data[2:4] is reserved and not used in mldv1
40 m.MulticastAddress = data[4:20]
41
42 return nil
43}
44
45// NextLayerType returns the layer type contained by this DecodingLayer.
46func (*MLDv1Message) NextLayerType() gopacket.LayerType {
47 return gopacket.LayerTypeZero
48}
49
50// SerializeTo writes the serialized form of this layer into the
51// SerializationBuffer, implementing gopacket.SerializableLayer.
52// See the docs for gopacket.SerializableLayer for more info.
53func (m *MLDv1Message) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
54 buf, err := b.PrependBytes(20)
55 if err != nil {
56 return err
57 }
58
59 if m.MaximumResponseDelay < 0 {
60 return errors.New("maximum response delay must not be negative")
61 }
62 dms := m.MaximumResponseDelay / time.Millisecond
63 if dms > math.MaxUint16 {
64 return fmt.Errorf("maximum response delay %dms is more than the allowed 65535ms", dms)
65 }
66 binary.BigEndian.PutUint16(buf[0:2], uint16(dms))
67
68 copy(buf[2:4], []byte{0x0, 0x0})
69
70 ma16 := m.MulticastAddress.To16()
71 if ma16 == nil {
72 return fmt.Errorf("invalid multicast address '%s'", m.MulticastAddress)
73 }
74 copy(buf[4:20], ma16)
75
76 return nil
77}
78
79// Sums this layer up nicely formatted
80func (m *MLDv1Message) String() string {
81 return fmt.Sprintf(
82 "Maximum Response Delay: %dms, Multicast Address: %s",
83 m.MaximumResponseDelay/time.Millisecond,
84 m.MulticastAddress)
85}
86
87// MLDv1MulticastListenerQueryMessage are sent by the router to determine
88// whether there are multicast listeners on the link.
89// https://tools.ietf.org/html/rfc2710 Page 5
90type MLDv1MulticastListenerQueryMessage struct {
91 MLDv1Message
92}
93
94// DecodeFromBytes decodes the given bytes into this layer.
95func (m *MLDv1MulticastListenerQueryMessage) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
96 err := m.MLDv1Message.DecodeFromBytes(data, df)
97 if err != nil {
98 return err
99 }
100
101 if len(data) > 20 {
102 m.Payload = data[20:]
103 }
104
105 return nil
106}
107
108// LayerType returns LayerTypeMLDv1MulticastListenerQuery.
109func (*MLDv1MulticastListenerQueryMessage) LayerType() gopacket.LayerType {
110 return LayerTypeMLDv1MulticastListenerQuery
111}
112
113// CanDecode returns the set of layer types that this DecodingLayer can decode.
114func (*MLDv1MulticastListenerQueryMessage) CanDecode() gopacket.LayerClass {
115 return LayerTypeMLDv1MulticastListenerQuery
116}
117
118// IsGeneralQuery is true when this is a general query.
119// In a Query message, the Multicast Address field is set to zero when
120// sending a General Query.
121// https://tools.ietf.org/html/rfc2710#section-3.6
122func (m *MLDv1MulticastListenerQueryMessage) IsGeneralQuery() bool {
123 return net.IPv6zero.Equal(m.MulticastAddress)
124}
125
126// IsSpecificQuery is true when this is not a general query.
127// In a Query message, the Multicast Address field is set to a specific
128// IPv6 multicast address when sending a Multicast-Address-Specific Query.
129// https://tools.ietf.org/html/rfc2710#section-3.6
130func (m *MLDv1MulticastListenerQueryMessage) IsSpecificQuery() bool {
131 return !m.IsGeneralQuery()
132}
133
134// MLDv1MulticastListenerReportMessage is sent by a client listening on
135// a specific multicast address to indicate that it is (still) listening
136// on the specific multicast address.
137// https://tools.ietf.org/html/rfc2710 Page 6
138type MLDv1MulticastListenerReportMessage struct {
139 MLDv1Message
140}
141
142// LayerType returns LayerTypeMLDv1MulticastListenerReport.
143func (*MLDv1MulticastListenerReportMessage) LayerType() gopacket.LayerType {
144 return LayerTypeMLDv1MulticastListenerReport
145}
146
147// CanDecode returns the set of layer types that this DecodingLayer can decode.
148func (*MLDv1MulticastListenerReportMessage) CanDecode() gopacket.LayerClass {
149 return LayerTypeMLDv1MulticastListenerReport
150}
151
152// MLDv1MulticastListenerDoneMessage should be sent by a client when it ceases
153// to listen to a multicast address on an interface.
154// https://tools.ietf.org/html/rfc2710 Page 7
155type MLDv1MulticastListenerDoneMessage struct {
156 MLDv1Message
157}
158
159// LayerType returns LayerTypeMLDv1MulticastListenerDone.
160func (*MLDv1MulticastListenerDoneMessage) LayerType() gopacket.LayerType {
161 return LayerTypeMLDv1MulticastListenerDone
162}
163
164// CanDecode returns the set of layer types that this DecodingLayer can decode.
165func (*MLDv1MulticastListenerDoneMessage) CanDecode() gopacket.LayerClass {
166 return LayerTypeMLDv1MulticastListenerDone
167}
168
169func decodeMLDv1MulticastListenerReport(data []byte, p gopacket.PacketBuilder) error {
170 m := &MLDv1MulticastListenerReportMessage{}
171 return decodingLayerDecoder(m, data, p)
172}
173
174func decodeMLDv1MulticastListenerQuery(data []byte, p gopacket.PacketBuilder) error {
175 m := &MLDv1MulticastListenerQueryMessage{}
176 return decodingLayerDecoder(m, data, p)
177}
178
179func decodeMLDv1MulticastListenerDone(data []byte, p gopacket.PacketBuilder) error {
180 m := &MLDv1MulticastListenerDoneMessage{}
181 return decodingLayerDecoder(m, data, p)
182}