gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/tcpip/header/mldv2_igmpv3_common.go (about) 1 // Copyright 2022 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 "fmt" 20 "time" 21 22 "gvisor.dev/gvisor/pkg/tcpip" 23 ) 24 25 func mldv2AndIGMPv3QuerierQueryCodeToInterval(code uint8) time.Duration { 26 // MLDv2: As per RFC 3810 section 5.1.19, 27 // 28 // The Querier's Query Interval Code field specifies the [Query 29 // Interval] used by the Querier. The actual interval, called the 30 // Querier's Query Interval (QQI), is represented in units of seconds, 31 // and is derived from the Querier's Query Interval Code as follows: 32 // 33 // If QQIC < 128, QQI = QQIC 34 // 35 // If QQIC >= 128, QQIC represents a floating-point value as follows: 36 // 37 // 0 1 2 3 4 5 6 7 38 // +-+-+-+-+-+-+-+-+ 39 // |1| exp | mant | 40 // +-+-+-+-+-+-+-+-+ 41 // 42 // QQI = (mant | 0x10) << (exp + 3) 43 // 44 // Multicast routers that are not the current Querier adopt the QQI 45 // value from the most recently received Query as their own [Query 46 // Interval] value, unless that most recently received QQI was zero, in 47 // which case the receiving routers use the default [Query Interval] 48 // value specified in section 9.2. 49 // 50 // IGMPv3: As per RFC 3376 section 4.1.7, 51 // 52 // The Querier's Query Interval Code field specifies the [Query 53 // Interval] used by the querier. The actual interval, called the 54 // Querier's Query Interval (QQI), is represented in units of seconds 55 // and is derived from the Querier's Query Interval Code as follows: 56 // 57 // If QQIC < 128, QQI = QQIC 58 // 59 // If QQIC >= 128, QQIC represents a floating-point value as follows: 60 // 61 // 0 1 2 3 4 5 6 7 62 // +-+-+-+-+-+-+-+-+ 63 // |1| exp | mant | 64 // +-+-+-+-+-+-+-+-+ 65 // 66 // QQI = (mant | 0x10) << (exp + 3) 67 // 68 // Multicast routers that are not the current querier adopt the QQI 69 // value from the most recently received Query as their own [Query 70 // Interval] value, unless that most recently received QQI was zero, in 71 // which case the receiving routers use the default [Query Interval] 72 // value specified in section 8.2. 73 interval := time.Duration(code) 74 if interval < 128 { 75 return interval * time.Second 76 } 77 78 const expMask = 0b111 79 const mantBits = 4 80 mant := interval & ((1 << mantBits) - 1) 81 exp := (interval >> mantBits) & expMask 82 return (mant | 0x10) << (exp + 3) * time.Second 83 } 84 85 // MakeAddressIterator returns an AddressIterator. 86 func MakeAddressIterator(addressSize int, buf *bytes.Buffer) AddressIterator { 87 return AddressIterator{addressSize: addressSize, buf: buf} 88 } 89 90 // AddressIterator is an iterator over IPv6 addresses. 91 type AddressIterator struct { 92 addressSize int 93 buf *bytes.Buffer 94 } 95 96 // Done indicates that the iterator has been exhausted/has no more elements. 97 func (it *AddressIterator) Done() bool { 98 return it.buf.Len() == 0 99 } 100 101 // Next returns the next address in the iterator. 102 // 103 // Returns false if the iterator has been exhausted. 104 func (it *AddressIterator) Next() (tcpip.Address, bool) { 105 if it.Done() { 106 var emptyAddress tcpip.Address 107 return emptyAddress, false 108 } 109 110 b := it.buf.Next(it.addressSize) 111 if len(b) != it.addressSize { 112 panic(fmt.Sprintf("got len(buf.Next(%d)) = %d, want = %d", it.addressSize, len(b), it.addressSize)) 113 } 114 115 return tcpip.AddrFromSlice(b), true 116 } 117 118 func makeAddressIterator(b []byte, expectedAddresses uint16, addressSize int) (AddressIterator, bool) { 119 expectedLen := int(expectedAddresses) * addressSize 120 if len(b) < expectedLen { 121 return AddressIterator{}, false 122 } 123 return MakeAddressIterator(addressSize, bytes.NewBuffer(b[:expectedLen])), true 124 }