1 // Copyright 2019 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 "bytes"
19 "encoding/binary"
20 "errors"
21 "fmt"
22 "io"
23 "math"
24 "time"
25 26 "gvisor.dev/gvisor/pkg/tcpip"
27 )
28 29 // ndpOptionIdentifier is an NDP option type identifier.
30 type ndpOptionIdentifier uint8
31 32 const (
33 // ndpSourceLinkLayerAddressOptionType is the type of the Source Link Layer
34 // Address option, as per RFC 4861 section 4.6.1.
35 ndpSourceLinkLayerAddressOptionType ndpOptionIdentifier = 1
36 37 // ndpTargetLinkLayerAddressOptionType is the type of the Target Link Layer
38 // Address option, as per RFC 4861 section 4.6.1.
39 ndpTargetLinkLayerAddressOptionType ndpOptionIdentifier = 2
40 41 // ndpPrefixInformationType is the type of the Prefix Information
42 // option, as per RFC 4861 section 4.6.2.
43 ndpPrefixInformationType ndpOptionIdentifier = 3
44 45 // ndpNonceOptionType is the type of the Nonce option, as per
46 // RFC 3971 section 5.3.2.
47 ndpNonceOptionType ndpOptionIdentifier = 14
48 49 // ndpRecursiveDNSServerOptionType is the type of the Recursive DNS
50 // Server option, as per RFC 8106 section 5.1.
51 ndpRecursiveDNSServerOptionType ndpOptionIdentifier = 25
52 53 // ndpDNSSearchListOptionType is the type of the DNS Search List option,
54 // as per RFC 8106 section 5.2.
55 ndpDNSSearchListOptionType ndpOptionIdentifier = 31
56 )
57 58 const (
59 // NDPLinkLayerAddressSize is the size of a Source or Target Link Layer
60 // Address option for an Ethernet address.
61 NDPLinkLayerAddressSize = 8
62 63 // ndpPrefixInformationLength is the expected length, in bytes, of the
64 // body of an NDP Prefix Information option, as per RFC 4861 section
65 // 4.6.2 which specifies that the Length field is 4. Given this, the
66 // expected length, in bytes, is 30 because 4 * lengthByteUnits (8) - 2
67 // (Type & Length) = 30.
68 ndpPrefixInformationLength = 30
69 70 // ndpPrefixInformationPrefixLengthOffset is the offset of the Prefix
71 // Length field within an NDPPrefixInformation.
72 ndpPrefixInformationPrefixLengthOffset = 0
73 74 // ndpPrefixInformationFlagsOffset is the offset of the flags byte
75 // within an NDPPrefixInformation.
76 ndpPrefixInformationFlagsOffset = 1
77 78 // ndpPrefixInformationOnLinkFlagMask is the mask of the On-Link Flag
79 // field in the flags byte within an NDPPrefixInformation.
80 ndpPrefixInformationOnLinkFlagMask = 1 << 7
81 82 // ndpPrefixInformationAutoAddrConfFlagMask is the mask of the
83 // Autonomous Address-Configuration flag field in the flags byte within
84 // an NDPPrefixInformation.
85 ndpPrefixInformationAutoAddrConfFlagMask = 1 << 6
86 87 // ndpPrefixInformationReserved1FlagsMask is the mask of the Reserved1
88 // field in the flags byte within an NDPPrefixInformation.
89 ndpPrefixInformationReserved1FlagsMask = 63
90 91 // ndpPrefixInformationValidLifetimeOffset is the start of the 4-byte
92 // Valid Lifetime field within an NDPPrefixInformation.
93 ndpPrefixInformationValidLifetimeOffset = 2
94 95 // ndpPrefixInformationPreferredLifetimeOffset is the start of the
96 // 4-byte Preferred Lifetime field within an NDPPrefixInformation.
97 ndpPrefixInformationPreferredLifetimeOffset = 6
98 99 // ndpPrefixInformationReserved2Offset is the start of the 4-byte
100 // Reserved2 field within an NDPPrefixInformation.
101 ndpPrefixInformationReserved2Offset = 10
102 103 // ndpPrefixInformationReserved2Length is the length of the Reserved2
104 // field.
105 //
106 // It is 4 bytes.
107 ndpPrefixInformationReserved2Length = 4
108 109 // ndpPrefixInformationPrefixOffset is the start of the Prefix field
110 // within an NDPPrefixInformation.
111 ndpPrefixInformationPrefixOffset = 14
112 113 // ndpRecursiveDNSServerLifetimeOffset is the start of the 4-byte
114 // Lifetime field within an NDPRecursiveDNSServer.
115 ndpRecursiveDNSServerLifetimeOffset = 2
116 117 // ndpRecursiveDNSServerAddressesOffset is the start of the addresses
118 // for IPv6 Recursive DNS Servers within an NDPRecursiveDNSServer.
119 ndpRecursiveDNSServerAddressesOffset = 6
120 121 // minNDPRecursiveDNSServerLength is the minimum NDP Recursive DNS Server
122 // option's body size when it contains at least one IPv6 address, as per
123 // RFC 8106 section 5.3.1.
124 minNDPRecursiveDNSServerBodySize = 22
125 126 // ndpDNSSearchListLifetimeOffset is the start of the 4-byte
127 // Lifetime field within an NDPDNSSearchList.
128 ndpDNSSearchListLifetimeOffset = 2
129 130 // ndpDNSSearchListDomainNamesOffset is the start of the DNS search list
131 // domain names within an NDPDNSSearchList.
132 ndpDNSSearchListDomainNamesOffset = 6
133 134 // minNDPDNSSearchListBodySize is the minimum NDP DNS Search List option's
135 // body size when it contains at least one domain name, as per RFC 8106
136 // section 5.3.1.
137 minNDPDNSSearchListBodySize = 14
138 139 // maxDomainNameLabelLength is the maximum length of a domain name
140 // label, as per RFC 1035 section 3.1.
141 maxDomainNameLabelLength = 63
142 143 // maxDomainNameLength is the maximum length of a domain name, including
144 // label AND label length octet, as per RFC 1035 section 3.1.
145 maxDomainNameLength = 255
146 147 // lengthByteUnits is the multiplier factor for the Length field of an
148 // NDP option. That is, the length field for NDP options is in units of
149 // 8 octets, as per RFC 4861 section 4.6.
150 lengthByteUnits = 8
151 152 // NDPInfiniteLifetime is a value that represents infinity for the
153 // 4-byte lifetime fields found in various NDP options. Its value is
154 // (2^32 - 1)s = 4294967295s.
155 NDPInfiniteLifetime = time.Second * math.MaxUint32
156 )
157 158 // NDPOptionIterator is an iterator of NDPOption.
159 //
160 // Note, between when an NDPOptionIterator is obtained and last used, no changes
161 // to the NDPOptions may happen. Doing so may cause undefined and unexpected
162 // behaviour. It is fine to obtain an NDPOptionIterator, iterate over the first
163 // few NDPOption then modify the backing NDPOptions so long as the
164 // NDPOptionIterator obtained before modification is no longer used.
165 type NDPOptionIterator struct {
166 opts *bytes.Buffer
167 }
168 169 // Potential errors when iterating over an NDPOptions.
170 var (
171 ErrNDPOptMalformedBody = errors.New("NDP option has a malformed body")
172 ErrNDPOptMalformedHeader = errors.New("NDP option has a malformed header")
173 )
174 175 // Next returns the next element in the backing NDPOptions, or true if we are
176 // done, or false if an error occurred.
177 //
178 // The return can be read as option, done, error. Note, option should only be
179 // used if done is false and error is nil.
180 func (i *NDPOptionIterator) Next() (NDPOption, bool, error) {
181 for {
182 // Do we still have elements to look at?
183 if i.opts.Len() == 0 {
184 return nil, true, nil
185 }
186 187 // Get the Type field.
188 temp, err := i.opts.ReadByte()
189 if err != nil {
190 if err != io.EOF {
191 // ReadByte should only ever return nil or io.EOF.
192 panic(fmt.Sprintf("unexpected error when reading the option's Type field: %s", err))
193 }
194 195 // We use io.ErrUnexpectedEOF as exhausting the buffer is unexpected once
196 // we start parsing an option; we expect the buffer to contain enough
197 // bytes for the whole option.
198 return nil, true, fmt.Errorf("unexpectedly exhausted buffer when reading the option's Type field: %w", io.ErrUnexpectedEOF)
199 }
200 kind := ndpOptionIdentifier(temp)
201 202 // Get the Length field.
203 length, err := i.opts.ReadByte()
204 if err != nil {
205 if err != io.EOF {
206 panic(fmt.Sprintf("unexpected error when reading the option's Length field for %s: %s", kind, err))
207 }
208 209 return nil, true, fmt.Errorf("unexpectedly exhausted buffer when reading the option's Length field for %s: %w", kind, io.ErrUnexpectedEOF)
210 }
211 212 // This would indicate an erroneous NDP option as the Length field should
213 // never be 0.
214 if length == 0 {
215 return nil, true, fmt.Errorf("zero valued Length field for %s: %w", kind, ErrNDPOptMalformedHeader)
216 }
217 218 // Get the body.
219 numBytes := int(length) * lengthByteUnits
220 numBodyBytes := numBytes - 2
221 body := i.opts.Next(numBodyBytes)
222 if len(body) < numBodyBytes {
223 return nil, true, fmt.Errorf("unexpectedly exhausted buffer when reading the option's Body for %s: %w", kind, io.ErrUnexpectedEOF)
224 }
225 226 switch kind {
227 case ndpSourceLinkLayerAddressOptionType:
228 return NDPSourceLinkLayerAddressOption(body), false, nil
229 230 case ndpTargetLinkLayerAddressOptionType:
231 return NDPTargetLinkLayerAddressOption(body), false, nil
232 233 case ndpNonceOptionType:
234 return NDPNonceOption(body), false, nil
235 236 case ndpRouteInformationType:
237 if numBodyBytes > ndpRouteInformationMaxLength {
238 return nil, true, fmt.Errorf("got %d bytes for NDP Route Information option's body, expected at max %d bytes: %w", numBodyBytes, ndpRouteInformationMaxLength, ErrNDPOptMalformedBody)
239 }
240 opt := NDPRouteInformation(body)
241 if err := opt.hasError(); err != nil {
242 return nil, true, err
243 }
244 245 return opt, false, nil
246 247 case ndpPrefixInformationType:
248 // Make sure the length of a Prefix Information option
249 // body is ndpPrefixInformationLength, as per RFC 4861
250 // section 4.6.2.
251 if numBodyBytes != ndpPrefixInformationLength {
252 return nil, true, fmt.Errorf("got %d bytes for NDP Prefix Information option's body, expected %d bytes: %w", numBodyBytes, ndpPrefixInformationLength, ErrNDPOptMalformedBody)
253 }
254 255 return NDPPrefixInformation(body), false, nil
256 257 case ndpRecursiveDNSServerOptionType:
258 opt := NDPRecursiveDNSServer(body)
259 if err := opt.checkAddresses(); err != nil {
260 return nil, true, err
261 }
262 263 return opt, false, nil
264 265 case ndpDNSSearchListOptionType:
266 opt := NDPDNSSearchList(body)
267 if err := opt.checkDomainNames(); err != nil {
268 return nil, true, err
269 }
270 271 return opt, false, nil
272 273 default:
274 // We do not yet recognize the option, just skip for
275 // now. This is okay because RFC 4861 allows us to
276 // skip/ignore any unrecognized options. However,
277 // we MUST recognized all the options in RFC 4861.
278 //
279 // TODO(b/141487990): Handle all NDP options as defined
280 // by RFC 4861.
281 }
282 }
283 }
284 285 // NDPOptions is a buffer of NDP options as defined by RFC 4861 section 4.6.
286 type NDPOptions []byte
287 288 // Iter returns an iterator of NDPOption.
289 //
290 // If check is true, Iter will do an integrity check on the options by iterating
291 // over it and returning an error if detected.
292 //
293 // See NDPOptionIterator for more information.
294 func (b NDPOptions) Iter(check bool) (NDPOptionIterator, error) {
295 it := NDPOptionIterator{
296 opts: bytes.NewBuffer(b),
297 }
298 299 if check {
300 it2 := NDPOptionIterator{
301 opts: bytes.NewBuffer(b),
302 }
303 304 for {
305 if _, done, err := it2.Next(); err != nil || done {
306 return it, err
307 }
308 }
309 }
310 311 return it, nil
312 }
313 314 // Serialize serializes the provided list of NDP options into b.
315 //
316 // Note, b must be of sufficient size to hold all the options in s. See
317 // NDPOptionsSerializer.Length for details on the getting the total size
318 // of a serialized NDPOptionsSerializer.
319 //
320 // Serialize may panic if b is not of sufficient size to hold all the options
321 // in s.
322 func (b NDPOptions) Serialize(s NDPOptionsSerializer) int {
323 done := 0
324 325 for _, o := range s {
326 l := paddedLength(o)
327 328 if l == 0 {
329 continue
330 }
331 332 b[0] = byte(o.kind())
333 334 // We know this safe because paddedLength would have returned
335 // 0 if o had an invalid length (> 255 * lengthByteUnits).
336 b[1] = uint8(l / lengthByteUnits)
337 338 // Serialize NDP option body.
339 used := o.serializeInto(b[2:])
340 341 // Zero out remaining (padding) bytes, if any exists.
342 if used+2 < l {
343 clear(b[used+2 : l])
344 }
345 346 b = b[l:]
347 done += l
348 }
349 350 return done
351 }
352 353 // NDPOption is the set of functions to be implemented by all NDP option types.
354 type NDPOption interface {
355 fmt.Stringer
356 357 // kind returns the type of the receiver.
358 kind() ndpOptionIdentifier
359 360 // length returns the length of the body of the receiver, in bytes.
361 length() int
362 363 // serializeInto serializes the receiver into the provided byte
364 // buffer.
365 //
366 // Note, the caller MUST provide a byte buffer with size of at least
367 // Length. Implementers of this function may assume that the byte buffer
368 // is of sufficient size. serializeInto MAY panic if the provided byte
369 // buffer is not of sufficient size.
370 //
371 // serializeInto will return the number of bytes that was used to
372 // serialize the receiver. Implementers must only use the number of
373 // bytes required to serialize the receiver. Callers MAY provide a
374 // larger buffer than required to serialize into.
375 serializeInto([]byte) int
376 }
377 378 // paddedLength returns the length of o, in bytes, with any padding bytes, if
379 // required.
380 func paddedLength(o NDPOption) int {
381 l := o.length()
382 383 if l == 0 {
384 return 0
385 }
386 387 // Length excludes the 2 Type and Length bytes.
388 l += 2
389 390 // Add extra bytes if needed to make sure the option is
391 // lengthByteUnits-byte aligned. We do this by adding lengthByteUnits-1
392 // to l and then stripping off the last few LSBits from l. This will
393 // make sure that l is rounded up to the nearest unit of
394 // lengthByteUnits. This works since lengthByteUnits is a power of 2
395 // (= 8).
396 mask := lengthByteUnits - 1
397 l += mask
398 l &^= mask
399 400 if l/lengthByteUnits > 255 {
401 // Should never happen because an option can only have a max
402 // value of 255 for its Length field, so just return 0 so this
403 // option does not get serialized.
404 //
405 // Returning 0 here will make sure that this option does not get
406 // serialized when NDPOptions.Serialize is called with the
407 // NDPOptionsSerializer that holds this option, effectively
408 // skipping this option during serialization. Also note that
409 // a value of zero for the Length field in an NDP option is
410 // invalid so this is another sign to the caller that this NDP
411 // option is malformed, as per RFC 4861 section 4.6.
412 return 0
413 }
414 415 return l
416 }
417 418 // NDPOptionsSerializer is a serializer for NDP options.
419 type NDPOptionsSerializer []NDPOption
420 421 // Length returns the total number of bytes required to serialize.
422 func (b NDPOptionsSerializer) Length() int {
423 l := 0
424 425 for _, o := range b {
426 l += paddedLength(o)
427 }
428 429 return l
430 }
431 432 // NDPNonceOption is the NDP Nonce Option as defined by RFC 3971 section 5.3.2.
433 //
434 // It is the first X bytes following the NDP option's Type and Length field
435 // where X is the value in Length multiplied by lengthByteUnits - 2 bytes.
436 type NDPNonceOption []byte
437 438 // kind implements NDPOption.
439 func (o NDPNonceOption) kind() ndpOptionIdentifier {
440 return ndpNonceOptionType
441 }
442 443 // length implements NDPOption.
444 func (o NDPNonceOption) length() int {
445 return len(o)
446 }
447 448 // serializeInto implements NDPOption.
449 func (o NDPNonceOption) serializeInto(b []byte) int {
450 return copy(b, o)
451 }
452 453 // String implements fmt.Stringer.
454 func (o NDPNonceOption) String() string {
455 return fmt.Sprintf("%T(%x)", o, []byte(o))
456 }
457 458 // Nonce returns the nonce value this option holds.
459 func (o NDPNonceOption) Nonce() []byte {
460 return o
461 }
462 463 // NDPSourceLinkLayerAddressOption is the NDP Source Link Layer Option
464 // as defined by RFC 4861 section 4.6.1.
465 //
466 // It is the first X bytes following the NDP option's Type and Length field
467 // where X is the value in Length multiplied by lengthByteUnits - 2 bytes.
468 type NDPSourceLinkLayerAddressOption tcpip.LinkAddress
469 470 // kind implements NDPOption.
471 func (o NDPSourceLinkLayerAddressOption) kind() ndpOptionIdentifier {
472 return ndpSourceLinkLayerAddressOptionType
473 }
474 475 // length implements NDPOption.
476 func (o NDPSourceLinkLayerAddressOption) length() int {
477 return len(o)
478 }
479 480 // serializeInto implements NDPOption.
481 func (o NDPSourceLinkLayerAddressOption) serializeInto(b []byte) int {
482 return copy(b, o)
483 }
484 485 // String implements fmt.Stringer.
486 func (o NDPSourceLinkLayerAddressOption) String() string {
487 return fmt.Sprintf("%T(%s)", o, tcpip.LinkAddress(o))
488 }
489 490 // EthernetAddress will return an ethernet (MAC) address if the
491 // NDPSourceLinkLayerAddressOption's body has at minimum EthernetAddressSize
492 // bytes. If the body has more than EthernetAddressSize bytes, only the first
493 // EthernetAddressSize bytes are returned as that is all that is needed for an
494 // Ethernet address.
495 func (o NDPSourceLinkLayerAddressOption) EthernetAddress() tcpip.LinkAddress {
496 if len(o) >= EthernetAddressSize {
497 return tcpip.LinkAddress(o[:EthernetAddressSize])
498 }
499 500 return tcpip.LinkAddress([]byte(nil))
501 }
502 503 // NDPTargetLinkLayerAddressOption is the NDP Target Link Layer Option
504 // as defined by RFC 4861 section 4.6.1.
505 //
506 // It is the first X bytes following the NDP option's Type and Length field
507 // where X is the value in Length multiplied by lengthByteUnits - 2 bytes.
508 type NDPTargetLinkLayerAddressOption tcpip.LinkAddress
509 510 // kind implements NDPOption.
511 func (o NDPTargetLinkLayerAddressOption) kind() ndpOptionIdentifier {
512 return ndpTargetLinkLayerAddressOptionType
513 }
514 515 // length implements NDPOption.
516 func (o NDPTargetLinkLayerAddressOption) length() int {
517 return len(o)
518 }
519 520 // serializeInto implements NDPOption.
521 func (o NDPTargetLinkLayerAddressOption) serializeInto(b []byte) int {
522 return copy(b, o)
523 }
524 525 // String implements fmt.Stringer.
526 func (o NDPTargetLinkLayerAddressOption) String() string {
527 return fmt.Sprintf("%T(%s)", o, tcpip.LinkAddress(o))
528 }
529 530 // EthernetAddress will return an ethernet (MAC) address if the
531 // NDPTargetLinkLayerAddressOption's body has at minimum EthernetAddressSize
532 // bytes. If the body has more than EthernetAddressSize bytes, only the first
533 // EthernetAddressSize bytes are returned as that is all that is needed for an
534 // Ethernet address.
535 func (o NDPTargetLinkLayerAddressOption) EthernetAddress() tcpip.LinkAddress {
536 if len(o) >= EthernetAddressSize {
537 return tcpip.LinkAddress(o[:EthernetAddressSize])
538 }
539 540 return tcpip.LinkAddress([]byte(nil))
541 }
542 543 // NDPPrefixInformation is the NDP Prefix Information option as defined by
544 // RFC 4861 section 4.6.2.
545 //
546 // The length, in bytes, of a valid NDP Prefix Information option body MUST be
547 // ndpPrefixInformationLength bytes.
548 type NDPPrefixInformation []byte
549 550 // kind implements NDPOption.
551 func (o NDPPrefixInformation) kind() ndpOptionIdentifier {
552 return ndpPrefixInformationType
553 }
554 555 // length implements NDPOption.
556 func (o NDPPrefixInformation) length() int {
557 return ndpPrefixInformationLength
558 }
559 560 // serializeInto implements NDPOption.
561 func (o NDPPrefixInformation) serializeInto(b []byte) int {
562 used := copy(b, o)
563 564 // Zero out the Reserved1 field.
565 b[ndpPrefixInformationFlagsOffset] &^= ndpPrefixInformationReserved1FlagsMask
566 567 // Zero out the Reserved2 field.
568 reserved2 := b[ndpPrefixInformationReserved2Offset:][:ndpPrefixInformationReserved2Length]
569 clear(reserved2)
570 571 return used
572 }
573 574 // String implements fmt.Stringer.
575 func (o NDPPrefixInformation) String() string {
576 return fmt.Sprintf("%T(O=%t, A=%t, PL=%s, VL=%s, Prefix=%s)",
577 o,
578 o.OnLinkFlag(),
579 o.AutonomousAddressConfigurationFlag(),
580 o.PreferredLifetime(),
581 o.ValidLifetime(),
582 o.Subnet())
583 }
584 585 // PrefixLength returns the value in the number of leading bits in the Prefix
586 // that are valid.
587 //
588 // Valid values are in the range [0, 128], but o may not always contain valid
589 // values. It is up to the caller to valdiate the Prefix Information option.
590 func (o NDPPrefixInformation) PrefixLength() uint8 {
591 return o[ndpPrefixInformationPrefixLengthOffset]
592 }
593 594 // OnLinkFlag returns true of the prefix is considered on-link. On-link means
595 // that a forwarding node is not needed to send packets to other nodes on the
596 // same prefix.
597 //
598 // Note, when this function returns false, no statement is made about the
599 // on-link property of a prefix. That is, if OnLinkFlag returns false, the
600 // caller MUST NOT conclude that the prefix is off-link and MUST NOT update any
601 // previously stored state for this prefix about its on-link status.
602 func (o NDPPrefixInformation) OnLinkFlag() bool {
603 return o[ndpPrefixInformationFlagsOffset]&ndpPrefixInformationOnLinkFlagMask != 0
604 }
605 606 // AutonomousAddressConfigurationFlag returns true if the prefix can be used for
607 // Stateless Address Auto-Configuration (as specified in RFC 4862).
608 func (o NDPPrefixInformation) AutonomousAddressConfigurationFlag() bool {
609 return o[ndpPrefixInformationFlagsOffset]&ndpPrefixInformationAutoAddrConfFlagMask != 0
610 }
611 612 // ValidLifetime returns the length of time that the prefix is valid for the
613 // purpose of on-link determination. This value is relative to the send time of
614 // the packet that the Prefix Information option was present in.
615 //
616 // Note, a value of 0 implies the prefix should not be considered as on-link,
617 // and a value of infinity/forever is represented by
618 // NDPInfiniteLifetime.
619 func (o NDPPrefixInformation) ValidLifetime() time.Duration {
620 // The field is the time in seconds, as per RFC 4861 section 4.6.2.
621 return time.Second * time.Duration(binary.BigEndian.Uint32(o[ndpPrefixInformationValidLifetimeOffset:]))
622 }
623 624 // PreferredLifetime returns the length of time that an address generated from
625 // the prefix via Stateless Address Auto-Configuration remains preferred. This
626 // value is relative to the send time of the packet that the Prefix Information
627 // option was present in.
628 //
629 // Note, a value of 0 implies that addresses generated from the prefix should
630 // no longer remain preferred, and a value of infinity is represented by
631 // NDPInfiniteLifetime.
632 //
633 // Also note that the value of this field MUST NOT exceed the Valid Lifetime
634 // field to avoid preferring addresses that are no longer valid, for the
635 // purpose of Stateless Address Auto-Configuration.
636 func (o NDPPrefixInformation) PreferredLifetime() time.Duration {
637 // The field is the time in seconds, as per RFC 4861 section 4.6.2.
638 return time.Second * time.Duration(binary.BigEndian.Uint32(o[ndpPrefixInformationPreferredLifetimeOffset:]))
639 }
640 641 // Prefix returns an IPv6 address or a prefix of an IPv6 address. The Prefix
642 // Length field (see NDPPrefixInformation.PrefixLength) contains the number
643 // of valid leading bits in the prefix.
644 //
645 // Hosts SHOULD ignore an NDP Prefix Information option where the Prefix field
646 // holds the link-local prefix (fe80::).
647 func (o NDPPrefixInformation) Prefix() tcpip.Address {
648 return tcpip.AddrFrom16Slice(o[ndpPrefixInformationPrefixOffset:][:IPv6AddressSize])
649 }
650 651 // Subnet returns the Prefix field and Prefix Length field represented in a
652 // tcpip.Subnet.
653 func (o NDPPrefixInformation) Subnet() tcpip.Subnet {
654 addrWithPrefix := tcpip.AddressWithPrefix{
655 Address: o.Prefix(),
656 PrefixLen: int(o.PrefixLength()),
657 }
658 return addrWithPrefix.Subnet()
659 }
660 661 // NDPRecursiveDNSServer is the NDP Recursive DNS Server option, as defined by
662 // RFC 8106 section 5.1.
663 //
664 // To make sure that the option meets its minimum length and does not end in the
665 // middle of a DNS server's IPv6 address, the length of a valid
666 // NDPRecursiveDNSServer must meet the following constraint:
667 //
668 // (Length - ndpRecursiveDNSServerAddressesOffset) % IPv6AddressSize == 0
669 type NDPRecursiveDNSServer []byte
670 671 // Type returns the type of an NDP Recursive DNS Server option.
672 //
673 // kind implements NDPOption.
674 func (NDPRecursiveDNSServer) kind() ndpOptionIdentifier {
675 return ndpRecursiveDNSServerOptionType
676 }
677 678 // length implements NDPOption.
679 func (o NDPRecursiveDNSServer) length() int {
680 return len(o)
681 }
682 683 // serializeInto implements NDPOption.
684 func (o NDPRecursiveDNSServer) serializeInto(b []byte) int {
685 used := copy(b, o)
686 687 // Zero out the reserved bytes that are before the Lifetime field.
688 clear(b[0:ndpRecursiveDNSServerLifetimeOffset])
689 690 return used
691 }
692 693 // String implements fmt.Stringer.
694 func (o NDPRecursiveDNSServer) String() string {
695 lt := o.Lifetime()
696 addrs, err := o.Addresses()
697 if err != nil {
698 return fmt.Sprintf("%T([] valid for %s; err = %s)", o, lt, err)
699 }
700 return fmt.Sprintf("%T(%s valid for %s)", o, addrs, lt)
701 }
702 703 // Lifetime returns the length of time that the DNS server addresses
704 // in this option may be used for name resolution.
705 //
706 // Note, a value of 0 implies the addresses should no longer be used,
707 // and a value of infinity/forever is represented by NDPInfiniteLifetime.
708 //
709 // Lifetime may panic if o does not have enough bytes to hold the Lifetime
710 // field.
711 func (o NDPRecursiveDNSServer) Lifetime() time.Duration {
712 // The field is the time in seconds, as per RFC 8106 section 5.1.
713 return time.Second * time.Duration(binary.BigEndian.Uint32(o[ndpRecursiveDNSServerLifetimeOffset:]))
714 }
715 716 // Addresses returns the recursive DNS server IPv6 addresses that may be
717 // used for name resolution.
718 //
719 // Note, the addresses MAY be link-local addresses.
720 func (o NDPRecursiveDNSServer) Addresses() ([]tcpip.Address, error) {
721 var addrs []tcpip.Address
722 return addrs, o.iterAddresses(func(addr tcpip.Address) { addrs = append(addrs, addr) })
723 }
724 725 // checkAddresses iterates over the addresses in an NDP Recursive DNS Server
726 // option and returns any error it encounters.
727 func (o NDPRecursiveDNSServer) checkAddresses() error {
728 return o.iterAddresses(nil)
729 }
730 731 // iterAddresses iterates over the addresses in an NDP Recursive DNS Server
732 // option and calls a function with each valid unicast IPv6 address.
733 //
734 // Note, the addresses MAY be link-local addresses.
735 func (o NDPRecursiveDNSServer) iterAddresses(fn func(tcpip.Address)) error {
736 if l := len(o); l < minNDPRecursiveDNSServerBodySize {
737 return fmt.Errorf("got %d bytes for NDP Recursive DNS Server option's body, expected at least %d bytes: %w", l, minNDPRecursiveDNSServerBodySize, io.ErrUnexpectedEOF)
738 }
739 740 o = o[ndpRecursiveDNSServerAddressesOffset:]
741 l := len(o)
742 if l%IPv6AddressSize != 0 {
743 return fmt.Errorf("NDP Recursive DNS Server option's body ends in the middle of an IPv6 address (addresses body size = %d bytes): %w", l, ErrNDPOptMalformedBody)
744 }
745 746 for i := 0; len(o) != 0; i++ {
747 addr := tcpip.AddrFrom16Slice(o[:IPv6AddressSize])
748 if !IsV6UnicastAddress(addr) {
749 return fmt.Errorf("%d-th address (%s) in NDP Recursive DNS Server option is not a valid unicast IPv6 address: %w", i, addr, ErrNDPOptMalformedBody)
750 }
751 752 if fn != nil {
753 fn(addr)
754 }
755 756 o = o[IPv6AddressSize:]
757 }
758 759 return nil
760 }
761 762 // NDPDNSSearchList is the NDP DNS Search List option, as defined by
763 // RFC 8106 section 5.2.
764 type NDPDNSSearchList []byte
765 766 // kind implements NDPOption.
767 func (o NDPDNSSearchList) kind() ndpOptionIdentifier {
768 return ndpDNSSearchListOptionType
769 }
770 771 // length implements NDPOption.
772 func (o NDPDNSSearchList) length() int {
773 return len(o)
774 }
775 776 // serializeInto implements NDPOption.
777 func (o NDPDNSSearchList) serializeInto(b []byte) int {
778 used := copy(b, o)
779 780 // Zero out the reserved bytes that are before the Lifetime field.
781 clear(b[0:ndpDNSSearchListLifetimeOffset])
782 783 return used
784 }
785 786 // String implements fmt.Stringer.
787 func (o NDPDNSSearchList) String() string {
788 lt := o.Lifetime()
789 domainNames, err := o.DomainNames()
790 if err != nil {
791 return fmt.Sprintf("%T([] valid for %s; err = %s)", o, lt, err)
792 }
793 return fmt.Sprintf("%T(%s valid for %s)", o, domainNames, lt)
794 }
795 796 // Lifetime returns the length of time that the DNS search list of domain names
797 // in this option may be used for name resolution.
798 //
799 // Note, a value of 0 implies the domain names should no longer be used,
800 // and a value of infinity/forever is represented by NDPInfiniteLifetime.
801 func (o NDPDNSSearchList) Lifetime() time.Duration {
802 // The field is the time in seconds, as per RFC 8106 section 5.1.
803 return time.Second * time.Duration(binary.BigEndian.Uint32(o[ndpDNSSearchListLifetimeOffset:]))
804 }
805 806 // DomainNames returns a DNS search list of domain names.
807 //
808 // DomainNames will parse the backing buffer as outlined by RFC 1035 section
809 // 3.1 and return a list of strings, with all domain names in lower case.
810 func (o NDPDNSSearchList) DomainNames() ([]string, error) {
811 var domainNames []string
812 return domainNames, o.iterDomainNames(func(domainName string) { domainNames = append(domainNames, domainName) })
813 }
814 815 // checkDomainNames iterates over the domain names in an NDP DNS Search List
816 // option and returns any error it encounters.
817 func (o NDPDNSSearchList) checkDomainNames() error {
818 return o.iterDomainNames(nil)
819 }
820 821 // iterDomainNames iterates over the domain names in an NDP DNS Search List
822 // option and calls a function with each valid domain name.
823 func (o NDPDNSSearchList) iterDomainNames(fn func(string)) error {
824 if l := len(o); l < minNDPDNSSearchListBodySize {
825 return fmt.Errorf("got %d bytes for NDP DNS Search List option's body, expected at least %d bytes: %w", l, minNDPDNSSearchListBodySize, io.ErrUnexpectedEOF)
826 }
827 828 var searchList bytes.Reader
829 searchList.Reset(o[ndpDNSSearchListDomainNamesOffset:])
830 831 var scratch [maxDomainNameLength]byte
832 domainName := bytes.NewBuffer(scratch[:])
833 834 // Parse the domain names, as per RFC 1035 section 3.1.
835 for searchList.Len() != 0 {
836 domainName.Reset()
837 838 // Parse a label within a domain name, as per RFC 1035 section 3.1.
839 for {
840 // The first byte is the label length.
841 labelLenByte, err := searchList.ReadByte()
842 if err != nil {
843 if err != io.EOF {
844 // ReadByte should only ever return nil or io.EOF.
845 panic(fmt.Sprintf("unexpected error when reading a label's length: %s", err))
846 }
847 848 // We use io.ErrUnexpectedEOF as exhausting the buffer is unexpected
849 // once we start parsing a domain name; we expect the buffer to contain
850 // enough bytes for the whole domain name.
851 return fmt.Errorf("unexpected exhausted buffer while parsing a new label for a domain from NDP Search List option: %w", io.ErrUnexpectedEOF)
852 }
853 labelLen := int(labelLenByte)
854 855 // A zero-length label implies the end of a domain name.
856 if labelLen == 0 {
857 // If the domain name is empty or we have no callback function, do
858 // nothing further with the current domain name.
859 if domainName.Len() == 0 || fn == nil {
860 break
861 }
862 863 // Ignore the trailing period in the parsed domain name.
864 domainName.Truncate(domainName.Len() - 1)
865 fn(domainName.String())
866 break
867 }
868 869 // The label's length must not exceed the maximum length for a label.
870 if labelLen > maxDomainNameLabelLength {
871 return fmt.Errorf("label length of %d bytes is greater than the max label length of %d bytes for an NDP Search List option: %w", labelLen, maxDomainNameLabelLength, ErrNDPOptMalformedBody)
872 }
873 874 // The label (and trailing period) must not make the domain name too long.
875 if labelLen+1 > domainName.Cap()-domainName.Len() {
876 return fmt.Errorf("label would make an NDP Search List option's domain name longer than the max domain name length of %d bytes: %w", maxDomainNameLength, ErrNDPOptMalformedBody)
877 }
878 879 // Copy the label and add a trailing period.
880 for i := 0; i < labelLen; i++ {
881 b, err := searchList.ReadByte()
882 if err != nil {
883 if err != io.EOF {
884 panic(fmt.Sprintf("unexpected error when reading domain name's label: %s", err))
885 }
886 887 return fmt.Errorf("read %d out of %d bytes for a domain name's label from NDP Search List option: %w", i, labelLen, io.ErrUnexpectedEOF)
888 }
889 890 // As per RFC 1035 section 2.3.1:
891 // 1) the label must only contain ASCII include letters, digits and
892 // hyphens
893 // 2) the first character in a label must be a letter
894 // 3) the last letter in a label must be a letter or digit
895 896 if !isLetter(b) {
897 if i == 0 {
898 return fmt.Errorf("first character of a domain name's label in an NDP Search List option must be a letter, got character code = %d: %w", b, ErrNDPOptMalformedBody)
899 }
900 901 if b == '-' {
902 if i == labelLen-1 {
903 return fmt.Errorf("last character of a domain name's label in an NDP Search List option must not be a hyphen (-): %w", ErrNDPOptMalformedBody)
904 }
905 } else if !isDigit(b) {
906 return fmt.Errorf("domain name's label in an NDP Search List option may only contain letters, digits and hyphens, got character code = %d: %w", b, ErrNDPOptMalformedBody)
907 }
908 }
909 910 // If b is an upper case character, make it lower case.
911 if isUpperLetter(b) {
912 b = b - 'A' + 'a'
913 }
914 915 if err := domainName.WriteByte(b); err != nil {
916 panic(fmt.Sprintf("unexpected error writing label to domain name buffer: %s", err))
917 }
918 }
919 if err := domainName.WriteByte('.'); err != nil {
920 panic(fmt.Sprintf("unexpected error writing trailing period to domain name buffer: %s", err))
921 }
922 }
923 }
924 925 return nil
926 }
927 928 func isLetter(b byte) bool {
929 return b >= 'a' && b <= 'z' || isUpperLetter(b)
930 }
931 932 func isUpperLetter(b byte) bool {
933 return b >= 'A' && b <= 'Z'
934 }
935 936 func isDigit(b byte) bool {
937 return b >= '0' && b <= '9'
938 }
939 940 // As per RFC 4191 section 2.3,
941 //
942 // 2.3. Route Information Option
943 //
944 // 0 1 2 3
945 // 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
946 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
947 // | Type | Length | Prefix Length |Resvd|Prf|Resvd|
948 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
949 // | Route Lifetime |
950 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
951 // | Prefix (Variable Length) |
952 // . .
953 // . .
954 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
955 //
956 // Fields:
957 //
958 // Type 24
959 //
960 //
961 // Length 8-bit unsigned integer. The length of the option
962 // (including the Type and Length fields) in units of 8
963 // octets. The Length field is 1, 2, or 3 depending on the
964 // Prefix Length. If Prefix Length is greater than 64, then
965 // Length must be 3. If Prefix Length is greater than 0,
966 // then Length must be 2 or 3. If Prefix Length is zero,
967 // then Length must be 1, 2, or 3.
968 const (
969 ndpRouteInformationType = ndpOptionIdentifier(24)
970 ndpRouteInformationMaxLength = 22
971 972 ndpRouteInformationPrefixLengthIdx = 0
973 ndpRouteInformationFlagsIdx = 1
974 ndpRouteInformationPrfShift = 3
975 ndpRouteInformationPrfMask = 3 << ndpRouteInformationPrfShift
976 ndpRouteInformationRouteLifetimeIdx = 2
977 ndpRouteInformationRoutePrefixIdx = 6
978 )
979 980 // NDPRouteInformation is the NDP Router Information option, as defined by
981 // RFC 4191 section 2.3.
982 type NDPRouteInformation []byte
983 984 func (NDPRouteInformation) kind() ndpOptionIdentifier {
985 return ndpRouteInformationType
986 }
987 988 func (o NDPRouteInformation) length() int {
989 return len(o)
990 }
991 992 func (o NDPRouteInformation) serializeInto(b []byte) int {
993 return copy(b, o)
994 }
995 996 // String implements fmt.Stringer.
997 func (o NDPRouteInformation) String() string {
998 return fmt.Sprintf("%T", o)
999 }
1000 1001 // PrefixLength returns the length of the prefix.
1002 func (o NDPRouteInformation) PrefixLength() uint8 {
1003 return o[ndpRouteInformationPrefixLengthIdx]
1004 }
1005 1006 // RoutePreference returns the preference of the route over other routes to the
1007 // same destination but through a different router.
1008 func (o NDPRouteInformation) RoutePreference() NDPRoutePreference {
1009 return NDPRoutePreference((o[ndpRouteInformationFlagsIdx] & ndpRouteInformationPrfMask) >> ndpRouteInformationPrfShift)
1010 }
1011 1012 // RouteLifetime returns the lifetime of the route.
1013 //
1014 // Note, a value of 0 implies the route is now invalid and a value of
1015 // infinity/forever is represented by NDPInfiniteLifetime.
1016 func (o NDPRouteInformation) RouteLifetime() time.Duration {
1017 return time.Second * time.Duration(binary.BigEndian.Uint32(o[ndpRouteInformationRouteLifetimeIdx:]))
1018 }
1019 1020 // Prefix returns the prefix of the destination subnet this route is for.
1021 func (o NDPRouteInformation) Prefix() (tcpip.Subnet, error) {
1022 prefixLength := int(o.PrefixLength())
1023 if max := IPv6AddressSize * 8; prefixLength > max {
1024 return tcpip.Subnet{}, fmt.Errorf("got prefix length = %d, want <= %d", prefixLength, max)
1025 }
1026 1027 prefix := o[ndpRouteInformationRoutePrefixIdx:]
1028 var addrBytes [IPv6AddressSize]byte
1029 if n := copy(addrBytes[:], prefix); n != len(prefix) {
1030 panic(fmt.Sprintf("got copy(addrBytes, prefix) = %d, want = %d", n, len(prefix)))
1031 }
1032 1033 return tcpip.AddressWithPrefix{
1034 Address: tcpip.AddrFrom16(addrBytes),
1035 PrefixLen: prefixLength,
1036 }.Subnet(), nil
1037 }
1038 1039 func (o NDPRouteInformation) hasError() error {
1040 l := len(o)
1041 if l < ndpRouteInformationRoutePrefixIdx {
1042 return fmt.Errorf("%T too small, got = %d bytes: %w", o, l, ErrNDPOptMalformedBody)
1043 }
1044 1045 prefixLength := int(o.PrefixLength())
1046 if max := IPv6AddressSize * 8; prefixLength > max {
1047 return fmt.Errorf("got prefix length = %d, want <= %d: %w", prefixLength, max, ErrNDPOptMalformedBody)
1048 }
1049 1050 // Length 8-bit unsigned integer. The length of the option
1051 // (including the Type and Length fields) in units of 8
1052 // octets. The Length field is 1, 2, or 3 depending on the
1053 // Prefix Length. If Prefix Length is greater than 64, then
1054 // Length must be 3. If Prefix Length is greater than 0,
1055 // then Length must be 2 or 3. If Prefix Length is zero,
1056 // then Length must be 1, 2, or 3.
1057 l += 2 // Add 2 bytes for the type and length bytes.
1058 lengthField := l / lengthByteUnits
1059 if prefixLength > 64 {
1060 if lengthField != 3 {
1061 return fmt.Errorf("Length field must be 3 when Prefix Length (%d) is > 64 (got = %d): %w", prefixLength, lengthField, ErrNDPOptMalformedBody)
1062 }
1063 } else if prefixLength > 0 {
1064 if lengthField != 2 && lengthField != 3 {
1065 return fmt.Errorf("Length field must be 2 or 3 when Prefix Length (%d) is between 0 and 64 (got = %d): %w", prefixLength, lengthField, ErrNDPOptMalformedBody)
1066 }
1067 } else if lengthField == 0 || lengthField > 3 {
1068 return fmt.Errorf("Length field must be 1, 2, or 3 when Prefix Length is zero (got = %d): %w", lengthField, ErrNDPOptMalformedBody)
1069 }
1070 1071 return nil
1072 }
1073