123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619 |
- package layers
- import (
- "encoding/binary"
- "errors"
- "fmt"
- "math"
- "net"
- "time"
- "github.com/google/gopacket"
- )
- const (
-
- mldv2STrue uint8 = 0x8
-
-
-
-
- mldv2SMask uint8 = 0x8
-
- mldv2QRVMask uint8 = 0x7
- )
- type MLDv2MulticastListenerQueryMessage struct {
- BaseLayer
-
- MaximumResponseCode uint16
-
-
-
- MulticastAddress net.IP
-
- SuppressRoutersideProcessing bool
-
- QueriersRobustnessVariable uint8
-
- QueriersQueryIntervalCode uint8
-
- NumberOfSources uint16
-
- SourceAddresses []net.IP
- }
- func (m *MLDv2MulticastListenerQueryMessage) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
- if len(data) < 24 {
- df.SetTruncated()
- return errors.New("ICMP layer less than 24 bytes for Multicast Listener Query Message V2")
- }
- m.MaximumResponseCode = binary.BigEndian.Uint16(data[0:2])
-
- m.MulticastAddress = data[4:20]
- m.SuppressRoutersideProcessing = (data[20] & mldv2SMask) == mldv2STrue
- m.QueriersRobustnessVariable = data[20] & mldv2QRVMask
- m.QueriersQueryIntervalCode = data[21]
- m.NumberOfSources = binary.BigEndian.Uint16(data[22:24])
- var end int
- for i := uint16(0); i < m.NumberOfSources; i++ {
- begin := 24 + (int(i) * 16)
- end = begin + 16
- if end > len(data) {
- df.SetTruncated()
- return fmt.Errorf("ICMP layer less than %d bytes for Multicast Listener Query Message V2", end)
- }
- m.SourceAddresses = append(m.SourceAddresses, data[begin:end])
- }
- return nil
- }
- func (*MLDv2MulticastListenerQueryMessage) NextLayerType() gopacket.LayerType {
- return gopacket.LayerTypeZero
- }
- func (m *MLDv2MulticastListenerQueryMessage) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
- if err := m.serializeSourceAddressesTo(b, opts); err != nil {
- return err
- }
- buf, err := b.PrependBytes(24)
- if err != nil {
- return err
- }
- binary.BigEndian.PutUint16(buf[0:2], m.MaximumResponseCode)
- copy(buf[2:4], []byte{0x00, 0x00})
- ma16 := m.MulticastAddress.To16()
- if ma16 == nil {
- return fmt.Errorf("invalid MulticastAddress '%s'", m.MulticastAddress)
- }
- copy(buf[4:20], ma16)
- byte20 := m.QueriersRobustnessVariable & mldv2QRVMask
- if m.SuppressRoutersideProcessing {
- byte20 |= mldv2STrue
- } else {
- byte20 &= ^mldv2STrue
- }
- byte20 &= 0x0F
- buf[20] = byte20
- binary.BigEndian.PutUint16(buf[22:24], m.NumberOfSources)
- buf[21] = m.QueriersQueryIntervalCode
- return nil
- }
- func (m *MLDv2MulticastListenerQueryMessage) serializeSourceAddressesTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
- numberOfSourceAddresses := len(m.SourceAddresses)
- if numberOfSourceAddresses > math.MaxUint16 {
- return fmt.Errorf(
- "there are more than %d source addresses, but 65535 is the maximum number of supported addresses",
- numberOfSourceAddresses)
- }
- if opts.FixLengths {
- m.NumberOfSources = uint16(numberOfSourceAddresses)
- }
- lastSAIdx := numberOfSourceAddresses - 1
- for k := range m.SourceAddresses {
- i := lastSAIdx - k
- buf, err := b.PrependBytes(16)
- if err != nil {
- return err
- }
- sa16 := m.SourceAddresses[i].To16()
- if sa16 == nil {
- return fmt.Errorf("invalid source address [%d] '%s'", i, m.SourceAddresses[i])
- }
- copy(buf[0:16], sa16)
- }
- return nil
- }
- func (m *MLDv2MulticastListenerQueryMessage) String() string {
- return fmt.Sprintf(
- "Maximum Response Code: %#x (%dms), Multicast Address: %s, Suppress Routerside Processing: %t, QRV: %#x, QQIC: %#x (%ds), Number of Source Address: %d (actual: %d), Source Addresses: %s",
- m.MaximumResponseCode,
- m.MaximumResponseDelay(),
- m.MulticastAddress,
- m.SuppressRoutersideProcessing,
- m.QueriersRobustnessVariable,
- m.QueriersQueryIntervalCode,
- m.QQI()/time.Second,
- m.NumberOfSources,
- len(m.SourceAddresses),
- m.SourceAddresses)
- }
- func (*MLDv2MulticastListenerQueryMessage) LayerType() gopacket.LayerType {
- return LayerTypeMLDv2MulticastListenerQuery
- }
- func (*MLDv2MulticastListenerQueryMessage) CanDecode() gopacket.LayerClass {
- return LayerTypeMLDv2MulticastListenerQuery
- }
- func (m *MLDv2MulticastListenerQueryMessage) QQI() time.Duration {
- data := m.QueriersQueryIntervalCode
- if data < 128 {
- return time.Second * time.Duration(data)
- }
- exp := uint16(data) & 0x70 >> 4
- mant := uint16(data) & 0x0F
- return time.Second * time.Duration(mant|0x1000<<(exp+3))
- }
- func (m *MLDv2MulticastListenerQueryMessage) SetQQI(d time.Duration) error {
- if d < 0 {
- m.QueriersQueryIntervalCode = 0
- return errors.New("QQI duration is negative")
- }
- if d == 0 {
- m.QueriersQueryIntervalCode = 0
- return nil
- }
- dms := d / time.Second
- if dms < 128 {
- m.QueriersQueryIntervalCode = uint8(dms)
- }
- if dms > 31744 {
- m.QueriersQueryIntervalCode = 0xFF
- return fmt.Errorf("QQI duration %ds is, maximum allowed is 31744s", dms)
- }
- value := uint16(dms)
- exp := uint8(7)
- for mask := uint16(0x4000); exp > 0; exp-- {
- if mask&value != 0 {
- break
- }
- mask >>= 1
- }
- mant := uint8(0x000F & (value >> (exp + 3)))
- sig := uint8(0x10)
- m.QueriersQueryIntervalCode = sig | exp<<4 | mant
- return nil
- }
- func (m *MLDv2MulticastListenerQueryMessage) MaximumResponseDelay() time.Duration {
- if m.MaximumResponseCode < 0x8000 {
- return time.Duration(m.MaximumResponseCode)
- }
- exp := m.MaximumResponseCode & 0x7000 >> 12
- mant := m.MaximumResponseCode & 0x0FFF
- return time.Millisecond * time.Duration(mant|0x1000<<(exp+3))
- }
- func (m *MLDv2MulticastListenerQueryMessage) SetMLDv2MaximumResponseDelay(d time.Duration) error {
- if d == 0 {
- m.MaximumResponseCode = 0
- return nil
- }
- if d < 0 {
- return errors.New("maximum response delay must not be negative")
- }
- dms := d / time.Millisecond
- if dms < 32768 {
- m.MaximumResponseCode = uint16(dms)
- }
- if dms > 4193280 {
- return fmt.Errorf("maximum response delay %dms is bigger the than maximum of 4193280ms", dms)
- }
- value := uint32(dms)
- exp := uint8(7)
- for mask := uint32(0x40000000); exp > 0; exp-- {
- if mask&value != 0 {
- break
- }
- mask >>= 1
- }
- mant := uint16(0x00000FFF & (value >> (exp + 3)))
- sig := uint16(0x1000)
- m.MaximumResponseCode = sig | uint16(exp)<<12 | mant
- return nil
- }
- type MLDv2MulticastListenerReportMessage struct {
- BaseLayer
-
- NumberOfMulticastAddressRecords uint16
-
- MulticastAddressRecords []MLDv2MulticastAddressRecord
- }
- func (m *MLDv2MulticastListenerReportMessage) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
- if len(data) < 4 {
- df.SetTruncated()
- return errors.New("ICMP layer less than 4 bytes for Multicast Listener Report Message V2")
- }
-
-
- m.NumberOfMulticastAddressRecords = binary.BigEndian.Uint16(data[2:4])
- begin := 4
- for i := uint16(0); i < m.NumberOfMulticastAddressRecords; i++ {
- mar := MLDv2MulticastAddressRecord{}
- read, err := mar.decode(data[begin:], df)
- if err != nil {
- return err
- }
- m.MulticastAddressRecords = append(m.MulticastAddressRecords, mar)
- begin += read
- }
- return nil
- }
- func (m *MLDv2MulticastListenerReportMessage) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
- lastItemIdx := len(m.MulticastAddressRecords) - 1
- for k := range m.MulticastAddressRecords {
- i := lastItemIdx - k
- err := m.MulticastAddressRecords[i].serializeTo(b, opts)
- if err != nil {
- return err
- }
- }
- if opts.FixLengths {
- numberOfMAR := len(m.MulticastAddressRecords)
- if numberOfMAR > math.MaxUint16 {
- return fmt.Errorf(
- "%d multicast address records added, but the maximum is 65535",
- numberOfMAR)
- }
- m.NumberOfMulticastAddressRecords = uint16(numberOfMAR)
- }
- buf, err := b.PrependBytes(4)
- if err != nil {
- return err
- }
- copy(buf[0:2], []byte{0x0, 0x0})
- binary.BigEndian.PutUint16(buf[2:4], m.NumberOfMulticastAddressRecords)
- return nil
- }
- func (m *MLDv2MulticastListenerReportMessage) String() string {
- return fmt.Sprintf(
- "Number of Mcast Addr Records: %d (actual %d), Multicast Address Records: %+v",
- m.NumberOfMulticastAddressRecords,
- len(m.MulticastAddressRecords),
- m.MulticastAddressRecords)
- }
- func (*MLDv2MulticastListenerReportMessage) LayerType() gopacket.LayerType {
- return LayerTypeMLDv2MulticastListenerReport
- }
- func (*MLDv2MulticastListenerReportMessage) CanDecode() gopacket.LayerClass {
- return LayerTypeMLDv2MulticastListenerReport
- }
- func (*MLDv2MulticastListenerReportMessage) NextLayerType() gopacket.LayerType {
- return gopacket.LayerTypePayload
- }
- type MLDv2MulticastAddressRecordType uint8
- const (
-
-
-
- MLDv2MulticastAddressRecordTypeModeIsIncluded MLDv2MulticastAddressRecordType = 1
-
-
-
- MLDv2MulticastAddressRecordTypeModeIsExcluded MLDv2MulticastAddressRecordType = 2
-
-
-
-
- MLDv2MulticastAddressRecordTypeChangeToIncludeMode MLDv2MulticastAddressRecordType = 3
-
-
-
-
- MLDv2MulticastAddressRecordTypeChangeToExcludeMode MLDv2MulticastAddressRecordType = 4
-
-
-
-
-
- MLDv2MulticastAddressRecordTypeAllowNewSources MLDv2MulticastAddressRecordType = 5
-
-
-
-
-
- MLDv2MulticastAddressRecordTypeBlockOldSources MLDv2MulticastAddressRecordType = 6
- )
- func (m MLDv2MulticastAddressRecordType) String() string {
- switch m {
- case MLDv2MulticastAddressRecordTypeModeIsIncluded:
- return "MODE_IS_INCLUDE"
- case MLDv2MulticastAddressRecordTypeModeIsExcluded:
- return "MODE_IS_EXCLUDE"
- case MLDv2MulticastAddressRecordTypeChangeToIncludeMode:
- return "CHANGE_TO_INCLUDE_MODE"
- case MLDv2MulticastAddressRecordTypeChangeToExcludeMode:
- return "CHANGE_TO_EXCLUDE_MODE"
- case MLDv2MulticastAddressRecordTypeAllowNewSources:
- return "ALLOW_NEW_SOURCES"
- case MLDv2MulticastAddressRecordTypeBlockOldSources:
- return "BLOCK_OLD_SOURCES"
- default:
- return fmt.Sprintf("UNKNOWN(%d)", m)
- }
- }
- type MLDv2MulticastAddressRecord struct {
-
- RecordType MLDv2MulticastAddressRecordType
-
- AuxDataLen uint8
-
- N uint16
-
- MulticastAddress net.IP
-
- SourceAddresses []net.IP
-
- AuxiliaryData []byte
- }
- func (m *MLDv2MulticastAddressRecord) decode(data []byte, df gopacket.DecodeFeedback) (int, error) {
- if len(data) < 4 {
- df.SetTruncated()
- return 0, errors.New(
- "Multicast Listener Report Message V2 layer less than 4 bytes for Multicast Address Record")
- }
- m.RecordType = MLDv2MulticastAddressRecordType(data[0])
- m.AuxDataLen = data[1]
- m.N = binary.BigEndian.Uint16(data[2:4])
- m.MulticastAddress = data[4:20]
- for i := uint16(0); i < m.N; i++ {
- begin := 20 + (int(i) * 16)
- end := begin + 16
- if len(data) < end {
- df.SetTruncated()
- return begin, fmt.Errorf(
- "Multicast Listener Report Message V2 layer less than %d bytes for Multicast Address Record", end)
- }
- m.SourceAddresses = append(m.SourceAddresses, data[begin:end])
- }
- expectedLengthWithouAuxData := 20 + (int(m.N) * 16)
- expectedTotalLength := (int(m.AuxDataLen) * 4) + expectedLengthWithouAuxData
- if len(data) < expectedTotalLength {
- return expectedLengthWithouAuxData, fmt.Errorf(
- "Multicast Listener Report Message V2 layer less than %d bytes for Multicast Address Record",
- expectedLengthWithouAuxData)
- }
- m.AuxiliaryData = data[expectedLengthWithouAuxData:expectedTotalLength]
- return expectedTotalLength, nil
- }
- func (m *MLDv2MulticastAddressRecord) String() string {
- return fmt.Sprintf(
- "RecordType: %d (%s), AuxDataLen: %d [32-bit words], N: %d, Multicast Address: %s, SourceAddresses: %s, Auxiliary Data: %#x",
- m.RecordType,
- m.RecordType.String(),
- m.AuxDataLen,
- m.N,
- m.MulticastAddress.To16(),
- m.SourceAddresses,
- m.AuxiliaryData)
- }
- func (m *MLDv2MulticastAddressRecord) serializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
- if err := m.serializeAuxiliaryDataTo(b, opts); err != nil {
- return err
- }
- if err := m.serializeSourceAddressesTo(b, opts); err != nil {
- return err
- }
- buf, err := b.PrependBytes(20)
- if err != nil {
- return err
- }
- buf[0] = uint8(m.RecordType)
- buf[1] = m.AuxDataLen
- binary.BigEndian.PutUint16(buf[2:4], m.N)
- ma16 := m.MulticastAddress.To16()
- if ma16 == nil {
- return fmt.Errorf("invalid multicast address '%s'", m.MulticastAddress)
- }
- copy(buf[4:20], ma16)
- return nil
- }
- func (m *MLDv2MulticastAddressRecord) serializeAuxiliaryDataTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
- if remainder := len(m.AuxiliaryData) % 4; remainder != 0 {
- zeroWord := []byte{0x0, 0x0, 0x0, 0x0}
- m.AuxiliaryData = append(m.AuxiliaryData, zeroWord[:remainder]...)
- }
- if opts.FixLengths {
- auxDataLen := len(m.AuxiliaryData) / 4
- if auxDataLen > math.MaxUint8 {
- return fmt.Errorf("auxilary data is %d 32-bit words, but the maximum is 255 32-bit words", auxDataLen)
- }
- m.AuxDataLen = uint8(auxDataLen)
- }
- buf, err := b.PrependBytes(len(m.AuxiliaryData))
- if err != nil {
- return err
- }
- copy(buf, m.AuxiliaryData)
- return nil
- }
- func (m *MLDv2MulticastAddressRecord) serializeSourceAddressesTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
- if opts.FixLengths {
- numberOfSourceAddresses := len(m.SourceAddresses)
- if numberOfSourceAddresses > math.MaxUint16 {
- return fmt.Errorf(
- "%d source addresses added, but the maximum is 65535",
- numberOfSourceAddresses)
- }
- m.N = uint16(numberOfSourceAddresses)
- }
- lastItemIdx := len(m.SourceAddresses) - 1
- for k := range m.SourceAddresses {
- i := lastItemIdx - k
- buf, err := b.PrependBytes(16)
- if err != nil {
- return err
- }
- sa16 := m.SourceAddresses[i].To16()
- if sa16 == nil {
- return fmt.Errorf("invalid source address [%d] '%s'", i, m.SourceAddresses[i])
- }
- copy(buf, sa16)
- }
- return nil
- }
- func decodeMLDv2MulticastListenerReport(data []byte, p gopacket.PacketBuilder) error {
- m := &MLDv2MulticastListenerReportMessage{}
- return decodingLayerDecoder(m, data, p)
- }
- func decodeMLDv2MulticastListenerQuery(data []byte, p gopacket.PacketBuilder) error {
- m := &MLDv2MulticastListenerQueryMessage{}
- return decodingLayerDecoder(m, data, p)
- }
|