blob: d9268db0563f6ba5ce1cdf0964e1976b323a5aae [file] [log] [blame]
Holger Hildebrandtfa074992020-03-27 15:42:06 +00001// Copyright 2012 Google, Inc. All rights reserved.
2// Copyright 2009-2011 Andreas Krennmair. All rights reserved.
3//
4// Use of this source code is governed by a BSD-style license
5// that can be found in the LICENSE file in the root of the source
6// tree.
7
8package layers
9
10import (
11 "encoding/binary"
12 "encoding/hex"
13 "errors"
14 "fmt"
15 "net"
16 "time"
17
18 "github.com/google/gopacket"
19)
20
21// Based on RFC 4861
22
23// ICMPv6Opt indicate how to decode the data associated with each ICMPv6Option.
24type ICMPv6Opt uint8
25
26const (
27 _ ICMPv6Opt = iota
28
29 // ICMPv6OptSourceAddress contains the link-layer address of the sender of
30 // the packet. It is used in the Neighbor Solicitation, Router
31 // Solicitation, and Router Advertisement packets. Must be ignored for other
32 // Neighbor discovery messages.
33 ICMPv6OptSourceAddress
34
35 // ICMPv6OptTargetAddress contains the link-layer address of the target. It
36 // is used in Neighbor Advertisement and Redirect packets. Must be ignored
37 // for other Neighbor discovery messages.
38 ICMPv6OptTargetAddress
39
40 // ICMPv6OptPrefixInfo provides hosts with on-link prefixes and prefixes
41 // for Address Autoconfiguration. The Prefix Information option appears in
42 // Router Advertisement packets and MUST be silently ignored for other
43 // messages.
44 ICMPv6OptPrefixInfo
45
46 // ICMPv6OptRedirectedHeader is used in Redirect messages and contains all
47 // or part of the packet that is being redirected.
48 ICMPv6OptRedirectedHeader
49
50 // ICMPv6OptMTU is used in Router Advertisement messages to ensure that all
51 // nodes on a link use the same MTU value in those cases where the link MTU
52 // is not well known. This option MUST be silently ignored for other
53 // Neighbor Discovery messages.
54 ICMPv6OptMTU
55)
56
57// ICMPv6Echo represents the structure of a ping.
58type ICMPv6Echo struct {
59 BaseLayer
60 Identifier uint16
61 SeqNumber uint16
62}
63
64// ICMPv6RouterSolicitation is sent by hosts to find routers.
65type ICMPv6RouterSolicitation struct {
66 BaseLayer
67 Options ICMPv6Options
68}
69
70// ICMPv6RouterAdvertisement is sent by routers in response to Solicitation.
71type ICMPv6RouterAdvertisement struct {
72 BaseLayer
73 HopLimit uint8
74 Flags uint8
75 RouterLifetime uint16
76 ReachableTime uint32
77 RetransTimer uint32
78 Options ICMPv6Options
79}
80
81// ICMPv6NeighborSolicitation is sent to request the link-layer address of a
82// target node.
83type ICMPv6NeighborSolicitation struct {
84 BaseLayer
85 TargetAddress net.IP
86 Options ICMPv6Options
87}
88
89// ICMPv6NeighborAdvertisement is sent by nodes in response to Solicitation.
90type ICMPv6NeighborAdvertisement struct {
91 BaseLayer
92 Flags uint8
93 TargetAddress net.IP
94 Options ICMPv6Options
95}
96
97// ICMPv6Redirect is sent by routers to inform hosts of a better first-hop node
98// on the path to a destination.
99type ICMPv6Redirect struct {
100 BaseLayer
101 TargetAddress net.IP
102 DestinationAddress net.IP
103 Options ICMPv6Options
104}
105
106// ICMPv6Option contains the type and data for a single option.
107type ICMPv6Option struct {
108 Type ICMPv6Opt
109 Data []byte
110}
111
112// ICMPv6Options is a slice of ICMPv6Option.
113type ICMPv6Options []ICMPv6Option
114
115func (i ICMPv6Opt) String() string {
116 switch i {
117 case ICMPv6OptSourceAddress:
118 return "SourceAddress"
119 case ICMPv6OptTargetAddress:
120 return "TargetAddress"
121 case ICMPv6OptPrefixInfo:
122 return "PrefixInfo"
123 case ICMPv6OptRedirectedHeader:
124 return "RedirectedHeader"
125 case ICMPv6OptMTU:
126 return "MTU"
127 default:
128 return fmt.Sprintf("Unknown(%d)", i)
129 }
130}
131
132// CanDecode returns the set of layer types that this DecodingLayer can decode.
133func (i *ICMPv6Echo) CanDecode() gopacket.LayerClass {
134 return LayerTypeICMPv6Echo
135}
136
137// LayerType returns LayerTypeICMPv6Echo.
138func (i *ICMPv6Echo) LayerType() gopacket.LayerType {
139 return LayerTypeICMPv6Echo
140}
141
142// NextLayerType returns the layer type contained by this DecodingLayer.
143func (i *ICMPv6Echo) NextLayerType() gopacket.LayerType {
144 return gopacket.LayerTypePayload
145}
146
147// DecodeFromBytes decodes the given bytes into this layer.
148func (i *ICMPv6Echo) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
149 if len(data) < 4 {
150 df.SetTruncated()
151 return errors.New("ICMP layer less then 4 bytes for ICMPv6 Echo")
152 }
153 i.Identifier = binary.BigEndian.Uint16(data[0:2])
154 i.SeqNumber = binary.BigEndian.Uint16(data[2:4])
155
156 return nil
157}
158
159// SerializeTo writes the serialized form of this layer into the
160// SerializationBuffer, implementing gopacket.SerializableLayer.
161// See the docs for gopacket.SerializableLayer for more info.
162func (i *ICMPv6Echo) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
163 buf, err := b.PrependBytes(4)
164 if err != nil {
165 return err
166 }
167
168 binary.BigEndian.PutUint16(buf, i.Identifier)
169 binary.BigEndian.PutUint16(buf[2:], i.SeqNumber)
170 return nil
171}
172
173// LayerType returns LayerTypeICMPv6.
174func (i *ICMPv6RouterSolicitation) LayerType() gopacket.LayerType {
175 return LayerTypeICMPv6RouterSolicitation
176}
177
178// NextLayerType returns the layer type contained by this DecodingLayer.
179func (i *ICMPv6RouterSolicitation) NextLayerType() gopacket.LayerType {
180 return gopacket.LayerTypePayload
181}
182
183// DecodeFromBytes decodes the given bytes into this layer.
184func (i *ICMPv6RouterSolicitation) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
185 // first 4 bytes are reserved followed by options
186 if len(data) < 4 {
187 df.SetTruncated()
188 return errors.New("ICMP layer less then 4 bytes for ICMPv6 router solicitation")
189 }
190
191 // truncate old options
192 i.Options = i.Options[:0]
193
194 return i.Options.DecodeFromBytes(data[4:], df)
195}
196
197// SerializeTo writes the serialized form of this layer into the
198// SerializationBuffer, implementing gopacket.SerializableLayer.
199// See the docs for gopacket.SerializableLayer for more info.
200func (i *ICMPv6RouterSolicitation) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
201 if err := i.Options.SerializeTo(b, opts); err != nil {
202 return err
203 }
204
205 buf, err := b.PrependBytes(4)
206 if err != nil {
207 return err
208 }
209
210 copy(buf, lotsOfZeros[:4])
211 return nil
212}
213
214// CanDecode returns the set of layer types that this DecodingLayer can decode.
215func (i *ICMPv6RouterSolicitation) CanDecode() gopacket.LayerClass {
216 return LayerTypeICMPv6RouterSolicitation
217}
218
219// LayerType returns LayerTypeICMPv6RouterAdvertisement.
220func (i *ICMPv6RouterAdvertisement) LayerType() gopacket.LayerType {
221 return LayerTypeICMPv6RouterAdvertisement
222}
223
224// NextLayerType returns the layer type contained by this DecodingLayer.
225func (i *ICMPv6RouterAdvertisement) NextLayerType() gopacket.LayerType {
226 return gopacket.LayerTypePayload
227}
228
229// DecodeFromBytes decodes the given bytes into this layer.
230func (i *ICMPv6RouterAdvertisement) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
231 if len(data) < 12 {
232 df.SetTruncated()
233 return errors.New("ICMP layer less then 12 bytes for ICMPv6 router advertisement")
234 }
235
236 i.HopLimit = uint8(data[0])
237 // M, O bit followed by 6 reserved bits
238 i.Flags = uint8(data[1])
239 i.RouterLifetime = binary.BigEndian.Uint16(data[2:4])
240 i.ReachableTime = binary.BigEndian.Uint32(data[4:8])
241 i.RetransTimer = binary.BigEndian.Uint32(data[8:12])
242 i.BaseLayer = BaseLayer{data, nil} // assume no payload
243
244 // truncate old options
245 i.Options = i.Options[:0]
246
247 return i.Options.DecodeFromBytes(data[12:], df)
248}
249
250// SerializeTo writes the serialized form of this layer into the
251// SerializationBuffer, implementing gopacket.SerializableLayer.
252// See the docs for gopacket.SerializableLayer for more info.
253func (i *ICMPv6RouterAdvertisement) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
254 if err := i.Options.SerializeTo(b, opts); err != nil {
255 return err
256 }
257
258 buf, err := b.PrependBytes(12)
259 if err != nil {
260 return err
261 }
262
263 buf[0] = byte(i.HopLimit)
264 buf[1] = byte(i.Flags)
265 binary.BigEndian.PutUint16(buf[2:], i.RouterLifetime)
266 binary.BigEndian.PutUint32(buf[4:], i.ReachableTime)
267 binary.BigEndian.PutUint32(buf[8:], i.RetransTimer)
268 return nil
269}
270
271// CanDecode returns the set of layer types that this DecodingLayer can decode.
272func (i *ICMPv6RouterAdvertisement) CanDecode() gopacket.LayerClass {
273 return LayerTypeICMPv6RouterAdvertisement
274}
275
276// ManagedAddressConfig is true when addresses are available via DHCPv6. If
277// set, the OtherConfig flag is redundant.
278func (i *ICMPv6RouterAdvertisement) ManagedAddressConfig() bool {
279 return i.Flags&0x80 != 0
280}
281
282// OtherConfig is true when there is other configuration information available
283// via DHCPv6. For example, DNS-related information.
284func (i *ICMPv6RouterAdvertisement) OtherConfig() bool {
285 return i.Flags&0x40 != 0
286}
287
288// LayerType returns LayerTypeICMPv6NeighborSolicitation.
289func (i *ICMPv6NeighborSolicitation) LayerType() gopacket.LayerType {
290 return LayerTypeICMPv6NeighborSolicitation
291}
292
293// NextLayerType returns the layer type contained by this DecodingLayer.
294func (i *ICMPv6NeighborSolicitation) NextLayerType() gopacket.LayerType {
295 return gopacket.LayerTypePayload
296}
297
298// DecodeFromBytes decodes the given bytes into this layer.
299func (i *ICMPv6NeighborSolicitation) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
300 if len(data) < 20 {
301 df.SetTruncated()
302 return errors.New("ICMP layer less then 20 bytes for ICMPv6 neighbor solicitation")
303 }
304
305 i.TargetAddress = net.IP(data[4:20])
306 i.BaseLayer = BaseLayer{data, nil} // assume no payload
307
308 // truncate old options
309 i.Options = i.Options[:0]
310
311 return i.Options.DecodeFromBytes(data[20:], df)
312}
313
314// SerializeTo writes the serialized form of this layer into the
315// SerializationBuffer, implementing gopacket.SerializableLayer.
316// See the docs for gopacket.SerializableLayer for more info.
317func (i *ICMPv6NeighborSolicitation) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
318 if err := i.Options.SerializeTo(b, opts); err != nil {
319 return err
320 }
321
322 buf, err := b.PrependBytes(20)
323 if err != nil {
324 return err
325 }
326
327 copy(buf, lotsOfZeros[:4])
328 copy(buf[4:], i.TargetAddress)
329 return nil
330}
331
332// CanDecode returns the set of layer types that this DecodingLayer can decode.
333func (i *ICMPv6NeighborSolicitation) CanDecode() gopacket.LayerClass {
334 return LayerTypeICMPv6NeighborSolicitation
335}
336
337// LayerType returns LayerTypeICMPv6NeighborAdvertisement.
338func (i *ICMPv6NeighborAdvertisement) LayerType() gopacket.LayerType {
339 return LayerTypeICMPv6NeighborAdvertisement
340}
341
342// NextLayerType returns the layer type contained by this DecodingLayer.
343func (i *ICMPv6NeighborAdvertisement) NextLayerType() gopacket.LayerType {
344 return gopacket.LayerTypePayload
345}
346
347// DecodeFromBytes decodes the given bytes into this layer.
348func (i *ICMPv6NeighborAdvertisement) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
349 if len(data) < 20 {
350 df.SetTruncated()
351 return errors.New("ICMP layer less then 20 bytes for ICMPv6 neighbor advertisement")
352 }
353
354 i.Flags = uint8(data[0])
355 i.TargetAddress = net.IP(data[4:20])
356 i.BaseLayer = BaseLayer{data, nil} // assume no payload
357
358 // truncate old options
359 i.Options = i.Options[:0]
360
361 return i.Options.DecodeFromBytes(data[20:], df)
362}
363
364// SerializeTo writes the serialized form of this layer into the
365// SerializationBuffer, implementing gopacket.SerializableLayer.
366// See the docs for gopacket.SerializableLayer for more info.
367func (i *ICMPv6NeighborAdvertisement) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
368 if err := i.Options.SerializeTo(b, opts); err != nil {
369 return err
370 }
371
372 buf, err := b.PrependBytes(20)
373 if err != nil {
374 return err
375 }
376
377 buf[0] = byte(i.Flags)
378 copy(buf[1:], lotsOfZeros[:3])
379 copy(buf[4:], i.TargetAddress)
380 return nil
381}
382
383// CanDecode returns the set of layer types that this DecodingLayer can decode.
384func (i *ICMPv6NeighborAdvertisement) CanDecode() gopacket.LayerClass {
385 return LayerTypeICMPv6NeighborAdvertisement
386}
387
388// Router indicates whether the sender is a router or not.
389func (i *ICMPv6NeighborAdvertisement) Router() bool {
390 return i.Flags&0x80 != 0
391}
392
393// Solicited indicates whether the advertisement was solicited or not.
394func (i *ICMPv6NeighborAdvertisement) Solicited() bool {
395 return i.Flags&0x40 != 0
396}
397
398// Override indicates whether the advertisement should Override an existing
399// cache entry.
400func (i *ICMPv6NeighborAdvertisement) Override() bool {
401 return i.Flags&0x20 != 0
402}
403
404// LayerType returns LayerTypeICMPv6Redirect.
405func (i *ICMPv6Redirect) LayerType() gopacket.LayerType {
406 return LayerTypeICMPv6Redirect
407}
408
409// NextLayerType returns the layer type contained by this DecodingLayer.
410func (i *ICMPv6Redirect) NextLayerType() gopacket.LayerType {
411 return gopacket.LayerTypePayload
412}
413
414// DecodeFromBytes decodes the given bytes into this layer.
415func (i *ICMPv6Redirect) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
416 if len(data) < 36 {
417 df.SetTruncated()
418 return errors.New("ICMP layer less then 36 bytes for ICMPv6 redirect")
419 }
420
421 i.TargetAddress = net.IP(data[4:20])
422 i.DestinationAddress = net.IP(data[20:36])
423 i.BaseLayer = BaseLayer{data, nil} // assume no payload
424
425 // truncate old options
426 i.Options = i.Options[:0]
427
428 return i.Options.DecodeFromBytes(data[36:], df)
429}
430
431// SerializeTo writes the serialized form of this layer into the
432// SerializationBuffer, implementing gopacket.SerializableLayer.
433// See the docs for gopacket.SerializableLayer for more info.
434func (i *ICMPv6Redirect) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
435 if err := i.Options.SerializeTo(b, opts); err != nil {
436 return err
437 }
438
439 buf, err := b.PrependBytes(36)
440 if err != nil {
441 return err
442 }
443
444 copy(buf, lotsOfZeros[:4])
445 copy(buf[4:], i.TargetAddress)
446 copy(buf[20:], i.DestinationAddress)
447 return nil
448}
449
450// CanDecode returns the set of layer types that this DecodingLayer can decode.
451func (i *ICMPv6Redirect) CanDecode() gopacket.LayerClass {
452 return LayerTypeICMPv6Redirect
453}
454
455func (i ICMPv6Option) String() string {
456 hd := hex.EncodeToString(i.Data)
457 if len(hd) > 0 {
458 hd = " 0x" + hd
459 }
460
461 switch i.Type {
462 case ICMPv6OptSourceAddress, ICMPv6OptTargetAddress:
463 return fmt.Sprintf("ICMPv6Option(%s:%v)",
464 i.Type,
465 net.HardwareAddr(i.Data))
466 case ICMPv6OptPrefixInfo:
467 if len(i.Data) == 30 {
468 prefixLen := uint8(i.Data[0])
469 onLink := (i.Data[1]&0x80 != 0)
470 autonomous := (i.Data[1]&0x40 != 0)
471 validLifetime := time.Duration(binary.BigEndian.Uint32(i.Data[2:6])) * time.Second
472 preferredLifetime := time.Duration(binary.BigEndian.Uint32(i.Data[6:10])) * time.Second
473
474 prefix := net.IP(i.Data[14:])
475
476 return fmt.Sprintf("ICMPv6Option(%s:%v/%v:%t:%t:%v:%v)",
477 i.Type,
478 prefix, prefixLen,
479 onLink, autonomous,
480 validLifetime, preferredLifetime)
481 }
482 case ICMPv6OptRedirectedHeader:
483 // could invoke IP decoder on data... probably best not to
484 break
485 case ICMPv6OptMTU:
486 if len(i.Data) == 6 {
487 return fmt.Sprintf("ICMPv6Option(%s:%v)",
488 i.Type,
489 binary.BigEndian.Uint32(i.Data[2:]))
490 }
491
492 }
493 return fmt.Sprintf("ICMPv6Option(%s:%s)", i.Type, hd)
494}
495
496// DecodeFromBytes decodes the given bytes into this layer.
497func (i *ICMPv6Options) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
498 for len(data) > 0 {
499 if len(data) < 2 {
500 df.SetTruncated()
501 return errors.New("ICMP layer less then 2 bytes for ICMPv6 message option")
502 }
503
504 // unit is 8 octets, convert to bytes
505 length := int(data[1]) * 8
506
507 if length == 0 {
508 df.SetTruncated()
509 return errors.New("ICMPv6 message option with length 0")
510 }
511
512 if len(data) < length {
513 df.SetTruncated()
514 return fmt.Errorf("ICMP layer only %v bytes for ICMPv6 message option with length %v", len(data), length)
515 }
516
517 o := ICMPv6Option{
518 Type: ICMPv6Opt(data[0]),
519 Data: data[2:length],
520 }
521
522 // chop off option we just consumed
523 data = data[length:]
524
525 *i = append(*i, o)
526 }
527
528 return nil
529}
530
531// SerializeTo writes the serialized form of this layer into the
532// SerializationBuffer, implementing gopacket.SerializableLayer.
533// See the docs for gopacket.SerializableLayer for more info.
534func (i *ICMPv6Options) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
535 for _, opt := range []ICMPv6Option(*i) {
536 length := len(opt.Data) + 2
537 buf, err := b.PrependBytes(length)
538 if err != nil {
539 return err
540 }
541
542 buf[0] = byte(opt.Type)
543 buf[1] = byte(length / 8)
544 copy(buf[2:], opt.Data)
545 }
546
547 return nil
548}
549
550func decodeICMPv6Echo(data []byte, p gopacket.PacketBuilder) error {
551 i := &ICMPv6Echo{}
552 return decodingLayerDecoder(i, data, p)
553}
554
555func decodeICMPv6RouterSolicitation(data []byte, p gopacket.PacketBuilder) error {
556 i := &ICMPv6RouterSolicitation{}
557 return decodingLayerDecoder(i, data, p)
558}
559
560func decodeICMPv6RouterAdvertisement(data []byte, p gopacket.PacketBuilder) error {
561 i := &ICMPv6RouterAdvertisement{}
562 return decodingLayerDecoder(i, data, p)
563}
564
565func decodeICMPv6NeighborSolicitation(data []byte, p gopacket.PacketBuilder) error {
566 i := &ICMPv6NeighborSolicitation{}
567 return decodingLayerDecoder(i, data, p)
568}
569
570func decodeICMPv6NeighborAdvertisement(data []byte, p gopacket.PacketBuilder) error {
571 i := &ICMPv6NeighborAdvertisement{}
572 return decodingLayerDecoder(i, data, p)
573}
574
575func decodeICMPv6Redirect(data []byte, p gopacket.PacketBuilder) error {
576 i := &ICMPv6Redirect{}
577 return decodingLayerDecoder(i, data, p)
578}