snapshot: sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1
Содержимое пина, зафиксированного в go.mod sing-box-lx, одним коммитом без истории. Полная история SagerNet/gvisor — 1.45 ГБ и клонируется в каждой CI-джобе; наша дельта — одна вставка в одну функцию, история для неё не нужна. Module path github.com/sagernet/gvisor сохранён намеренно: на него опирается replace-директива суперпроекта. Патч поверх — отдельным коммитом, чтобы дельта читалась одним git show и переносилась на новый пин копированием. SPECS/TASKS/048-GVISOR_HANDSHAKE_NIL_CRASH
This commit is contained in:
commit
2c4ae3b0a4
712 changed files with 185689 additions and 0 deletions
500
pkg/tcpip/header/igmpv3.go
Normal file
500
pkg/tcpip/header/igmpv3.go
Normal file
|
|
@ -0,0 +1,500 @@
|
|||
// Copyright 2022 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package header
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/gvisor/pkg/tcpip"
|
||||
)
|
||||
|
||||
// IGMPv3RoutersAddress is the address to send IGMPv3 reports to.
|
||||
//
|
||||
// As per RFC 3376 section 4.2.14,
|
||||
//
|
||||
// Version 3 Reports are sent with an IP destination address of
|
||||
// 224.0.0.22, to which all IGMPv3-capable multicast routers listen.
|
||||
var IGMPv3RoutersAddress = tcpip.AddrFrom4([4]byte{0xe0, 0x00, 0x00, 0x16})
|
||||
|
||||
const (
|
||||
// IGMPv3QueryMinimumSize is the mimum size of a valid IGMPv3 query,
|
||||
// as per RFC 3376 section 4.1.
|
||||
IGMPv3QueryMinimumSize = 12
|
||||
|
||||
igmpv3QueryMaxRespCodeOffset = 1
|
||||
igmpv3QueryGroupAddressOffset = 4
|
||||
igmpv3QueryResvSQRVOffset = 8
|
||||
igmpv3QueryQRVMask = 0b111
|
||||
igmpv3QueryQQICOffset = 9
|
||||
igmpv3QueryNumberOfSourcesOffset = 10
|
||||
igmpv3QuerySourcesOffset = 12
|
||||
)
|
||||
|
||||
// IGMPv3Query is an IGMPv3 query message.
|
||||
//
|
||||
// As per RFC 3376 section 4.1,
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 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
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Type = 0x11 | Max Resp Code | Checksum |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Group Address |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Resv |S| QRV | QQIC | Number of Sources (N) |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Source Address [1] |
|
||||
// +- -+
|
||||
// | Source Address [2] |
|
||||
// +- . -+
|
||||
// . . .
|
||||
// . . .
|
||||
// +- -+
|
||||
// | Source Address [N] |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
type IGMPv3Query IGMP
|
||||
|
||||
// MaximumResponseCode returns the Maximum Response Code.
|
||||
func (i IGMPv3Query) MaximumResponseCode() uint8 {
|
||||
return i[igmpv3QueryMaxRespCodeOffset]
|
||||
}
|
||||
|
||||
// IGMPv3MaximumResponseDelay returns the Maximum Response Delay in an IGMPv3
|
||||
// Maximum Response Code.
|
||||
//
|
||||
// As per RFC 3376 section 4.1.1,
|
||||
//
|
||||
// The Max Resp Code field specifies the maximum time allowed before
|
||||
// sending a responding report. The actual time allowed, called the Max
|
||||
// Resp Time, is represented in units of 1/10 second and is derived from
|
||||
// the Max Resp Code as follows:
|
||||
//
|
||||
// If Max Resp Code < 128, Max Resp Time = Max Resp Code
|
||||
//
|
||||
// If Max Resp Code >= 128, Max Resp Code represents a floating-point
|
||||
// value as follows:
|
||||
//
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
// |1| exp | mant |
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// Max Resp Time = (mant | 0x10) << (exp + 3)
|
||||
//
|
||||
// Small values of Max Resp Time allow IGMPv3 routers to tune the "leave
|
||||
// latency" (the time between the moment the last host leaves a group
|
||||
// and the moment the routing protocol is notified that there are no
|
||||
// more members). Larger values, especially in the exponential range,
|
||||
// allow tuning of the burstiness of IGMP traffic on a network.
|
||||
func IGMPv3MaximumResponseDelay(codeRaw uint8) time.Duration {
|
||||
code := uint16(codeRaw)
|
||||
if code < 128 {
|
||||
return DecisecondToDuration(code)
|
||||
}
|
||||
|
||||
const mantBits = 4
|
||||
const expMask = 0b111
|
||||
exp := (code >> mantBits) & expMask
|
||||
mant := code & ((1 << mantBits) - 1)
|
||||
return DecisecondToDuration((mant | 0x10) << (exp + 3))
|
||||
}
|
||||
|
||||
// GroupAddress returns the group address.
|
||||
func (i IGMPv3Query) GroupAddress() tcpip.Address {
|
||||
return tcpip.AddrFrom4([4]byte(i[igmpv3QueryGroupAddressOffset:][:IPv4AddressSize]))
|
||||
}
|
||||
|
||||
// QuerierRobustnessVariable returns the querier's robustness variable.
|
||||
func (i IGMPv3Query) QuerierRobustnessVariable() uint8 {
|
||||
return i[igmpv3QueryResvSQRVOffset] & igmpv3QueryQRVMask
|
||||
}
|
||||
|
||||
// QuerierQueryInterval returns the querier's query interval.
|
||||
func (i IGMPv3Query) QuerierQueryInterval() time.Duration {
|
||||
return mldv2AndIGMPv3QuerierQueryCodeToInterval(i[igmpv3QueryQQICOffset])
|
||||
}
|
||||
|
||||
// Sources returns an iterator over source addresses in the query.
|
||||
//
|
||||
// Returns false if the message cannot hold the expected number of sources.
|
||||
func (i IGMPv3Query) Sources() (AddressIterator, bool) {
|
||||
return makeAddressIterator(
|
||||
i[igmpv3QuerySourcesOffset:],
|
||||
binary.BigEndian.Uint16(i[igmpv3QueryNumberOfSourcesOffset:]),
|
||||
IPv4AddressSize,
|
||||
)
|
||||
}
|
||||
|
||||
// IGMPv3ReportRecordType is the type of an IGMPv3 multicast address record
|
||||
// found in an IGMPv3 report, as per RFC 3810 section 5.2.12.
|
||||
type IGMPv3ReportRecordType int
|
||||
|
||||
// IGMPv3 multicast address record types, as per RFC 3810 section 5.2.12.
|
||||
const (
|
||||
IGMPv3ReportRecordModeIsInclude IGMPv3ReportRecordType = 1
|
||||
IGMPv3ReportRecordModeIsExclude IGMPv3ReportRecordType = 2
|
||||
IGMPv3ReportRecordChangeToIncludeMode IGMPv3ReportRecordType = 3
|
||||
IGMPv3ReportRecordChangeToExcludeMode IGMPv3ReportRecordType = 4
|
||||
IGMPv3ReportRecordAllowNewSources IGMPv3ReportRecordType = 5
|
||||
IGMPv3ReportRecordBlockOldSources IGMPv3ReportRecordType = 6
|
||||
)
|
||||
|
||||
const (
|
||||
igmpv3ReportGroupAddressRecordMinimumSize = 8
|
||||
igmpv3ReportGroupAddressRecordTypeOffset = 0
|
||||
igmpv3ReportGroupAddressRecordAuxDataLenOffset = 1
|
||||
igmpv3ReportGroupAddressRecordAuxDataLenUnits = 4
|
||||
igmpv3ReportGroupAddressRecordNumberOfSourcesOffset = 2
|
||||
igmpv3ReportGroupAddressRecordGroupAddressOffset = 4
|
||||
igmpv3ReportGroupAddressRecordSourcesOffset = 8
|
||||
)
|
||||
|
||||
// IGMPv3ReportGroupAddressRecordSerializer is an IGMPv3 Multicast Address
|
||||
// Record serializer.
|
||||
//
|
||||
// As per RFC 3810 section 5.2, a Multicast Address Record has the following
|
||||
// internal format:
|
||||
//
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Record Type | Aux Data Len | Number of Sources (N) |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// * Multicast Address *
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// * Source Address [1] *
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// +- -+
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// * Source Address [2] *
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// +- -+
|
||||
// . . .
|
||||
// . . .
|
||||
// . . .
|
||||
// +- -+
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// * Source Address [N] *
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// . .
|
||||
// . Auxiliary Data .
|
||||
// . .
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
type IGMPv3ReportGroupAddressRecordSerializer struct {
|
||||
RecordType IGMPv3ReportRecordType
|
||||
GroupAddress tcpip.Address
|
||||
Sources []tcpip.Address
|
||||
}
|
||||
|
||||
// Length returns the number of bytes this serializer would occupy.
|
||||
func (s *IGMPv3ReportGroupAddressRecordSerializer) Length() int {
|
||||
return igmpv3ReportGroupAddressRecordSourcesOffset + len(s.Sources)*IPv4AddressSize
|
||||
}
|
||||
|
||||
func copyIPv4Address(dst []byte, src tcpip.Address) {
|
||||
srcBytes := src.As4()
|
||||
if n := copy(dst, srcBytes[:]); n != IPv4AddressSize {
|
||||
panic(fmt.Sprintf("got copy(...) = %d, want = %d", n, IPv4AddressSize))
|
||||
}
|
||||
}
|
||||
|
||||
// SerializeInto serializes the record into the buffer.
|
||||
//
|
||||
// Panics if the buffer does not have enough space to fit the record.
|
||||
func (s *IGMPv3ReportGroupAddressRecordSerializer) SerializeInto(b []byte) {
|
||||
b[igmpv3ReportGroupAddressRecordTypeOffset] = byte(s.RecordType)
|
||||
b[igmpv3ReportGroupAddressRecordAuxDataLenOffset] = 0
|
||||
binary.BigEndian.PutUint16(b[igmpv3ReportGroupAddressRecordNumberOfSourcesOffset:], uint16(len(s.Sources)))
|
||||
copyIPv4Address(b[igmpv3ReportGroupAddressRecordGroupAddressOffset:], s.GroupAddress)
|
||||
b = b[igmpv3ReportGroupAddressRecordSourcesOffset:]
|
||||
for _, source := range s.Sources {
|
||||
copyIPv4Address(b, source)
|
||||
b = b[IPv4AddressSize:]
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
igmpv3ReportTypeOffset = 0
|
||||
igmpv3ReportReserved1Offset = 1
|
||||
igmpv3ReportReserved2Offset = 4
|
||||
igmpv3ReportNumberOfGroupAddressRecordsOffset = 6
|
||||
igmpv3ReportGroupAddressRecordsOffset = 8
|
||||
)
|
||||
|
||||
// IGMPv3ReportSerializer is an MLD Version 2 Report serializer.
|
||||
//
|
||||
// As per RFC 3810 section 5.2,
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 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
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Type = 143 | Reserved | Checksum |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Reserved |Nr of Mcast Address Records (M)|
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// . .
|
||||
// . Multicast Address Record [1] .
|
||||
// . .
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// . .
|
||||
// . Multicast Address Record [2] .
|
||||
// . .
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | . |
|
||||
// . . .
|
||||
// | . |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// . .
|
||||
// . Multicast Address Record [M] .
|
||||
// . .
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
type IGMPv3ReportSerializer struct {
|
||||
Records []IGMPv3ReportGroupAddressRecordSerializer
|
||||
}
|
||||
|
||||
// Length returns the number of bytes this serializer would occupy.
|
||||
func (s *IGMPv3ReportSerializer) Length() int {
|
||||
ret := igmpv3ReportGroupAddressRecordsOffset
|
||||
for _, record := range s.Records {
|
||||
ret += record.Length()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// SerializeInto serializes the report into the buffer.
|
||||
//
|
||||
// Panics if the buffer does not have enough space to fit the report.
|
||||
func (s *IGMPv3ReportSerializer) SerializeInto(b []byte) {
|
||||
b[igmpv3ReportTypeOffset] = byte(IGMPv3MembershipReport)
|
||||
b[igmpv3ReportReserved1Offset] = 0
|
||||
binary.BigEndian.PutUint16(b[igmpv3ReportReserved2Offset:], 0)
|
||||
binary.BigEndian.PutUint16(b[igmpv3ReportNumberOfGroupAddressRecordsOffset:], uint16(len(s.Records)))
|
||||
recordsBytes := b[igmpv3ReportGroupAddressRecordsOffset:]
|
||||
for _, record := range s.Records {
|
||||
len := record.Length()
|
||||
record.SerializeInto(recordsBytes[:len])
|
||||
recordsBytes = recordsBytes[len:]
|
||||
}
|
||||
binary.BigEndian.PutUint16(b[igmpChecksumOffset:], IGMPCalculateChecksum(b))
|
||||
}
|
||||
|
||||
// IGMPv3ReportGroupAddressRecord is an IGMPv3 record.
|
||||
//
|
||||
// As per RFC 3810 section 5.2, a Multicast Address Record has the following
|
||||
// internal format:
|
||||
//
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Record Type | Aux Data Len | Number of Sources (N) |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// * Multicast Address *
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// * Source Address [1] *
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// +- -+
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// * Source Address [2] *
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// +- -+
|
||||
// . . .
|
||||
// . . .
|
||||
// . . .
|
||||
// +- -+
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// * Source Address [N] *
|
||||
// | |
|
||||
// * *
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// . .
|
||||
// . Auxiliary Data .
|
||||
// . .
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
type IGMPv3ReportGroupAddressRecord []byte
|
||||
|
||||
// RecordType returns the type of this record.
|
||||
func (r IGMPv3ReportGroupAddressRecord) RecordType() IGMPv3ReportRecordType {
|
||||
return IGMPv3ReportRecordType(r[igmpv3ReportGroupAddressRecordTypeOffset])
|
||||
}
|
||||
|
||||
// AuxDataLen returns the length of the auxiliary data in this record.
|
||||
func (r IGMPv3ReportGroupAddressRecord) AuxDataLen() int {
|
||||
return int(r[igmpv3ReportGroupAddressRecordAuxDataLenOffset]) * igmpv3ReportGroupAddressRecordAuxDataLenUnits
|
||||
}
|
||||
|
||||
// numberOfSources returns the number of sources in this record.
|
||||
func (r IGMPv3ReportGroupAddressRecord) numberOfSources() uint16 {
|
||||
return binary.BigEndian.Uint16(r[igmpv3ReportGroupAddressRecordNumberOfSourcesOffset:])
|
||||
}
|
||||
|
||||
// GroupAddress returns the multicast address this record targets.
|
||||
func (r IGMPv3ReportGroupAddressRecord) GroupAddress() tcpip.Address {
|
||||
return tcpip.AddrFrom4([4]byte(r[igmpv3ReportGroupAddressRecordGroupAddressOffset:][:IPv4AddressSize]))
|
||||
}
|
||||
|
||||
// Sources returns an iterator over source addresses in the query.
|
||||
//
|
||||
// Returns false if the message cannot hold the expected number of sources.
|
||||
func (r IGMPv3ReportGroupAddressRecord) Sources() (AddressIterator, bool) {
|
||||
expectedLen := int(r.numberOfSources()) * IPv4AddressSize
|
||||
b := r[igmpv3ReportGroupAddressRecordSourcesOffset:]
|
||||
if len(b) < expectedLen {
|
||||
return AddressIterator{}, false
|
||||
}
|
||||
return AddressIterator{addressSize: IPv4AddressSize, buf: bytes.NewBuffer(b[:expectedLen])}, true
|
||||
}
|
||||
|
||||
// IGMPv3Report is an IGMPv3 Report.
|
||||
//
|
||||
// As per RFC 3810 section 5.2,
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 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
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Type = 143 | Reserved | Checksum |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Reserved |Nr of Mcast Address Records (M)|
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// . .
|
||||
// . Multicast Address Record [1] .
|
||||
// . .
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// . .
|
||||
// . Multicast Address Record [2] .
|
||||
// . .
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | . |
|
||||
// . . .
|
||||
// | . |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// . .
|
||||
// . Multicast Address Record [M] .
|
||||
// . .
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
type IGMPv3Report []byte
|
||||
|
||||
// Checksum returns the checksum.
|
||||
func (i IGMPv3Report) Checksum() uint16 {
|
||||
return binary.BigEndian.Uint16(i[igmpChecksumOffset:])
|
||||
}
|
||||
|
||||
// IGMPv3ReportGroupAddressRecordIterator is an iterator over IGMPv3 Multicast
|
||||
// Address Records.
|
||||
type IGMPv3ReportGroupAddressRecordIterator struct {
|
||||
recordsLeft uint16
|
||||
buf *bytes.Buffer
|
||||
}
|
||||
|
||||
// IGMPv3ReportGroupAddressRecordIteratorNextDisposition is the possible
|
||||
// return values from IGMPv3ReportGroupAddressRecordIterator.Next.
|
||||
type IGMPv3ReportGroupAddressRecordIteratorNextDisposition int
|
||||
|
||||
const (
|
||||
// IGMPv3ReportGroupAddressRecordIteratorNextOk indicates that a multicast
|
||||
// address record was yielded.
|
||||
IGMPv3ReportGroupAddressRecordIteratorNextOk IGMPv3ReportGroupAddressRecordIteratorNextDisposition = iota
|
||||
|
||||
// IGMPv3ReportGroupAddressRecordIteratorNextDone indicates that the iterator
|
||||
// has been exhausted.
|
||||
IGMPv3ReportGroupAddressRecordIteratorNextDone
|
||||
|
||||
// IGMPv3ReportGroupAddressRecordIteratorNextErrBufferTooShort indicates
|
||||
// that the iterator expected another record, but the buffer ended
|
||||
// prematurely.
|
||||
IGMPv3ReportGroupAddressRecordIteratorNextErrBufferTooShort
|
||||
)
|
||||
|
||||
// Next returns the next IGMPv3 Multicast Address Record.
|
||||
func (it *IGMPv3ReportGroupAddressRecordIterator) Next() (IGMPv3ReportGroupAddressRecord, IGMPv3ReportGroupAddressRecordIteratorNextDisposition) {
|
||||
if it.recordsLeft == 0 {
|
||||
return IGMPv3ReportGroupAddressRecord{}, IGMPv3ReportGroupAddressRecordIteratorNextDone
|
||||
}
|
||||
if it.buf.Len() < igmpv3ReportGroupAddressRecordMinimumSize {
|
||||
return IGMPv3ReportGroupAddressRecord{}, IGMPv3ReportGroupAddressRecordIteratorNextErrBufferTooShort
|
||||
}
|
||||
|
||||
hdr := IGMPv3ReportGroupAddressRecord(it.buf.Bytes())
|
||||
expectedLen := igmpv3ReportGroupAddressRecordMinimumSize +
|
||||
int(hdr.AuxDataLen()) + int(hdr.numberOfSources())*IPv4AddressSize
|
||||
|
||||
bytes := it.buf.Next(expectedLen)
|
||||
if len(bytes) < expectedLen {
|
||||
return IGMPv3ReportGroupAddressRecord{}, IGMPv3ReportGroupAddressRecordIteratorNextErrBufferTooShort
|
||||
}
|
||||
it.recordsLeft--
|
||||
return IGMPv3ReportGroupAddressRecord(bytes), IGMPv3ReportGroupAddressRecordIteratorNextOk
|
||||
}
|
||||
|
||||
// GroupAddressRecords returns an iterator of IGMPv3 Multicast Address
|
||||
// Records.
|
||||
func (i IGMPv3Report) GroupAddressRecords() IGMPv3ReportGroupAddressRecordIterator {
|
||||
return IGMPv3ReportGroupAddressRecordIterator{
|
||||
recordsLeft: binary.BigEndian.Uint16(i[igmpv3ReportNumberOfGroupAddressRecordsOffset:]),
|
||||
buf: bytes.NewBuffer(i[igmpv3ReportGroupAddressRecordsOffset:]),
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue