github.com/gopacket/gopacket@v1.1.0/layers/mldv2.go (about)

     1  // Copyright 2018 GoPacket Authors. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style license
     4  // that can be found in the LICENSE file in the root of the source
     5  // tree.
     6  
     7  package layers
     8  
     9  import (
    10  	"encoding/binary"
    11  	"errors"
    12  	"fmt"
    13  	"math"
    14  	"net"
    15  	"time"
    16  
    17  	"github.com/gopacket/gopacket"
    18  )
    19  
    20  const (
    21  	// S Flag bit is 1
    22  	mldv2STrue uint8 = 0x8
    23  
    24  	// S Flag value mask
    25  	//   mldv2STrue & mldv2SMask == mldv2STrue  // true
    26  	//          0x1 & mldv2SMask == mldv2STrue  // true
    27  	//          0x0 & mldv2SMask == mldv2STrue  // false
    28  	mldv2SMask uint8 = 0x8
    29  
    30  	// QRV value mask
    31  	mldv2QRVMask uint8 = 0x7
    32  )
    33  
    34  // MLDv2MulticastListenerQueryMessage are sent by multicast routers to query the
    35  // multicast listening state of neighboring interfaces.
    36  // https://tools.ietf.org/html/rfc3810#section-5.1
    37  //
    38  // Some information, like Maximum Response Code and Multicast Address are in the
    39  // previous layer LayerTypeMLDv1MulticastListenerQuery
    40  type MLDv2MulticastListenerQueryMessage struct {
    41  	BaseLayer
    42  	// 5.1.3. Maximum Response Delay COde
    43  	MaximumResponseCode uint16
    44  	// 5.1.5. Multicast Address
    45  	// Zero in general query
    46  	// Specific IPv6 multicast address otherwise
    47  	MulticastAddress net.IP
    48  	// 5.1.7. S Flag (Suppress Router-Side Processing)
    49  	SuppressRoutersideProcessing bool
    50  	// 5.1.8. QRV (Querier's Robustness Variable)
    51  	QueriersRobustnessVariable uint8
    52  	// 5.1.9. QQIC (Querier's Query Interval Code)
    53  	QueriersQueryIntervalCode uint8
    54  	// 5.1.10. Number of Sources (N)
    55  	NumberOfSources uint16
    56  	// 5.1.11 Source Address [i]
    57  	SourceAddresses []net.IP
    58  }
    59  
    60  // DecodeFromBytes decodes the given bytes into this layer.
    61  func (m *MLDv2MulticastListenerQueryMessage) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
    62  	if len(data) < 24 {
    63  		df.SetTruncated()
    64  		return errors.New("ICMP layer less than 24 bytes for Multicast Listener Query Message V2")
    65  	}
    66  
    67  	m.MaximumResponseCode = binary.BigEndian.Uint16(data[0:2])
    68  	// ignore data[2:4] as per https://tools.ietf.org/html/rfc3810#section-5.1.4
    69  	m.MulticastAddress = data[4:20]
    70  	m.SuppressRoutersideProcessing = (data[20] & mldv2SMask) == mldv2STrue
    71  	m.QueriersRobustnessVariable = data[20] & mldv2QRVMask
    72  	m.QueriersQueryIntervalCode = data[21]
    73  
    74  	m.NumberOfSources = binary.BigEndian.Uint16(data[22:24])
    75  
    76  	var end int
    77  	for i := uint16(0); i < m.NumberOfSources; i++ {
    78  		begin := 24 + (int(i) * 16)
    79  		end = begin + 16
    80  
    81  		if end > len(data) {
    82  			df.SetTruncated()
    83  			return fmt.Errorf("ICMP layer less than %d bytes for Multicast Listener Query Message V2", end)
    84  		}
    85  
    86  		m.SourceAddresses = append(m.SourceAddresses, data[begin:end])
    87  	}
    88  
    89  	return nil
    90  }
    91  
    92  // NextLayerType returns the layer type contained by this DecodingLayer.
    93  func (*MLDv2MulticastListenerQueryMessage) NextLayerType() gopacket.LayerType {
    94  	return gopacket.LayerTypeZero
    95  }
    96  
    97  // SerializeTo writes the serialized form of this layer into the
    98  // SerializationBuffer, implementing gopacket.SerializableLayer.
    99  // See the docs for gopacket.SerializableLayer for more info.
   100  func (m *MLDv2MulticastListenerQueryMessage) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   101  	if err := m.serializeSourceAddressesTo(b, opts); err != nil {
   102  		return err
   103  	}
   104  
   105  	buf, err := b.PrependBytes(24)
   106  	if err != nil {
   107  		return err
   108  	}
   109  
   110  	binary.BigEndian.PutUint16(buf[0:2], m.MaximumResponseCode)
   111  	copy(buf[2:4], []byte{0x00, 0x00}) // set reserved bytes to zero
   112  
   113  	ma16 := m.MulticastAddress.To16()
   114  	if ma16 == nil {
   115  		return fmt.Errorf("invalid MulticastAddress '%s'", m.MulticastAddress)
   116  	}
   117  	copy(buf[4:20], ma16)
   118  
   119  	byte20 := m.QueriersRobustnessVariable & mldv2QRVMask
   120  	if m.SuppressRoutersideProcessing {
   121  		byte20 |= mldv2STrue
   122  	} else {
   123  		byte20 &= ^mldv2STrue // the complement of mldv2STrue
   124  	}
   125  	byte20 &= 0x0F // set reserved bits to zero
   126  	buf[20] = byte20
   127  
   128  	binary.BigEndian.PutUint16(buf[22:24], m.NumberOfSources)
   129  	buf[21] = m.QueriersQueryIntervalCode
   130  
   131  	return nil
   132  }
   133  
   134  // writes each source address to the buffer preserving the order
   135  func (m *MLDv2MulticastListenerQueryMessage) serializeSourceAddressesTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   136  	numberOfSourceAddresses := len(m.SourceAddresses)
   137  	if numberOfSourceAddresses > math.MaxUint16 {
   138  		return fmt.Errorf(
   139  			"there are more than %d source addresses, but 65535 is the maximum number of supported addresses",
   140  			numberOfSourceAddresses)
   141  	}
   142  
   143  	if opts.FixLengths {
   144  		m.NumberOfSources = uint16(numberOfSourceAddresses)
   145  	}
   146  
   147  	lastSAIdx := numberOfSourceAddresses - 1
   148  	for k := range m.SourceAddresses {
   149  		i := lastSAIdx - k // reverse order
   150  
   151  		buf, err := b.PrependBytes(16)
   152  		if err != nil {
   153  			return err
   154  		}
   155  
   156  		sa16 := m.SourceAddresses[i].To16()
   157  		if sa16 == nil {
   158  			return fmt.Errorf("invalid source address [%d] '%s'", i, m.SourceAddresses[i])
   159  		}
   160  		copy(buf[0:16], sa16)
   161  	}
   162  
   163  	return nil
   164  }
   165  
   166  // String sums this layer up nicely formatted
   167  func (m *MLDv2MulticastListenerQueryMessage) String() string {
   168  	return fmt.Sprintf(
   169  		"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",
   170  		m.MaximumResponseCode,
   171  		m.MaximumResponseDelay(),
   172  		m.MulticastAddress,
   173  		m.SuppressRoutersideProcessing,
   174  		m.QueriersRobustnessVariable,
   175  		m.QueriersQueryIntervalCode,
   176  		m.QQI()/time.Second,
   177  		m.NumberOfSources,
   178  		len(m.SourceAddresses),
   179  		m.SourceAddresses)
   180  }
   181  
   182  // LayerType returns LayerTypeMLDv2MulticastListenerQuery.
   183  func (*MLDv2MulticastListenerQueryMessage) LayerType() gopacket.LayerType {
   184  	return LayerTypeMLDv2MulticastListenerQuery
   185  }
   186  
   187  // CanDecode returns the set of layer types that this DecodingLayer can decode.
   188  func (*MLDv2MulticastListenerQueryMessage) CanDecode() gopacket.LayerClass {
   189  	return LayerTypeMLDv2MulticastListenerQuery
   190  }
   191  
   192  // QQI calculates the Querier's Query Interval based on the QQIC
   193  // according to https://tools.ietf.org/html/rfc3810#section-5.1.9
   194  func (m *MLDv2MulticastListenerQueryMessage) QQI() time.Duration {
   195  	data := m.QueriersQueryIntervalCode
   196  	if data < 128 {
   197  		return time.Second * time.Duration(data)
   198  	}
   199  
   200  	exp := uint16(data) & 0x70 >> 4
   201  	mant := uint16(data) & 0x0F
   202  	return time.Second * time.Duration(mant|0x1000<<(exp+3))
   203  }
   204  
   205  // SetQQI calculates and updates the Querier's Query Interval Code (QQIC)
   206  // according to https://tools.ietf.org/html/rfc3810#section-5.1.9
   207  func (m *MLDv2MulticastListenerQueryMessage) SetQQI(d time.Duration) error {
   208  	if d < 0 {
   209  		m.QueriersQueryIntervalCode = 0
   210  		return errors.New("QQI duration is negative")
   211  	}
   212  
   213  	if d == 0 {
   214  		m.QueriersQueryIntervalCode = 0
   215  		return nil
   216  	}
   217  
   218  	dms := d / time.Second
   219  	if dms < 128 {
   220  		m.QueriersQueryIntervalCode = uint8(dms)
   221  	}
   222  
   223  	if dms > 31744 { // mant=0xF, exp=0x7
   224  		m.QueriersQueryIntervalCode = 0xFF
   225  		return fmt.Errorf("QQI duration %ds is, maximum allowed is 31744s", dms)
   226  	}
   227  
   228  	value := uint16(dms) // ok, because 31744 < math.MaxUint16
   229  	exp := uint8(7)
   230  	for mask := uint16(0x4000); exp > 0; exp-- {
   231  		if mask&value != 0 {
   232  			break
   233  		}
   234  
   235  		mask >>= 1
   236  	}
   237  
   238  	mant := uint8(0x000F & (value >> (exp + 3)))
   239  	sig := uint8(0x10)
   240  	m.QueriersQueryIntervalCode = sig | exp<<4 | mant
   241  
   242  	return nil
   243  }
   244  
   245  // MaximumResponseDelay returns the Maximum Response Delay based on the
   246  // Maximum Response Code according to
   247  // https://tools.ietf.org/html/rfc3810#section-5.1.3
   248  func (m *MLDv2MulticastListenerQueryMessage) MaximumResponseDelay() time.Duration {
   249  	if m.MaximumResponseCode < 0x8000 {
   250  		return time.Duration(m.MaximumResponseCode)
   251  	}
   252  
   253  	exp := m.MaximumResponseCode & 0x7000 >> 12
   254  	mant := m.MaximumResponseCode & 0x0FFF
   255  
   256  	return time.Millisecond * time.Duration(mant|0x1000<<(exp+3))
   257  }
   258  
   259  // SetMLDv2MaximumResponseDelay updates the Maximum Response Code according to
   260  // https://tools.ietf.org/html/rfc3810#section-5.1.3
   261  func (m *MLDv2MulticastListenerQueryMessage) SetMLDv2MaximumResponseDelay(d time.Duration) error {
   262  	if d == 0 {
   263  		m.MaximumResponseCode = 0
   264  		return nil
   265  	}
   266  
   267  	if d < 0 {
   268  		return errors.New("maximum response delay must not be negative")
   269  	}
   270  
   271  	dms := d / time.Millisecond
   272  
   273  	if dms < 32768 {
   274  		m.MaximumResponseCode = uint16(dms)
   275  	}
   276  
   277  	if dms > 4193280 { // mant=0xFFF, exp=0x7
   278  		return fmt.Errorf("maximum response delay %dms is bigger the than maximum of 4193280ms", dms)
   279  	}
   280  
   281  	value := uint32(dms) // ok, because 4193280 < math.MaxUint32
   282  	exp := uint8(7)
   283  	for mask := uint32(0x40000000); exp > 0; exp-- {
   284  		if mask&value != 0 {
   285  			break
   286  		}
   287  
   288  		mask >>= 1
   289  	}
   290  
   291  	mant := uint16(0x00000FFF & (value >> (exp + 3)))
   292  	sig := uint16(0x1000)
   293  	m.MaximumResponseCode = sig | uint16(exp)<<12 | mant
   294  	return nil
   295  }
   296  
   297  // MLDv2MulticastListenerReportMessage is sent by an IP node to report the
   298  // current multicast listening state, or changes therein.
   299  // https://tools.ietf.org/html/rfc3810#section-5.2
   300  type MLDv2MulticastListenerReportMessage struct {
   301  	BaseLayer
   302  	// 5.2.3. Nr of Mcast Address Records
   303  	NumberOfMulticastAddressRecords uint16
   304  	// 5.2.4. Multicast Address Record [i]
   305  	MulticastAddressRecords []MLDv2MulticastAddressRecord
   306  }
   307  
   308  // DecodeFromBytes decodes the given bytes into this layer.
   309  func (m *MLDv2MulticastListenerReportMessage) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   310  	if len(data) < 4 {
   311  		df.SetTruncated()
   312  		return errors.New("ICMP layer less than 4 bytes for Multicast Listener Report Message V2")
   313  	}
   314  
   315  	// ignore data[0:2] as per RFC
   316  	// https://tools.ietf.org/html/rfc3810#section-5.2.1
   317  	m.NumberOfMulticastAddressRecords = binary.BigEndian.Uint16(data[2:4])
   318  
   319  	begin := 4
   320  	for i := uint16(0); i < m.NumberOfMulticastAddressRecords; i++ {
   321  		mar := MLDv2MulticastAddressRecord{}
   322  		read, err := mar.decode(data[begin:], df)
   323  		if err != nil {
   324  			return err
   325  		}
   326  
   327  		m.MulticastAddressRecords = append(m.MulticastAddressRecords, mar)
   328  
   329  		begin += read
   330  	}
   331  
   332  	return nil
   333  }
   334  
   335  // SerializeTo writes the serialized form of this layer into the
   336  // SerializationBuffer, implementing gopacket.SerializableLayer.
   337  // See the docs for gopacket.SerializableLayer for more info.
   338  func (m *MLDv2MulticastListenerReportMessage) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   339  	lastItemIdx := len(m.MulticastAddressRecords) - 1
   340  	for k := range m.MulticastAddressRecords {
   341  		i := lastItemIdx - k // reverse order
   342  
   343  		err := m.MulticastAddressRecords[i].serializeTo(b, opts)
   344  		if err != nil {
   345  			return err
   346  		}
   347  	}
   348  
   349  	if opts.FixLengths {
   350  		numberOfMAR := len(m.MulticastAddressRecords)
   351  		if numberOfMAR > math.MaxUint16 {
   352  			return fmt.Errorf(
   353  				"%d multicast address records added, but the maximum is 65535",
   354  				numberOfMAR)
   355  		}
   356  
   357  		m.NumberOfMulticastAddressRecords = uint16(numberOfMAR)
   358  	}
   359  
   360  	buf, err := b.PrependBytes(4)
   361  	if err != nil {
   362  		return err
   363  	}
   364  
   365  	copy(buf[0:2], []byte{0x0, 0x0})
   366  	binary.BigEndian.PutUint16(buf[2:4], m.NumberOfMulticastAddressRecords)
   367  	return nil
   368  }
   369  
   370  // Sums this layer up nicely formatted
   371  func (m *MLDv2MulticastListenerReportMessage) String() string {
   372  	return fmt.Sprintf(
   373  		"Number of Mcast Addr Records: %d (actual %d), Multicast Address Records: %+v",
   374  		m.NumberOfMulticastAddressRecords,
   375  		len(m.MulticastAddressRecords),
   376  		m.MulticastAddressRecords)
   377  }
   378  
   379  // LayerType returns LayerTypeMLDv2MulticastListenerQuery.
   380  func (*MLDv2MulticastListenerReportMessage) LayerType() gopacket.LayerType {
   381  	return LayerTypeMLDv2MulticastListenerReport
   382  }
   383  
   384  // CanDecode returns the set of layer types that this DecodingLayer can decode.
   385  func (*MLDv2MulticastListenerReportMessage) CanDecode() gopacket.LayerClass {
   386  	return LayerTypeMLDv2MulticastListenerReport
   387  }
   388  
   389  // NextLayerType returns the layer type contained by this DecodingLayer.
   390  func (*MLDv2MulticastListenerReportMessage) NextLayerType() gopacket.LayerType {
   391  	return gopacket.LayerTypePayload
   392  }
   393  
   394  // MLDv2MulticastAddressRecordType holds the type of a
   395  // Multicast Address Record, according to
   396  // https://tools.ietf.org/html/rfc3810#section-5.2.5 and
   397  // https://tools.ietf.org/html/rfc3810#section-5.2.12
   398  type MLDv2MulticastAddressRecordType uint8
   399  
   400  const (
   401  	// MLDv2MulticastAddressRecordTypeModeIsIncluded stands for
   402  	// MODE_IS_INCLUDE - indicates that the interface has a filter
   403  	// mode of INCLUDE for the specified multicast address.
   404  	MLDv2MulticastAddressRecordTypeModeIsIncluded MLDv2MulticastAddressRecordType = 1
   405  	// MLDv2MulticastAddressRecordTypeModeIsExcluded stands for
   406  	// MODE_IS_EXCLUDE - indicates that the interface has a filter
   407  	// mode of EXCLUDE for the specified multicast address.
   408  	MLDv2MulticastAddressRecordTypeModeIsExcluded MLDv2MulticastAddressRecordType = 2
   409  	// MLDv2MulticastAddressRecordTypeChangeToIncludeMode stands for
   410  	// CHANGE_TO_INCLUDE_MODE - indicates that the interface has
   411  	// changed to INCLUDE filter mode for the specified multicast
   412  	// address.
   413  	MLDv2MulticastAddressRecordTypeChangeToIncludeMode MLDv2MulticastAddressRecordType = 3
   414  	// MLDv2MulticastAddressRecordTypeChangeToExcludeMode stands for
   415  	// CHANGE_TO_EXCLUDE_MODE - indicates that the interface has
   416  	// changed to EXCLUDE filter mode for the specified multicast
   417  	// address
   418  	MLDv2MulticastAddressRecordTypeChangeToExcludeMode MLDv2MulticastAddressRecordType = 4
   419  	// MLDv2MulticastAddressRecordTypeAllowNewSources stands for
   420  	// ALLOW_NEW_SOURCES - indicates that the Source Address [i]
   421  	// fields in this Multicast Address Record contain a list of
   422  	// the additional sources that the node wishes to listen to,
   423  	// for packets sent to the specified multicast address.
   424  	MLDv2MulticastAddressRecordTypeAllowNewSources MLDv2MulticastAddressRecordType = 5
   425  	// MLDv2MulticastAddressRecordTypeBlockOldSources stands for
   426  	// BLOCK_OLD_SOURCES - indicates that the Source Address [i]
   427  	// fields in this Multicast Address Record contain a list of
   428  	// the sources that the node no longer wishes to listen to,
   429  	// for packets sent to the specified multicast address.
   430  	MLDv2MulticastAddressRecordTypeBlockOldSources MLDv2MulticastAddressRecordType = 6
   431  )
   432  
   433  // Human readable record types
   434  // Naming follows https://tools.ietf.org/html/rfc3810#section-5.2.12
   435  func (m MLDv2MulticastAddressRecordType) String() string {
   436  	switch m {
   437  	case MLDv2MulticastAddressRecordTypeModeIsIncluded:
   438  		return "MODE_IS_INCLUDE"
   439  	case MLDv2MulticastAddressRecordTypeModeIsExcluded:
   440  		return "MODE_IS_EXCLUDE"
   441  	case MLDv2MulticastAddressRecordTypeChangeToIncludeMode:
   442  		return "CHANGE_TO_INCLUDE_MODE"
   443  	case MLDv2MulticastAddressRecordTypeChangeToExcludeMode:
   444  		return "CHANGE_TO_EXCLUDE_MODE"
   445  	case MLDv2MulticastAddressRecordTypeAllowNewSources:
   446  		return "ALLOW_NEW_SOURCES"
   447  	case MLDv2MulticastAddressRecordTypeBlockOldSources:
   448  		return "BLOCK_OLD_SOURCES"
   449  	default:
   450  		return fmt.Sprintf("UNKNOWN(%d)", m)
   451  	}
   452  }
   453  
   454  // MLDv2MulticastAddressRecord contains information on the sender listening to a
   455  // single multicast address on the interface the report is sent.
   456  // https://tools.ietf.org/html/rfc3810#section-5.2.4
   457  type MLDv2MulticastAddressRecord struct {
   458  	// 5.2.5. Record Type
   459  	RecordType MLDv2MulticastAddressRecordType
   460  	// 5.2.6. Auxiliary Data Length (number of 32-bit words)
   461  	AuxDataLen uint8
   462  	// 5.2.7. Number Of Sources (N)
   463  	N uint16
   464  	// 5.2.8. Multicast Address
   465  	MulticastAddress net.IP
   466  	// 5.2.9 Source Address [i]
   467  	SourceAddresses []net.IP
   468  	// 5.2.10 Auxiliary Data
   469  	AuxiliaryData []byte
   470  }
   471  
   472  // decodes a multicast address record from bytes
   473  func (m *MLDv2MulticastAddressRecord) decode(data []byte, df gopacket.DecodeFeedback) (int, error) {
   474  	if len(data) < 20 {
   475  		df.SetTruncated()
   476  		return 0, errors.New(
   477  			"Multicast Listener Report Message V2 layer less than 4 bytes for Multicast Address Record")
   478  	}
   479  
   480  	m.RecordType = MLDv2MulticastAddressRecordType(data[0])
   481  	m.AuxDataLen = data[1]
   482  	m.N = binary.BigEndian.Uint16(data[2:4])
   483  	m.MulticastAddress = data[4:20]
   484  
   485  	for i := uint16(0); i < m.N; i++ {
   486  		begin := 20 + (int(i) * 16)
   487  		end := begin + 16
   488  
   489  		if len(data) < end {
   490  			df.SetTruncated()
   491  			return begin, fmt.Errorf(
   492  				"Multicast Listener Report Message V2 layer less than %d bytes for Multicast Address Record", end)
   493  		}
   494  
   495  		m.SourceAddresses = append(m.SourceAddresses, data[begin:end])
   496  	}
   497  
   498  	expectedLengthWithouAuxData := 20 + (int(m.N) * 16)
   499  	expectedTotalLength := (int(m.AuxDataLen) * 4) + expectedLengthWithouAuxData // *4 because AuxDataLen are 32bit words
   500  	if len(data) < expectedTotalLength {
   501  		return expectedLengthWithouAuxData, fmt.Errorf(
   502  			"Multicast Listener Report Message V2 layer less than %d bytes for Multicast Address Record",
   503  			expectedLengthWithouAuxData)
   504  	}
   505  
   506  	m.AuxiliaryData = data[expectedLengthWithouAuxData:expectedTotalLength]
   507  
   508  	return expectedTotalLength, nil
   509  }
   510  
   511  // String sums this layer up nicely formatted
   512  func (m *MLDv2MulticastAddressRecord) String() string {
   513  	return fmt.Sprintf(
   514  		"RecordType: %d (%s), AuxDataLen: %d [32-bit words], N: %d, Multicast Address: %s, SourceAddresses: %s, Auxiliary Data: %#x",
   515  		m.RecordType,
   516  		m.RecordType.String(),
   517  		m.AuxDataLen,
   518  		m.N,
   519  		m.MulticastAddress.To16(),
   520  		m.SourceAddresses,
   521  		m.AuxiliaryData)
   522  }
   523  
   524  // serializes a multicast address record
   525  func (m *MLDv2MulticastAddressRecord) serializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   526  	if err := m.serializeAuxiliaryDataTo(b, opts); err != nil {
   527  		return err
   528  	}
   529  
   530  	if err := m.serializeSourceAddressesTo(b, opts); err != nil {
   531  		return err
   532  	}
   533  
   534  	buf, err := b.PrependBytes(20)
   535  	if err != nil {
   536  		return err
   537  	}
   538  
   539  	buf[0] = uint8(m.RecordType)
   540  	buf[1] = m.AuxDataLen
   541  	binary.BigEndian.PutUint16(buf[2:4], m.N)
   542  
   543  	ma16 := m.MulticastAddress.To16()
   544  	if ma16 == nil {
   545  		return fmt.Errorf("invalid multicast address '%s'", m.MulticastAddress)
   546  	}
   547  	copy(buf[4:20], ma16)
   548  
   549  	return nil
   550  }
   551  
   552  // serializes the auxiliary data of a multicast address record
   553  func (m *MLDv2MulticastAddressRecord) serializeAuxiliaryDataTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   554  	if remainder := len(m.AuxiliaryData) % 4; remainder != 0 {
   555  		zeroWord := []byte{0x0, 0x0, 0x0, 0x0}
   556  		m.AuxiliaryData = append(m.AuxiliaryData, zeroWord[:remainder]...)
   557  	}
   558  
   559  	if opts.FixLengths {
   560  		auxDataLen := len(m.AuxiliaryData) / 4
   561  
   562  		if auxDataLen > math.MaxUint8 {
   563  			return fmt.Errorf("auxilary data is %d 32-bit words, but the maximum is 255 32-bit words", auxDataLen)
   564  		}
   565  
   566  		m.AuxDataLen = uint8(auxDataLen)
   567  	}
   568  
   569  	buf, err := b.PrependBytes(len(m.AuxiliaryData))
   570  	if err != nil {
   571  		return err
   572  	}
   573  
   574  	copy(buf, m.AuxiliaryData)
   575  	return nil
   576  }
   577  
   578  // serializes the source addresses of a multicast address record preserving the order
   579  func (m *MLDv2MulticastAddressRecord) serializeSourceAddressesTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   580  	if opts.FixLengths {
   581  		numberOfSourceAddresses := len(m.SourceAddresses)
   582  
   583  		if numberOfSourceAddresses > math.MaxUint16 {
   584  			return fmt.Errorf(
   585  				"%d source addresses added, but the maximum is 65535",
   586  				numberOfSourceAddresses)
   587  		}
   588  
   589  		m.N = uint16(numberOfSourceAddresses)
   590  	}
   591  
   592  	lastItemIdx := len(m.SourceAddresses) - 1
   593  	for k := range m.SourceAddresses {
   594  		i := lastItemIdx - k // reverse order
   595  
   596  		buf, err := b.PrependBytes(16)
   597  		if err != nil {
   598  			return err
   599  		}
   600  
   601  		sa16 := m.SourceAddresses[i].To16()
   602  		if sa16 == nil {
   603  			return fmt.Errorf("invalid source address [%d] '%s'", i, m.SourceAddresses[i])
   604  		}
   605  		copy(buf, sa16)
   606  	}
   607  
   608  	return nil
   609  }
   610  
   611  func decodeMLDv2MulticastListenerReport(data []byte, p gopacket.PacketBuilder) error {
   612  	m := &MLDv2MulticastListenerReportMessage{}
   613  	return decodingLayerDecoder(m, data, p)
   614  }
   615  
   616  func decodeMLDv2MulticastListenerQuery(data []byte, p gopacket.PacketBuilder) error {
   617  	m := &MLDv2MulticastListenerQueryMessage{}
   618  	return decodingLayerDecoder(m, data, p)
   619  }